1 """SCons.Conftest
2
3 Autoconf-like configuration support; low level implementation of tests.
4 """
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 import re
98 import string
99 from types import IntType
100
101
102
103
104
105 LogInputFiles = 1
106 LogErrorMessages = 1
107
108
109
110
111
112
113
114
115
116
117
119 """
120 Configure check to see if the compiler works.
121 Note that this uses the current value of compiler and linker flags, make
122 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
123 "language" should be "C" or "C++" and is used to select the compiler.
124 Default is "C".
125 "text" may be used to specify the code to be build.
126 Returns an empty string for success, an error message for failure.
127 """
128 lang, suffix, msg = _lang2suffix(language)
129 if msg:
130 context.Display("%s\n" % msg)
131 return msg
132
133 if not text:
134 text = """
135 int main() {
136 return 0;
137 }
138 """
139
140 context.Display("Checking if building a %s file works... " % lang)
141 ret = context.BuildProg(text, suffix)
142 _YesNoResult(context, ret, None, text)
143 return ret
144
146 """
147 Configure check for a working C compiler.
148
149 This checks whether the C compiler, as defined in the $CC construction
150 variable, can compile a C source file. It uses the current $CCCOM value
151 too, so that it can test against non working flags.
152
153 """
154 context.Display("Checking whether the C compiler works")
155 text = """
156 int main()
157 {
158 return 0;
159 }
160 """
161 ret = _check_empty_program(context, 'CC', text, 'C')
162 _YesNoResult(context, ret, None, text)
163 return ret
164
166 """
167 Configure check for a working shared C compiler.
168
169 This checks whether the C compiler, as defined in the $SHCC construction
170 variable, can compile a C source file. It uses the current $SHCCCOM value
171 too, so that it can test against non working flags.
172
173 """
174 context.Display("Checking whether the (shared) C compiler works")
175 text = """
176 int foo()
177 {
178 return 0;
179 }
180 """
181 ret = _check_empty_program(context, 'SHCC', text, 'C', use_shared = True)
182 _YesNoResult(context, ret, None, text)
183 return ret
184
186 """
187 Configure check for a working CXX compiler.
188
189 This checks whether the CXX compiler, as defined in the $CXX construction
190 variable, can compile a CXX source file. It uses the current $CXXCOM value
191 too, so that it can test against non working flags.
192
193 """
194 context.Display("Checking whether the C++ compiler works")
195 text = """
196 int main()
197 {
198 return 0;
199 }
200 """
201 ret = _check_empty_program(context, 'CXX', text, 'C++')
202 _YesNoResult(context, ret, None, text)
203 return ret
204
206 """
207 Configure check for a working shared CXX compiler.
208
209 This checks whether the CXX compiler, as defined in the $SHCXX construction
210 variable, can compile a CXX source file. It uses the current $SHCXXCOM value
211 too, so that it can test against non working flags.
212
213 """
214 context.Display("Checking whether the (shared) C++ compiler works")
215 text = """
216 int main()
217 {
218 return 0;
219 }
220 """
221 ret = _check_empty_program(context, 'SHCXX', text, 'C++', use_shared = True)
222 _YesNoResult(context, ret, None, text)
223 return ret
224
226 """Return 0 on success, 1 otherwise."""
227 if not context.env.has_key(comp) or not context.env[comp]:
228
229 return 1
230
231 lang, suffix, msg = _lang2suffix(language)
232 if msg:
233 return 1
234
235 if use_shared:
236 return context.CompileSharedObject(text, suffix)
237 else:
238 return context.CompileProg(text, suffix)
239
240
241 -def CheckFunc(context, function_name, header = None, language = None):
242 """
243 Configure check for a function "function_name".
244 "language" should be "C" or "C++" and is used to select the compiler.
245 Default is "C".
246 Optional "header" can be defined to define a function prototype, include a
247 header file or anything else that comes before main().
248 Sets HAVE_function_name in context.havedict according to the result.
249 Note that this uses the current value of compiler and linker flags, make
250 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
251 Returns an empty string for success, an error message for failure.
252 """
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 if context.headerfilename:
269 includetext = '#include "%s"' % context.headerfilename
270 else:
271 includetext = ''
272 if not header:
273 header = """
274 #ifdef __cplusplus
275 extern "C"
276 #endif
277 char %s();""" % function_name
278
279 lang, suffix, msg = _lang2suffix(language)
280 if msg:
281 context.Display("Cannot check for %s(): %s\n" % (function_name, msg))
282 return msg
283
284 text = """
285 %(include)s
286 #include <assert.h>
287 %(hdr)s
288
289 int main() {
290 #if defined (__stub_%(name)s) || defined (__stub___%(name)s)
291 fail fail fail
292 #else
293 %(name)s();
294 #endif
295
296 return 0;
297 }
298 """ % { 'name': function_name,
299 'include': includetext,
300 'hdr': header }
301
302 context.Display("Checking for %s function %s()... " % (lang, function_name))
303 ret = context.BuildProg(text, suffix)
304 _YesNoResult(context, ret, "HAVE_" + function_name, text,
305 "Define to 1 if the system has the function `%s'." %\
306 function_name)
307 return ret
308
309
312 """
313 Configure check for a C or C++ header file "header_name".
314 Optional "header" can be defined to do something before including the
315 header file (unusual, supported for consistency).
316 "language" should be "C" or "C++" and is used to select the compiler.
317 Default is "C".
318 Sets HAVE_header_name in context.havedict according to the result.
319 Note that this uses the current value of compiler and linker flags, make
320 sure $CFLAGS and $CPPFLAGS are set correctly.
321 Returns an empty string for success, an error message for failure.
322 """
323
324
325
326
327
328
329
330
331
332 if context.headerfilename:
333 includetext = '#include "%s"\n' % context.headerfilename
334 else:
335 includetext = ''
336 if not header:
337 header = ""
338
339 lang, suffix, msg = _lang2suffix(language)
340 if msg:
341 context.Display("Cannot check for header file %s: %s\n"
342 % (header_name, msg))
343 return msg
344
345 if not include_quotes:
346 include_quotes = "<>"
347
348 text = "%s%s\n#include %s%s%s\n\n" % (includetext, header,
349 include_quotes[0], header_name, include_quotes[1])
350
351 context.Display("Checking for %s header file %s... " % (lang, header_name))
352 ret = context.CompileProg(text, suffix)
353 _YesNoResult(context, ret, "HAVE_" + header_name, text,
354 "Define to 1 if you have the <%s> header file." % header_name)
355 return ret
356
357
358 -def CheckType(context, type_name, fallback = None,
359 header = None, language = None):
360 """
361 Configure check for a C or C++ type "type_name".
362 Optional "header" can be defined to include a header file.
363 "language" should be "C" or "C++" and is used to select the compiler.
364 Default is "C".
365 Sets HAVE_type_name in context.havedict according to the result.
366 Note that this uses the current value of compiler and linker flags, make
367 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
368 Returns an empty string for success, an error message for failure.
369 """
370
371
372 if context.headerfilename:
373 includetext = '#include "%s"' % context.headerfilename
374 else:
375 includetext = ''
376 if not header:
377 header = ""
378
379 lang, suffix, msg = _lang2suffix(language)
380 if msg:
381 context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
382 return msg
383
384
385
386
387
388
389
390
391
392
393
394
395 text = """
396 %(include)s
397 %(header)s
398
399 int main() {
400 if ((%(name)s *) 0)
401 return 0;
402 if (sizeof (%(name)s))
403 return 0;
404 }
405 """ % { 'include': includetext,
406 'header': header,
407 'name': type_name }
408
409 context.Display("Checking for %s type %s... " % (lang, type_name))
410 ret = context.BuildProg(text, suffix)
411 _YesNoResult(context, ret, "HAVE_" + type_name, text,
412 "Define to 1 if the system has the type `%s'." % type_name)
413 if ret and fallback and context.headerfilename:
414 f = open(context.headerfilename, "a")
415 f.write("typedef %s %s;\n" % (fallback, type_name))
416 f.close()
417
418 return ret
419
420 -def CheckTypeSize(context, type_name, header = None, language = None, expect = None):
421 """This check can be used to get the size of a given type, or to check whether
422 the type is of expected size.
423
424 Arguments:
425 - type : str
426 the type to check
427 - includes : sequence
428 list of headers to include in the test code before testing the type
429 - language : str
430 'C' or 'C++'
431 - expect : int
432 if given, will test wether the type has the given number of bytes.
433 If not given, will automatically find the size.
434
435 Returns:
436 status : int
437 0 if the check failed, or the found size of the type if the check succeeded."""
438
439
440 if context.headerfilename:
441 includetext = '#include "%s"' % context.headerfilename
442 else:
443 includetext = ''
444
445 if not header:
446 header = ""
447
448 lang, suffix, msg = _lang2suffix(language)
449 if msg:
450 context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
451 return msg
452
453 src = includetext + header
454 if not expect is None:
455
456 context.Display('Checking %s is %d bytes... ' % (type_name, expect))
457
458
459
460
461 src = src + r"""
462 typedef %s scons_check_type;
463
464 int main()
465 {
466 static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %d)];
467 test_array[0] = 0;
468
469 return 0;
470 }
471 """
472
473 st = context.CompileProg(src % (type_name, expect), suffix)
474 if not st:
475 context.Display("yes\n")
476 _Have(context, "SIZEOF_%s" % type_name, expect,
477 "The size of `%s', as computed by sizeof." % type_name)
478 return expect
479 else:
480 context.Display("no\n")
481 _LogFailed(context, src, st)
482 return 0
483 else:
484
485 context.Message('Checking size of %s ... ' % type_name)
486
487
488
489
490
491
492
493
494 src = src + """
495 #include <stdlib.h>
496 #include <stdio.h>
497 int main() {
498 printf("%d", (int)sizeof(""" + type_name + """));
499 return 0;
500 }
501 """
502 st, out = context.RunProg(src, suffix)
503 try:
504 size = int(out)
505 except ValueError:
506
507
508 st = 1
509 size = 0
510
511 if not st:
512 context.Display("yes\n")
513 _Have(context, "SIZEOF_%s" % type_name, size,
514 "The size of `%s', as computed by sizeof." % type_name)
515 return size
516 else:
517 context.Display("no\n")
518 _LogFailed(context, src, st)
519 return 0
520
521 return 0
522
524 """Checks whether symbol is declared.
525
526 Use the same test as autoconf, that is test whether the symbol is defined
527 as a macro or can be used as an r-value.
528
529 Arguments:
530 symbol : str
531 the symbol to check
532 includes : str
533 Optional "header" can be defined to include a header file.
534 language : str
535 only C and C++ supported.
536
537 Returns:
538 status : bool
539 True if the check failed, False if succeeded."""
540
541
542 if context.headerfilename:
543 includetext = '#include "%s"' % context.headerfilename
544 else:
545 includetext = ''
546
547 if not includes:
548 includes = ""
549
550 lang, suffix, msg = _lang2suffix(language)
551 if msg:
552 context.Display("Cannot check for declaration %s: %s\n" % (type_name, msg))
553 return msg
554
555 src = includetext + includes
556 context.Display('Checking whether %s is declared... ' % symbol)
557
558 src = src + r"""
559 int main()
560 {
561 #ifndef %s
562 (void) %s;
563 #endif
564 ;
565 return 0;
566 }
567 """ % (symbol, symbol)
568
569 st = context.CompileProg(src, suffix)
570 _YesNoResult(context, st, "HAVE_DECL_" + symbol, src,
571 "Set to 1 if %s is defined." % symbol)
572 return st
573
574 -def CheckLib(context, libs, func_name = None, header = None,
575 extra_libs = None, call = None, language = None, autoadd = 1):
576 """
577 Configure check for a C or C++ libraries "libs". Searches through
578 the list of libraries, until one is found where the test succeeds.
579 Tests if "func_name" or "call" exists in the library. Note: if it exists
580 in another library the test succeeds anyway!
581 Optional "header" can be defined to include a header file. If not given a
582 default prototype for "func_name" is added.
583 Optional "extra_libs" is a list of library names to be added after
584 "lib_name" in the build command. To be used for libraries that "lib_name"
585 depends on.
586 Optional "call" replaces the call to "func_name" in the test code. It must
587 consist of complete C statements, including a trailing ";".
588 Both "func_name" and "call" arguments are optional, and in that case, just
589 linking against the libs is tested.
590 "language" should be "C" or "C++" and is used to select the compiler.
591 Default is "C".
592 Note that this uses the current value of compiler and linker flags, make
593 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
594 Returns an empty string for success, an error message for failure.
595 """
596
597 if context.headerfilename:
598 includetext = '#include "%s"' % context.headerfilename
599 else:
600 includetext = ''
601 if not header:
602 header = ""
603
604 text = """
605 %s
606 %s""" % (includetext, header)
607
608
609 if func_name and func_name != "main":
610 if not header:
611 text = text + """
612 #ifdef __cplusplus
613 extern "C"
614 #endif
615 char %s();
616 """ % func_name
617
618
619 if not call:
620 call = "%s();" % func_name
621
622
623 text = text + """
624 int
625 main() {
626 %s
627 return 0;
628 }
629 """ % (call or "")
630
631 if call:
632 i = string.find(call, "\n")
633 if i > 0:
634 calltext = call[:i] + ".."
635 elif call[-1] == ';':
636 calltext = call[:-1]
637 else:
638 calltext = call
639
640 for lib_name in libs:
641
642 lang, suffix, msg = _lang2suffix(language)
643 if msg:
644 context.Display("Cannot check for library %s: %s\n" % (lib_name, msg))
645 return msg
646
647
648 if call:
649 context.Display("Checking for %s in %s library %s... "
650 % (calltext, lang, lib_name))
651
652 else:
653 context.Display("Checking for %s library %s... "
654 % (lang, lib_name))
655
656 if lib_name:
657 l = [ lib_name ]
658 if extra_libs:
659 l.extend(extra_libs)
660 oldLIBS = context.AppendLIBS(l)
661 sym = "HAVE_LIB" + lib_name
662 else:
663 oldLIBS = -1
664 sym = None
665
666 ret = context.BuildProg(text, suffix)
667
668 _YesNoResult(context, ret, sym, text,
669 "Define to 1 if you have the `%s' library." % lib_name)
670 if oldLIBS != -1 and (ret or not autoadd):
671 context.SetLIBS(oldLIBS)
672
673 if not ret:
674 return ret
675
676 return ret
677
678
679
680
681
683 """
684 Handle the result of a test with a "yes" or "no" result.
685 "ret" is the return value: empty if OK, error message when not.
686 "key" is the name of the symbol to be defined (HAVE_foo).
687 "text" is the source code of the program used for testing.
688 "comment" is the C comment to add above the line defining the symbol (the
689 comment is automatically put inside a /* */). If None, no comment is added.
690 """
691 if key:
692 _Have(context, key, not ret, comment)
693 if ret:
694 context.Display("no\n")
695 _LogFailed(context, text, ret)
696 else:
697 context.Display("yes\n")
698
699
700 -def _Have(context, key, have, comment = None):
701 """
702 Store result of a test in context.havedict and context.headerfilename.
703 "key" is a "HAVE_abc" name. It is turned into all CAPITALS and non-
704 alphanumerics are replaced by an underscore.
705 The value of "have" can be:
706 1 - Feature is defined, add "#define key".
707 0 - Feature is not defined, add "/* #undef key */".
708 Adding "undef" is what autoconf does. Not useful for the
709 compiler, but it shows that the test was done.
710 number - Feature is defined to this number "#define key have".
711 Doesn't work for 0 or 1, use a string then.
712 string - Feature is defined to this string "#define key have".
713 Give "have" as is should appear in the header file, include quotes
714 when desired and escape special characters!
715 """
716 key_up = string.upper(key)
717 key_up = re.sub('[^A-Z0-9_]', '_', key_up)
718 context.havedict[key_up] = have
719 if have == 1:
720 line = "#define %s 1\n" % key_up
721 elif have == 0:
722 line = "/* #undef %s */\n" % key_up
723 elif type(have) == IntType:
724 line = "#define %s %d\n" % (key_up, have)
725 else:
726 line = "#define %s %s\n" % (key_up, str(have))
727
728 if comment is not None:
729 lines = "\n/* %s */\n" % comment + line
730 else:
731 lines = "\n" + line
732
733 if context.headerfilename:
734 f = open(context.headerfilename, "a")
735 f.write(lines)
736 f.close()
737 elif hasattr(context,'config_h'):
738 context.config_h = context.config_h + lines
739
740
742 """
743 Write to the log about a failed program.
744 Add line numbers, so that error messages can be understood.
745 """
746 if LogInputFiles:
747 context.Log("Failed program was:\n")
748 lines = string.split(text, '\n')
749 if len(lines) and lines[-1] == '':
750 lines = lines[:-1]
751 n = 1
752 for line in lines:
753 context.Log("%d: %s\n" % (n, line))
754 n = n + 1
755 if LogErrorMessages:
756 context.Log("Error message: %s\n" % msg)
757
758
760 """
761 Convert a language name to a suffix.
762 When "lang" is empty or None C is assumed.
763 Returns a tuple (lang, suffix, None) when it works.
764 For an unrecognized language returns (None, None, msg).
765 Where:
766 lang = the unified language name
767 suffix = the suffix, including the leading dot
768 msg = an error message
769 """
770 if not lang or lang in ["C", "c"]:
771 return ("C", ".c", None)
772 if lang in ["c++", "C++", "cpp", "CXX", "cxx"]:
773 return ("C++", ".cpp", None)
774
775 return None, None, "Unsupported language: %s" % lang
776
777
778
779