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