3 Autoconf-like configuration support; low level implementation of tests.
7 # Copyright (c) 2003 Stichting NLnet Labs
8 # Copyright (c) 2001, 2002, 2003 Steven Knight
10 # Permission is hereby granted, free of charge, to any person obtaining
11 # a copy of this software and associated documentation files (the
12 # "Software"), to deal in the Software without restriction, including
13 # without limitation the rights to use, copy, modify, merge, publish,
14 # distribute, sublicense, and/or sell copies of the Software, and to
15 # permit persons to whom the Software is furnished to do so, subject to
16 # the following conditions:
18 # The above copyright notice and this permission notice shall be included
19 # in all copies or substantial portions of the Software.
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 # The purpose of this module is to define how a check is to be performed.
32 # Use one of the Check...() functions below.
36 # A context class is used that defines functions for carrying out the tests,
37 # logging and messages. The following methods and members must be present:
39 # context.Display(msg) Function called to print messages that are normally
40 # displayed for the user. Newlines are explicitly used.
41 # The text should also be written to the logfile!
43 # context.Log(msg) Function called to write to a log file.
45 # context.BuildProg(text, ext)
46 # Function called to build a program, using "ext" for the
47 # file extention. Must return an empty string for
48 # success, an error message for failure.
49 # For reliable test results building should be done just
50 # like an actual program would be build, using the same
51 # command and arguments (including configure results so
54 # context.CompileProg(text, ext)
55 # Function called to compile a program, using "ext" for
56 # the file extention. Must return an empty string for
57 # success, an error message for failure.
58 # For reliable test results compiling should be done just
59 # like an actual source file would be compiled, using the
60 # same command and arguments (including configure results
63 # context.AppendLIBS(lib_name_list)
64 # Append "lib_name_list" to the value of LIBS.
65 # "lib_namelist" is a list of strings.
66 # Return the value of LIBS before changing it (any type
67 # can be used, it is passed to SetLIBS() later.
69 # context.SetLIBS(value)
70 # Set LIBS to "value". The type of "value" is what
71 # AppendLIBS() returned.
72 # Return the value of LIBS before changing it (any type
73 # can be used, it is passed to SetLIBS() later.
75 # context.headerfilename
76 # Name of file to append configure results to, usually
78 # The file must not exist or be empty when starting.
79 # Empty or None to skip this (some tests will not work!).
81 # context.config_h (may be missing). If present, must be a string, which
82 # will be filled with the contents of a config_h file.
84 # context.vardict Dictionary holding variables used for the tests and
85 # stores results from the tests, used for the build
87 # Normally contains "CC", "LIBS", "CPPFLAGS", etc.
89 # context.havedict Dictionary holding results from the tests that are to
90 # be used inside a program.
91 # Names often start with "HAVE_". These are zero
92 # (feature not present) or one (feature present). Other
93 # variables may have any value, e.g., "PERLVERSION" can
94 # be a number and "SYSTEMNAME" a string.
99 from types import IntType
105 LogInputFiles = 1 # Set that to log the input files in case of a failed test
106 LogErrorMessages = 1 # Set that to log Conftest-generated error messages
113 # - When a language is specified which is not supported the test fails. The
114 # message is a bit different, because not all the arguments for the normal
115 # message are available yet (chicken-egg problem).
118 def CheckBuilder(context, text = None, language = None):
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.
125 "text" may be used to specify the code to be build.
126 Returns an empty string for success, an error message for failure.
128 lang, suffix, msg = _lang2suffix(language)
130 context.Display("%s\n" % msg)
140 context.Display("Checking if building a %s file works... " % lang)
141 ret = context.BuildProg(text, suffix)
142 _YesNoResult(context, ret, None, text)
145 def CheckCC(context):
147 Configure check for a working C compiler.
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.
154 context.Display("Checking whether the C compiler works")
161 ret = _check_empty_program(context, 'CC', text, 'C')
162 _YesNoResult(context, ret, None, text)
165 def CheckSHCC(context):
167 Configure check for a working shared C compiler.
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.
174 context.Display("Checking whether the (shared) C compiler works")
181 ret = _check_empty_program(context, 'SHCC', text, 'C', use_shared = True)
182 _YesNoResult(context, ret, None, text)
185 def CheckCXX(context):
187 Configure check for a working CXX compiler.
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.
194 context.Display("Checking whether the C++ compiler works")
201 ret = _check_empty_program(context, 'CXX', text, 'C++')
202 _YesNoResult(context, ret, None, text)
205 def CheckSHCXX(context):
207 Configure check for a working shared CXX compiler.
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.
214 context.Display("Checking whether the (shared) C++ compiler works")
221 ret = _check_empty_program(context, 'SHCXX', text, 'C++', use_shared = True)
222 _YesNoResult(context, ret, None, text)
225 def _check_empty_program(context, comp, text, language, use_shared = False):
226 """Return 0 on success, 1 otherwise."""
227 if not context.env.has_key(comp) or not context.env[comp]:
228 # The compiler construction variable is not set or empty
231 lang, suffix, msg = _lang2suffix(language)
236 return context.CompileSharedObject(text, suffix)
238 return context.CompileProg(text, suffix)
241 def CheckFunc(context, function_name, header = None, language = None):
243 Configure check for a function "function_name".
244 "language" should be "C" or "C++" and is used to select the compiler.
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.
254 # Remarks from autoconf:
255 # - Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h>
256 # which includes <sys/select.h> which contains a prototype for select.
257 # Similarly for bzero.
258 # - assert.h is included to define __stub macros and hopefully few
259 # prototypes, which can conflict with char $1(); below.
260 # - Override any gcc2 internal prototype to avoid an error.
261 # - We use char for the function declaration because int might match the
262 # return type of a gcc2 builtin and then its argument prototype would
264 # - The GNU C library defines this for functions which it implements to
265 # always fail with ENOSYS. Some functions are actually named something
266 # starting with __ and the normal name is an alias.
268 if context.headerfilename:
269 includetext = '#include "%s"' % context.headerfilename
277 char %s();""" % function_name
279 lang, suffix, msg = _lang2suffix(language)
281 context.Display("Cannot check for %s(): %s\n" % (function_name, msg))
290 #if defined (__stub_%(name)s) || defined (__stub___%(name)s)
298 """ % { 'name': function_name,
299 'include': includetext,
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'." %\
310 def CheckHeader(context, header_name, header = None, language = None,
311 include_quotes = None):
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.
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.
323 # Why compile the program instead of just running the preprocessor?
324 # It is possible that the header file exists, but actually using it may
325 # fail (e.g., because it depends on other header files). Thus this test is
326 # more strict. It may require using the "header" argument.
328 # Use <> by default, because the check is normally used for system header
329 # files. SCons passes '""' to overrule this.
331 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
332 if context.headerfilename:
333 includetext = '#include "%s"\n' % context.headerfilename
339 lang, suffix, msg = _lang2suffix(language)
341 context.Display("Cannot check for header file %s: %s\n"
342 % (header_name, msg))
345 if not include_quotes:
346 include_quotes = "<>"
348 text = "%s%s\n#include %s%s%s\n\n" % (includetext, header,
349 include_quotes[0], header_name, include_quotes[1])
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)
358 def CheckType(context, type_name, fallback = None,
359 header = None, language = None):
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.
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.
371 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
372 if context.headerfilename:
373 includetext = '#include "%s"' % context.headerfilename
379 lang, suffix, msg = _lang2suffix(language)
381 context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
384 # Remarks from autoconf about this test:
385 # - Grepping for the type in include files is not reliable (grep isn't
387 # - Using "TYPE my_var;" doesn't work for const qualified types in C++.
388 # Adding an initializer is not valid for some C++ classes.
389 # - Using the type as parameter to a function either fails for K&$ C or for
391 # - Using "TYPE *my_var;" is valid in C for some types that are not
392 # declared (struct something).
393 # - Using "sizeof(TYPE)" is valid when TYPE is actually a variable.
394 # - Using the previous two together works reliably.
402 if (sizeof (%(name)s))
405 """ % { 'include': includetext,
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))
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.
427 - includes : sequence
428 list of headers to include in the test code before testing the type
432 if given, will test wether the type has the given number of bytes.
433 If not given, will automatically find the size.
437 0 if the check failed, or the found size of the type if the check succeeded."""
439 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
440 if context.headerfilename:
441 includetext = '#include "%s"' % context.headerfilename
448 lang, suffix, msg = _lang2suffix(language)
450 context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
453 src = includetext + header
454 if not expect is None:
455 # Only check if the given size is the right one
456 context.Display('Checking %s is %d bytes... ' % (type_name, expect))
458 # test code taken from autoconf: this is a pretty clever hack to find that
459 # a type is of a given size using only compilation. This speeds things up
460 # quite a bit compared to straightforward code using TryRun
462 typedef %s scons_check_type;
466 static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %d)];
473 st = context.CompileProg(src % (type_name, expect), suffix)
475 context.Display("yes\n")
476 _Have(context, "SIZEOF_%s" % type_name, expect,
477 "The size of `%s', as computed by sizeof." % type_name)
480 context.Display("no\n")
481 _LogFailed(context, src, st)
484 # Only check if the given size is the right one
485 context.Message('Checking size of %s ... ' % type_name)
487 # We have to be careful with the program we wish to test here since
488 # compilation will be attempted using the current environment's flags.
489 # So make sure that the program will compile without any warning. For
490 # example using: 'int main(int argc, char** argv)' will fail with the
491 # '-Wall -Werror' flags since the variables argc and argv would not be
492 # used in the program...
498 printf("%d", (int)sizeof(""" + type_name + """));
502 st, out = context.RunProg(src, suffix)
506 # If cannot convert output of test prog to an integer (the size),
507 # something went wront, so just fail
512 context.Display("yes\n")
513 _Have(context, "SIZEOF_%s" % type_name, size,
514 "The size of `%s', as computed by sizeof." % type_name)
517 context.Display("no\n")
518 _LogFailed(context, src, st)
523 def CheckDeclaration(context, symbol, includes = None, language = None):
524 """Checks whether symbol is declared.
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.
533 Optional "header" can be defined to include a header file.
535 only C and C++ supported.
539 True if the check failed, False if succeeded."""
541 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
542 if context.headerfilename:
543 includetext = '#include "%s"' % context.headerfilename
550 lang, suffix, msg = _lang2suffix(language)
552 context.Display("Cannot check for declaration %s: %s\n" % (type_name, msg))
555 src = includetext + includes
556 context.Display('Checking whether %s is declared... ' % symbol)
567 """ % (symbol, symbol)
569 st = context.CompileProg(src, suffix)
570 _YesNoResult(context, st, "HAVE_DECL_" + symbol, src,
571 "Set to 1 if %s is defined." % symbol)
574 def CheckLib(context, libs, func_name = None, header = None,
575 extra_libs = None, call = None, language = None, autoadd = 1):
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"
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.
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.
596 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
597 if context.headerfilename:
598 includetext = '#include "%s"' % context.headerfilename
606 %s""" % (includetext, header)
608 # Add a function declaration if needed.
609 if func_name and func_name != "main":
618 # The actual test code.
620 call = "%s();" % func_name
622 # if no function to test, leave main() blank
632 i = string.find(call, "\n")
634 calltext = call[:i] + ".."
635 elif call[-1] == ';':
640 for lib_name in libs:
642 lang, suffix, msg = _lang2suffix(language)
644 context.Display("Cannot check for library %s: %s\n" % (lib_name, msg))
647 # if a function was specified to run in main(), say it
649 context.Display("Checking for %s in %s library %s... "
650 % (calltext, lang, lib_name))
651 # otherwise, just say the name of library and language
653 context.Display("Checking for %s library %s... "
660 oldLIBS = context.AppendLIBS(l)
661 sym = "HAVE_LIB" + lib_name
666 ret = context.BuildProg(text, suffix)
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)
679 # END OF PUBLIC FUNCTIONS
682 def _YesNoResult(context, ret, key, text, comment = None):
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.
692 _Have(context, key, not ret, comment)
694 context.Display("no\n")
695 _LogFailed(context, text, ret)
697 context.Display("yes\n")
700 def _Have(context, key, have, comment = None):
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!
716 key_up = string.upper(key)
717 key_up = re.sub('[^A-Z0-9_]', '_', key_up)
718 context.havedict[key_up] = have
720 line = "#define %s 1\n" % key_up
722 line = "/* #undef %s */\n" % key_up
723 elif type(have) == IntType:
724 line = "#define %s %d\n" % (key_up, have)
726 line = "#define %s %s\n" % (key_up, str(have))
728 if comment is not None:
729 lines = "\n/* %s */\n" % comment + line
733 if context.headerfilename:
734 f = open(context.headerfilename, "a")
737 elif hasattr(context,'config_h'):
738 context.config_h = context.config_h + lines
741 def _LogFailed(context, text, msg):
743 Write to the log about a failed program.
744 Add line numbers, so that error messages can be understood.
747 context.Log("Failed program was:\n")
748 lines = string.split(text, '\n')
749 if len(lines) and lines[-1] == '':
750 lines = lines[:-1] # remove trailing empty line
753 context.Log("%d: %s\n" % (n, line))
756 context.Log("Error message: %s\n" % msg)
759 def _lang2suffix(lang):
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).
766 lang = the unified language name
767 suffix = the suffix, including the leading dot
768 msg = an error message
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)
775 return None, None, "Unsupported language: %s" % lang
778 # vim: set sw=4 et sts=4 tw=79 fo+=l: