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