2
* JB, the Jean-Yves Lefort's Build System
3
* Copyright (C) 2008 Jean-Yves Lefort <jylefort@brutele.be>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 3 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
#include "jb-variable.h"
26
#include "jb-compile-options.h"
28
#include "jb-feature.h"
31
jb_check_host_system (void)
34
gboolean status = FALSE;
36
if (jb_variable_get_variable("host-cpu") != NULL)
37
return; /* already checked */
39
jb_message_checking("the host system type");
41
if (jb_exec(&output, NULL, "jbsrc/tools/config.sub `jbsrc/tools/config.guess`"))
46
fields = g_strsplit(output, "-", 0);
47
len = g_strv_length(fields);
51
jb_variable_set_string("host-cpu", fields[0]);
52
jb_variable_set_string("host-manufacturer", fields[1]);
53
jb_variable_set_string("host-kernel", NULL);
54
jb_variable_set_string("host-os", fields[2]);
59
jb_variable_set_string("host-cpu", fields[0]);
60
jb_variable_set_string("host-manufacturer", fields[1]);
61
jb_variable_set_string("host-kernel", fields[2]);
62
jb_variable_set_string("host-os", fields[3]);
70
jb_message_result_string(output);
72
jb_message_result_string("unknown");
77
jb_error("unable to determine host system type");
81
jb_register_program (const char *name, JBVariableFlags flags)
86
g_return_if_fail(name != NULL);
88
description = g_strdup_printf("%s program", name);
90
program = g_find_program_in_path(name);
92
jb_variable_add_string(name,
94
jb_variable_group_external_programs,
102
/* the program must have been registered with jb_register_program() */
104
jb_check_program (const char *name)
106
static GHashTable *checked_programs = NULL;
107
JBVariable *variable;
109
gboolean result = FALSE;
111
g_return_val_if_fail(name != NULL, FALSE);
113
/* do not check for the same program twice */
114
if (checked_programs != NULL)
116
gpointer checked_result;
118
if (g_hash_table_lookup_extended(checked_programs, name, NULL, &checked_result))
119
return GPOINTER_TO_INT(checked_result);
122
checked_programs = g_hash_table_new(g_str_hash, g_str_equal);
124
jb_message_checking("for %s", name);
126
variable = jb_variable_get_variable_or_error(name);
128
program = g_value_get_string(&variable->value);
130
if (variable->user_set)
132
char *absolute_program;
134
absolute_program = g_find_program_in_path(program);
135
if (absolute_program != NULL)
137
jb_message_result_string(absolute_program);
138
g_value_take_string(&variable->value, absolute_program);
143
jb_message_result_string_format("not found (\"%s\" was specified but was not found, is a directory or is not executable)", program);
144
g_value_set_string(&variable->value, NULL);
151
jb_message_result_string(program);
155
jb_message_result_string("not found");
158
g_hash_table_insert(checked_programs, g_strdup(name), GINT_TO_POINTER(result));
164
jb_require_program (const char *name)
166
g_return_if_fail(name != NULL);
168
if (! jb_check_program(name))
169
jb_error("required program \"%s\" not found", name);
173
log_c_test (const char *filename, const char *action)
179
source = jb_read_file_or_exit(filename);
180
lines = g_strsplit(source, "\n", 0);
183
jb_log("attempting to %s program %s:", action, filename);
185
for (i = 0; lines[i] != NULL; i++)
187
const char *line = lines[i];
189
/* do not output a spurious empty last line */
190
if (*line == '\0' && lines[i + 1] == NULL)
193
jb_log("%4i %s", i + 1, lines[i]);
196
jb_log(JB_SEPARATOR);
202
jb_test_compile (const char *filename,
204
const char *cppflags)
206
g_return_val_if_fail(filename != NULL, FALSE);
208
log_c_test(filename, "compile");
210
return jb_exec_expand(NULL, NULL,
211
"$cc $cflags $extra-cflags"
212
" $cppflags $extra-cppflags"
213
" -o build/test.o -c $filename",
214
"extra-cflags", cflags,
215
"extra-cppflags", cppflags,
216
"filename", filename,
221
jb_test_link (const char *filename,
223
const char *cppflags,
226
g_return_val_if_fail(filename != NULL, FALSE);
228
log_c_test(filename, "link");
230
return jb_exec_expand(NULL, NULL,
231
"$cc $cflags $extra-cflags"
232
" $cppflags $extra-cppflags"
233
" $ldflags $extra-ldflags"
234
" -o build/test $filename",
235
"extra-cflags", cflags,
236
"extra-cppflags", cppflags,
237
"extra-ldflags", ldflags,
238
"filename", filename,
243
jb_test_run (const char *filename,
245
const char *cppflags,
248
if (! jb_test_link(filename, cflags, cppflags, ldflags))
251
return jb_exec(NULL, NULL, "build/test");
255
jb_check_functions (const char *functions, const char *libname)
257
char **functions_array;
259
GString *checking_message;
261
char *ldflags = NULL;
264
g_return_val_if_fail(functions != NULL, FALSE);
266
functions_array = g_strsplit(functions, " ", 0);
268
checking_message = g_string_new("for ");
270
for (i = 0; functions_array[i] != NULL; i++)
273
g_string_append_printf(checking_message, ", ");
275
g_string_append_printf(checking_message, "%s()", functions_array[i]);
279
g_string_append_printf(checking_message, " in -l%s", libname);
281
g_string_append(checking_message, " in libc");
283
jb_message_checking("%s", checking_message->str);
284
g_string_free(checking_message, TRUE);
286
program = g_string_new(NULL);
289
* Quoting c.m4 in autoconf: "Override any GCC internal prototype to
290
* avoid an error. Use char because int might match the return type
291
* of a GCC builtin and then its argument prototype would still
294
for (i = 0; functions_array[i] != NULL; i++)
295
g_string_append_printf(program, "char %s ();\n", functions_array[i]);
297
g_string_append(program, "int main () {");
299
for (i = 0; functions_array[i] != NULL; i++)
300
g_string_append_printf(program, " %s();", functions_array[i]);
302
g_string_append(program, " }\n");
304
jb_write_file_or_exit("build/test.c", program->str);
305
g_string_free(program, TRUE);
308
ldflags = g_strdup_printf("-l%s", libname);
309
result = jb_test_link("build/test.c", NULL, NULL, ldflags);
312
jb_message_result_bool(result);
318
jb_check_packages (const char *group_name,
319
const char *varprefix,
320
const char *packages)
322
char *quoted_packages;
324
char *ldflags = NULL;
328
g_return_val_if_fail(group_name != NULL, FALSE);
329
g_return_val_if_fail(varprefix != NULL, FALSE);
330
g_return_val_if_fail(packages != NULL, FALSE);
331
g_return_val_if_fail(jb_feature_is_enabled(&jb_pkg_config_feature), FALSE);
333
jb_require_program("pkg-config");
335
jb_message_checking("for %s", group_name);
337
quoted_packages = g_shell_quote(packages);
339
status = jb_exec_expand(&cflags, NULL, "$pkg-config --cflags $packages",
340
"packages", quoted_packages,
342
&& jb_exec_expand(&ldflags, NULL, "$pkg-config --libs $packages",
343
"packages", quoted_packages,
347
jb_variable_set_package_flags(varprefix,
352
jb_exec_expand(NULL, &error, "$pkg-config --print-errors $packages",
353
"packages", quoted_packages,
356
g_free(quoted_packages);
360
jb_message_result_bool(status);
364
jb_warning("%s", error);
372
* If one or more options (bool variables) in the provided
373
* NULL-terminated list are enabled, checks for the specified
374
* packages. If the packages are not found, disable the provided
378
jb_check_packages_for_options (const char *group_name,
379
const char *varprefix,
380
const char *packages,
383
GSList *options = NULL;
386
gboolean needs_packages = FALSE;
388
g_return_if_fail(group_name != NULL);
389
g_return_if_fail(varprefix != NULL);
390
g_return_if_fail(packages != NULL);
391
g_return_if_fail(jb_feature_is_enabled(&jb_pkg_config_feature));
393
va_start(args, packages);
394
while ((option = va_arg(args, const char *)) != NULL)
396
options = g_slist_append(options, (gpointer) option);
398
if (jb_variable_get_bool(option))
399
needs_packages = TRUE;
403
if (needs_packages && ! jb_check_packages(group_name, varprefix, packages))
407
JB_LIST_FOREACH(l, options)
411
if (jb_variable_get_bool(option))
413
jb_warning("disabling option \"%s\" since %s was not found", option, group_name);
414
jb_variable_set_bool(option, FALSE);
419
g_slist_free(options);
423
jb_require_packages (const char *group_name,
424
const char *varprefix,
425
const char *packages)
427
g_return_if_fail(group_name != NULL);
428
g_return_if_fail(varprefix != NULL);
429
g_return_if_fail(packages != NULL);
430
g_return_if_fail(jb_feature_is_enabled(&jb_pkg_config_feature));
432
if (! jb_check_packages(group_name, varprefix, packages))
433
jb_error("unable to find %s", group_name);
437
jb_get_package_variable (const char *package, const char *variable)
441
g_return_val_if_fail(package != NULL, NULL);
442
g_return_val_if_fail(variable != NULL, NULL);
443
g_return_val_if_fail(jb_feature_is_enabled(&jb_pkg_config_feature), FALSE);
445
jb_require_program("pkg-config");
447
if (! jb_exec_expand(&value, NULL, "$pkg-config --variable=$variable $package",
448
"variable", variable,
460
jb_check_cc_dependency_style (void)
462
if (! jb_variable_get_bool("cc-dependency-tracking"))
463
return; /* we don't need to know since we will not use it */
465
jb_message_checking("the C compiler dependency style");
467
jb_write_file_or_exit("build/test.c",
468
"#include <stdio.h>\n"
471
unlink("build/test.o");
472
unlink("build/test.o.deps");
474
if (jb_test_compile("build/test.c",
475
"-MT build/test.o -MD -MP -MF build/test.o.deps",
477
&& g_file_test("build/test.o", G_FILE_TEST_IS_REGULAR)
478
&& g_file_test("build/test.o.deps", G_FILE_TEST_IS_REGULAR))
479
jb_message_result_string("GCC");
482
jb_message_result_string("unknown, disabling dependency tracking");
483
jb_variable_set_bool("cc-dependency-tracking", FALSE);
492
return ((char *) &i)[sizeof(int) - 1] == 1;
496
jb_check_endianness (void)
498
jb_message_checking("the host CPU endianness");
501
jb_message_result_string("big-endian");
502
jb_compile_options_add_cppflags(&jb_compile_options, "-DWORDS_BIGENDIAN");
505
jb_message_result_string("little-endian");
509
check_reentrant_resolver_real (gboolean *result)
515
if (! strcmp(jb_variable_get_string("host-kernel"), "linux"))
521
os = jb_variable_get_string("host-os");
523
if (sscanf(os, "freebsd%d.%d", &freebsd_major, &freebsd_minor) == 2)
526
*result = (freebsd_major == 5 && freebsd_minor >= 3) || freebsd_major >= 6;
530
if (g_str_has_prefix(os, "netbsd") || g_str_has_prefix(os, "openbsd"))
536
return FALSE; /* unknown */
540
jb_check_reentrant_dns_resolver (void)
544
jb_check_host_system();
546
jb_message_checking("if the DNS resolver is reentrant");
548
if (check_reentrant_resolver_real(&result))
550
jb_message_result_bool(result);
552
jb_compile_options_add_cppflags(&jb_compile_options, "-DHAVE_REENTRANT_RESOLVER");
555
jb_message_result_string("unknown, assuming it is not");
559
jb_check_gnome_prefix (void)
563
prefix = jb_get_package_variable("libgnome-2.0", "prefix");
565
jb_message_checking("for the GNOME prefix");
568
jb_message_result_string(prefix);
570
jb_message_result_string("not found");
572
jb_variable_set_string("gnome-prefix", prefix);