~ubuntu-branches/debian/sid/link-monitor-applet/sid

« back to all changes in this revision

Viewing changes to jbsrc/lib/jb-tests.c

  • Committer: Bazaar Package Importer
  • Author(s): Adriaan Peeters
  • Date: 2008-03-30 22:26:13 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080330222613-5aubcuo9mgg2n7st
Tags: upstream-3.0
ImportĀ upstreamĀ versionĀ 3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * JB, the Jean-Yves Lefort's Build System
 
3
 * Copyright (C) 2008 Jean-Yves Lefort <jylefort@brutele.be>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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.
 
18
 */
 
19
 
 
20
#include <stdio.h>
 
21
#include <string.h>
 
22
#include <unistd.h>
 
23
#include <glib.h>
 
24
#include "jb-util.h"
 
25
#include "jb-variable.h"
 
26
#include "jb-compile-options.h"
 
27
#include "jb-tests.h"
 
28
#include "jb-feature.h"
 
29
 
 
30
void
 
31
jb_check_host_system (void)
 
32
{
 
33
  char *output;
 
34
  gboolean status = FALSE;
 
35
 
 
36
  if (jb_variable_get_variable("host-cpu") != NULL)
 
37
    return;                     /* already checked */
 
38
 
 
39
  jb_message_checking("the host system type");
 
40
 
 
41
  if (jb_exec(&output, NULL, "jbsrc/tools/config.sub `jbsrc/tools/config.guess`"))
 
42
    {
 
43
      char **fields;
 
44
      int len;
 
45
 
 
46
      fields = g_strsplit(output, "-", 0);
 
47
      len = g_strv_length(fields);
 
48
 
 
49
      if (len == 3)
 
50
        {
 
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]);
 
55
          status = TRUE;
 
56
        }
 
57
      else if (len == 4)
 
58
        {
 
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]);
 
63
          status = TRUE;
 
64
        }
 
65
 
 
66
      g_strfreev(fields);
 
67
    }
 
68
 
 
69
  if (status)
 
70
    jb_message_result_string(output);
 
71
  else
 
72
    jb_message_result_string("unknown");
 
73
 
 
74
  g_free(output);
 
75
 
 
76
  if (! status)
 
77
    jb_error("unable to determine host system type");
 
78
}
 
79
 
 
80
void
 
81
jb_register_program (const char *name, JBVariableFlags flags)
 
82
{
 
83
  char *description;
 
84
  char *program;
 
85
 
 
86
  g_return_if_fail(name != NULL);
 
87
 
 
88
  description = g_strdup_printf("%s program", name);
 
89
 
 
90
  program = g_find_program_in_path(name);
 
91
 
 
92
  jb_variable_add_string(name,
 
93
                         description,
 
94
                         jb_variable_group_external_programs,
 
95
                         flags,
 
96
                         program);
 
97
 
 
98
  g_free(description);
 
99
  g_free(program);
 
100
}
 
101
 
 
102
/* the program must have been registered with jb_register_program() */
 
103
gboolean
 
104
jb_check_program (const char *name)
 
105
{
 
106
  static GHashTable *checked_programs = NULL;
 
107
  JBVariable *variable;
 
108
  const char *program;
 
109
  gboolean result = FALSE;
 
110
 
 
111
  g_return_val_if_fail(name != NULL, FALSE);
 
112
 
 
113
  /* do not check for the same program twice */
 
114
  if (checked_programs != NULL)
 
115
    {
 
116
      gpointer checked_result;
 
117
 
 
118
      if (g_hash_table_lookup_extended(checked_programs, name, NULL, &checked_result))
 
119
        return GPOINTER_TO_INT(checked_result);
 
120
    }
 
121
  else
 
122
    checked_programs = g_hash_table_new(g_str_hash, g_str_equal);
 
123
 
 
124
  jb_message_checking("for %s", name);
 
125
 
 
126
  variable = jb_variable_get_variable_or_error(name);
 
127
 
 
128
  program = g_value_get_string(&variable->value);
 
129
 
 
130
  if (variable->user_set)
 
131
    {
 
132
      char *absolute_program;
 
133
 
 
134
      absolute_program = g_find_program_in_path(program);
 
135
      if (absolute_program != NULL)
 
136
        {
 
137
          jb_message_result_string(absolute_program);
 
138
          g_value_take_string(&variable->value, absolute_program);
 
139
          result = TRUE;
 
140
        }
 
141
      else
 
142
        {
 
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);
 
145
        }
 
146
    }
 
147
  else
 
148
    {
 
149
      if (program != NULL)
 
150
        {
 
151
          jb_message_result_string(program);
 
152
          result = TRUE;
 
153
        }
 
154
      else
 
155
        jb_message_result_string("not found");
 
156
    }
 
157
 
 
158
  g_hash_table_insert(checked_programs, g_strdup(name), GINT_TO_POINTER(result));
 
159
 
 
160
  return result;
 
161
}
 
162
 
 
163
void
 
164
jb_require_program (const char *name)
 
165
{
 
166
  g_return_if_fail(name != NULL);
 
167
 
 
168
  if (! jb_check_program(name))
 
169
    jb_error("required program \"%s\" not found", name);
 
170
}
 
171
 
 
172
static void
 
173
log_c_test (const char *filename, const char *action)
 
174
{
 
175
  char *source;
 
176
  char **lines;
 
177
  int i;
 
178
 
 
179
  source = jb_read_file_or_exit(filename);
 
180
  lines = g_strsplit(source, "\n", 0);
 
181
  g_free(source);
 
182
 
 
183
  jb_log("attempting to %s program %s:", action, filename);
 
184
 
 
185
  for (i = 0; lines[i] != NULL; i++)
 
186
    {
 
187
      const char *line = lines[i];
 
188
 
 
189
      /* do not output a spurious empty last line */
 
190
      if (*line == '\0' && lines[i + 1] == NULL)
 
191
        break;
 
192
 
 
193
      jb_log("%4i %s", i + 1, lines[i]);
 
194
    }
 
195
 
 
196
  jb_log(JB_SEPARATOR);
 
197
 
 
198
  g_strfreev(lines);
 
199
}
 
200
 
 
201
gboolean
 
202
jb_test_compile (const char *filename,
 
203
                 const char *cflags,
 
204
                 const char *cppflags)
 
205
{
 
206
  g_return_val_if_fail(filename != NULL, FALSE);
 
207
 
 
208
  log_c_test(filename, "compile");
 
209
 
 
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,
 
217
                        NULL);
 
218
}
 
219
 
 
220
gboolean
 
221
jb_test_link (const char *filename,
 
222
              const char *cflags,
 
223
              const char *cppflags,
 
224
              const char *ldflags)
 
225
{
 
226
  g_return_val_if_fail(filename != NULL, FALSE);
 
227
 
 
228
  log_c_test(filename, "link");
 
229
 
 
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,
 
239
                        NULL);
 
240
}
 
241
 
 
242
gboolean
 
243
jb_test_run (const char *filename,
 
244
             const char *cflags,
 
245
             const char *cppflags,
 
246
             const char *ldflags)
 
247
{
 
248
  if (! jb_test_link(filename, cflags, cppflags, ldflags))
 
249
    return FALSE;
 
250
 
 
251
  return jb_exec(NULL, NULL, "build/test");
 
252
}
 
253
 
 
254
gboolean
 
255
jb_check_functions (const char *functions, const char *libname)
 
256
{
 
257
  char **functions_array;
 
258
  int i;
 
259
  GString *checking_message;
 
260
  GString *program;
 
261
  char *ldflags = NULL;
 
262
  gboolean result;
 
263
 
 
264
  g_return_val_if_fail(functions != NULL, FALSE);
 
265
 
 
266
  functions_array = g_strsplit(functions, " ", 0);
 
267
 
 
268
  checking_message = g_string_new("for ");
 
269
 
 
270
  for (i = 0; functions_array[i] != NULL; i++)
 
271
    {
 
272
      if (i != 0)
 
273
        g_string_append_printf(checking_message, ", ");
 
274
 
 
275
      g_string_append_printf(checking_message, "%s()", functions_array[i]);
 
276
    }
 
277
 
 
278
  if (libname)
 
279
    g_string_append_printf(checking_message, " in -l%s", libname);
 
280
  else
 
281
    g_string_append(checking_message, " in libc");
 
282
 
 
283
  jb_message_checking("%s", checking_message->str);
 
284
  g_string_free(checking_message, TRUE);
 
285
 
 
286
  program = g_string_new(NULL);
 
287
 
 
288
  /*
 
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
 
292
   * apply."
 
293
   */
 
294
  for (i = 0; functions_array[i] != NULL; i++)
 
295
    g_string_append_printf(program, "char %s ();\n", functions_array[i]);
 
296
 
 
297
  g_string_append(program, "int main () {");
 
298
 
 
299
  for (i = 0; functions_array[i] != NULL; i++)
 
300
    g_string_append_printf(program, " %s();", functions_array[i]);
 
301
 
 
302
  g_string_append(program, " }\n");
 
303
 
 
304
  jb_write_file_or_exit("build/test.c", program->str);
 
305
  g_string_free(program, TRUE);
 
306
 
 
307
  if (libname)
 
308
    ldflags = g_strdup_printf("-l%s", libname);
 
309
  result = jb_test_link("build/test.c", NULL, NULL, ldflags);
 
310
  g_free(ldflags);
 
311
 
 
312
  jb_message_result_bool(result);
 
313
 
 
314
  return result;
 
315
}
 
316
 
 
317
gboolean
 
318
jb_check_packages (const char *group_name,
 
319
                   const char *varprefix,
 
320
                   const char *packages)
 
321
{
 
322
  char *quoted_packages;
 
323
  char *cflags = NULL;
 
324
  char *ldflags = NULL;
 
325
  char *error = NULL;
 
326
  gboolean status;
 
327
 
 
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);
 
332
 
 
333
  jb_require_program("pkg-config");
 
334
 
 
335
  jb_message_checking("for %s", group_name);
 
336
 
 
337
  quoted_packages = g_shell_quote(packages);
 
338
 
 
339
  status = jb_exec_expand(&cflags, NULL, "$pkg-config --cflags $packages",
 
340
                          "packages", quoted_packages,
 
341
                          NULL)
 
342
    && jb_exec_expand(&ldflags, NULL, "$pkg-config --libs $packages",
 
343
                      "packages", quoted_packages,
 
344
                      NULL);
 
345
 
 
346
  if (status)
 
347
    jb_variable_set_package_flags(varprefix,
 
348
                                  cflags,
 
349
                                  NULL,
 
350
                                  ldflags);
 
351
  else
 
352
    jb_exec_expand(NULL, &error, "$pkg-config --print-errors $packages",
 
353
                   "packages", quoted_packages,
 
354
                   NULL);
 
355
 
 
356
  g_free(quoted_packages);
 
357
  g_free(cflags);
 
358
  g_free(ldflags);
 
359
 
 
360
  jb_message_result_bool(status);
 
361
 
 
362
  if (error != NULL)
 
363
    {
 
364
      jb_warning("%s", error);
 
365
      g_free(error);
 
366
    }
 
367
 
 
368
  return status;
 
369
}
 
370
 
 
371
/*
 
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
 
375
 * options.
 
376
 */
 
377
void
 
378
jb_check_packages_for_options (const char *group_name,
 
379
                               const char *varprefix,
 
380
                               const char *packages,
 
381
                               ...)
 
382
{
 
383
  GSList *options = NULL;
 
384
  va_list args;
 
385
  const char *option;
 
386
  gboolean needs_packages = FALSE;
 
387
 
 
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));
 
392
 
 
393
  va_start(args, packages);
 
394
  while ((option = va_arg(args, const char *)) != NULL)
 
395
    {
 
396
      options = g_slist_append(options, (gpointer) option);
 
397
 
 
398
      if (jb_variable_get_bool(option))
 
399
        needs_packages = TRUE;
 
400
    }
 
401
  va_end(args);
 
402
 
 
403
  if (needs_packages && ! jb_check_packages(group_name, varprefix, packages))
 
404
    {
 
405
      GSList *l;
 
406
 
 
407
      JB_LIST_FOREACH(l, options)
 
408
        {
 
409
          option = l->data;
 
410
 
 
411
          if (jb_variable_get_bool(option))
 
412
            {
 
413
              jb_warning("disabling option \"%s\" since %s was not found", option, group_name);
 
414
              jb_variable_set_bool(option, FALSE);
 
415
            }
 
416
        }
 
417
    }
 
418
 
 
419
  g_slist_free(options);
 
420
}
 
421
 
 
422
void
 
423
jb_require_packages (const char *group_name,
 
424
                     const char *varprefix,
 
425
                     const char *packages)
 
426
{
 
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));
 
431
 
 
432
  if (! jb_check_packages(group_name, varprefix, packages))
 
433
    jb_error("unable to find %s", group_name);
 
434
}
 
435
 
 
436
char *
 
437
jb_get_package_variable (const char *package, const char *variable)
 
438
{
 
439
  char *value;
 
440
 
 
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);
 
444
 
 
445
  jb_require_program("pkg-config");
 
446
 
 
447
  if (! jb_exec_expand(&value, NULL, "$pkg-config --variable=$variable $package",
 
448
                       "variable", variable,
 
449
                       "package", package,
 
450
                       NULL))
 
451
    {
 
452
      g_free(value);
 
453
      value = NULL;
 
454
    }
 
455
 
 
456
  return value;
 
457
}
 
458
 
 
459
void
 
460
jb_check_cc_dependency_style (void)
 
461
{
 
462
  if (! jb_variable_get_bool("cc-dependency-tracking"))
 
463
    return; /* we don't need to know since we will not use it */
 
464
 
 
465
  jb_message_checking("the C compiler dependency style");
 
466
 
 
467
  jb_write_file_or_exit("build/test.c",
 
468
                        "#include <stdio.h>\n"
 
469
                        "int main () {}\n");
 
470
 
 
471
  unlink("build/test.o");
 
472
  unlink("build/test.o.deps");
 
473
 
 
474
  if (jb_test_compile("build/test.c",
 
475
                      "-MT build/test.o -MD -MP -MF build/test.o.deps",
 
476
                      NULL)
 
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");
 
480
  else
 
481
    {
 
482
      jb_message_result_string("unknown, disabling dependency tracking");
 
483
      jb_variable_set_bool("cc-dependency-tracking", FALSE);
 
484
    }
 
485
}
 
486
 
 
487
static gboolean
 
488
is_bigendian (void)
 
489
{
 
490
  int i = 1;
 
491
 
 
492
  return ((char *) &i)[sizeof(int) - 1] == 1;
 
493
}
 
494
 
 
495
void
 
496
jb_check_endianness (void)
 
497
{
 
498
  jb_message_checking("the host CPU endianness");
 
499
  if (is_bigendian())
 
500
    {
 
501
      jb_message_result_string("big-endian");
 
502
      jb_compile_options_add_cppflags(&jb_compile_options, "-DWORDS_BIGENDIAN");
 
503
    }
 
504
  else
 
505
    jb_message_result_string("little-endian");
 
506
}
 
507
 
 
508
static gboolean
 
509
check_reentrant_resolver_real (gboolean *result)
 
510
{
 
511
  const char *os;
 
512
  int freebsd_major;
 
513
  int freebsd_minor;
 
514
 
 
515
  if (! strcmp(jb_variable_get_string("host-kernel"), "linux"))
 
516
    {
 
517
      *result = TRUE;
 
518
      return TRUE;
 
519
    }
 
520
 
 
521
  os = jb_variable_get_string("host-os");
 
522
 
 
523
  if (sscanf(os, "freebsd%d.%d", &freebsd_major, &freebsd_minor) == 2)
 
524
    {
 
525
      /* FreeBSD >= 5.3 */
 
526
      *result = (freebsd_major == 5 && freebsd_minor >= 3) || freebsd_major >= 6;
 
527
      return TRUE;
 
528
    }
 
529
 
 
530
  if (g_str_has_prefix(os, "netbsd") || g_str_has_prefix(os, "openbsd"))
 
531
    {
 
532
      *result = FALSE;
 
533
      return TRUE;
 
534
    }
 
535
 
 
536
  return FALSE;                 /* unknown */
 
537
}
 
538
 
 
539
void
 
540
jb_check_reentrant_dns_resolver (void)
 
541
{
 
542
  gboolean result;
 
543
 
 
544
  jb_check_host_system();
 
545
 
 
546
  jb_message_checking("if the DNS resolver is reentrant");
 
547
 
 
548
  if (check_reentrant_resolver_real(&result))
 
549
    {
 
550
      jb_message_result_bool(result);
 
551
      if (result)
 
552
        jb_compile_options_add_cppflags(&jb_compile_options, "-DHAVE_REENTRANT_RESOLVER");
 
553
    }
 
554
  else
 
555
    jb_message_result_string("unknown, assuming it is not");
 
556
}
 
557
 
 
558
void
 
559
jb_check_gnome_prefix (void)
 
560
{
 
561
  char *prefix;
 
562
 
 
563
  prefix = jb_get_package_variable("libgnome-2.0", "prefix");
 
564
 
 
565
  jb_message_checking("for the GNOME prefix");
 
566
 
 
567
  if (prefix != NULL)
 
568
    jb_message_result_string(prefix);
 
569
  else
 
570
    jb_message_result_string("not found");
 
571
 
 
572
  jb_variable_set_string("gnome-prefix", prefix);
 
573
}