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)
146 def CheckFunc(context, function_name, header = None, language = None):
148 Configure check for a function "function_name".
149 "language" should be "C" or "C++" and is used to select the compiler.
151 Optional "header" can be defined to define a function prototype, include a
152 header file or anything else that comes before main().
153 Sets HAVE_function_name in context.havedict according to the result.
154 Note that this uses the current value of compiler and linker flags, make
155 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
156 Returns an empty string for success, an error message for failure.
159 # Remarks from autoconf:
160 # - Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h>
161 # which includes <sys/select.h> which contains a prototype for select.
162 # Similarly for bzero.
163 # - assert.h is included to define __stub macros and hopefully few
164 # prototypes, which can conflict with char $1(); below.
165 # - Override any gcc2 internal prototype to avoid an error.
166 # - We use char for the function declaration because int might match the
167 # return type of a gcc2 builtin and then its argument prototype would
169 # - The GNU C library defines this for functions which it implements to
170 # always fail with ENOSYS. Some functions are actually named something
171 # starting with __ and the normal name is an alias.
173 if context.headerfilename:
174 includetext = '#include "%s"' % context.headerfilename
182 char %s();""" % function_name
184 lang, suffix, msg = _lang2suffix(language)
186 context.Display("Cannot check for %s(): %s\n" % (function_name, msg))
195 #if defined (__stub_%(name)s) || defined (__stub___%(name)s)
203 """ % { 'name': function_name,
204 'include': includetext,
207 context.Display("Checking for %s function %s()... " % (lang, function_name))
208 ret = context.BuildProg(text, suffix)
209 _YesNoResult(context, ret, "HAVE_" + function_name, text)
213 def CheckHeader(context, header_name, header = None, language = None,
214 include_quotes = None):
216 Configure check for a C or C++ header file "header_name".
217 Optional "header" can be defined to do something before including the
218 header file (unusual, supported for consistency).
219 "language" should be "C" or "C++" and is used to select the compiler.
221 Sets HAVE_header_name in context.havedict according to the result.
222 Note that this uses the current value of compiler and linker flags, make
223 sure $CFLAGS and $CPPFLAGS are set correctly.
224 Returns an empty string for success, an error message for failure.
226 # Why compile the program instead of just running the preprocessor?
227 # It is possible that the header file exists, but actually using it may
228 # fail (e.g., because it depends on other header files). Thus this test is
229 # more strict. It may require using the "header" argument.
231 # Use <> by default, because the check is normally used for system header
232 # files. SCons passes '""' to overrule this.
234 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
235 if context.headerfilename:
236 includetext = '#include "%s"\n' % context.headerfilename
242 lang, suffix, msg = _lang2suffix(language)
244 context.Display("Cannot check for header file %s: %s\n"
245 % (header_name, msg))
248 if not include_quotes:
249 include_quotes = "<>"
251 text = "%s%s\n#include %s%s%s\n\n" % (includetext, header,
252 include_quotes[0], header_name, include_quotes[1])
254 context.Display("Checking for %s header file %s... " % (lang, header_name))
255 ret = context.CompileProg(text, suffix)
256 _YesNoResult(context, ret, "HAVE_" + header_name, text)
260 def CheckType(context, type_name, fallback = None,
261 header = None, language = None):
263 Configure check for a C or C++ type "type_name".
264 Optional "header" can be defined to include a header file.
265 "language" should be "C" or "C++" and is used to select the compiler.
267 Sets HAVE_type_name in context.havedict according to the result.
268 Note that this uses the current value of compiler and linker flags, make
269 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
270 Returns an empty string for success, an error message for failure.
273 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
274 if context.headerfilename:
275 includetext = '#include "%s"' % context.headerfilename
281 lang, suffix, msg = _lang2suffix(language)
283 context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
286 # Remarks from autoconf about this test:
287 # - Grepping for the type in include files is not reliable (grep isn't
289 # - Using "TYPE my_var;" doesn't work for const qualified types in C++.
290 # Adding an initializer is not valid for some C++ classes.
291 # - Using the type as parameter to a function either fails for K&$ C or for
293 # - Using "TYPE *my_var;" is valid in C for some types that are not
294 # declared (struct something).
295 # - Using "sizeof(TYPE)" is valid when TYPE is actually a variable.
296 # - Using the previous two together works reliably.
304 if (sizeof (%(name)s))
307 """ % { 'include': includetext,
311 context.Display("Checking for %s type %s... " % (lang, type_name))
312 ret = context.BuildProg(text, suffix)
313 _YesNoResult(context, ret, "HAVE_" + type_name, text)
314 if ret and fallback and context.headerfilename:
315 f = open(context.headerfilename, "a")
316 f.write("typedef %s %s;\n" % (fallback, type_name))
322 def CheckLib(context, libs, func_name = None, header = None,
323 extra_libs = None, call = None, language = None, autoadd = 1):
325 Configure check for a C or C++ libraries "libs". Searches through
326 the list of libraries, until one is found where the test succeeds.
327 Tests if "func_name" or "call" exists in the library. Note: if it exists
328 in another library the test succeeds anyway!
329 Optional "header" can be defined to include a header file. If not given a
330 default prototype for "func_name" is added.
331 Optional "extra_libs" is a list of library names to be added after
332 "lib_name" in the build command. To be used for libraries that "lib_name"
334 Optional "call" replaces the call to "func_name" in the test code. It must
335 consist of complete C statements, including a trailing ";".
336 Both "func_name" and "call" arguments are optional, and in that case, just
337 linking against the libs is tested.
338 "language" should be "C" or "C++" and is used to select the compiler.
340 Note that this uses the current value of compiler and linker flags, make
341 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
342 Returns an empty string for success, an error message for failure.
344 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
345 if context.headerfilename:
346 includetext = '#include "%s"' % context.headerfilename
354 %s""" % (includetext, header)
356 # Add a function declaration if needed.
357 if func_name and func_name != "main":
366 # The actual test code.
368 call = "%s();" % func_name
370 # if no function to test, leave main() blank
380 i = string.find(call, "\n")
382 calltext = call[:i] + ".."
383 elif call[-1] == ';':
388 for lib_name in libs:
390 lang, suffix, msg = _lang2suffix(language)
392 context.Display("Cannot check for library %s: %s\n" % (lib_name, msg))
395 # if a function was specified to run in main(), say it
397 context.Display("Checking for %s in %s library %s... "
398 % (calltext, lang, lib_name))
399 # otherwise, just say the name of library and language
401 context.Display("Checking for %s library %s... "
408 oldLIBS = context.AppendLIBS(l)
409 sym = "HAVE_LIB" + lib_name
414 ret = context.BuildProg(text, suffix)
416 _YesNoResult(context, ret, sym, text)
417 if oldLIBS != -1 and (ret or not autoadd):
418 context.SetLIBS(oldLIBS)
426 # END OF PUBLIC FUNCTIONS
429 def _YesNoResult(context, ret, key, text):
431 Handle the result of a test with a "yes" or "no" result.
432 "ret" is the return value: empty if OK, error message when not.
433 "key" is the name of the symbol to be defined (HAVE_foo).
434 "text" is the source code of the program used for testing.
437 _Have(context, key, not ret)
439 context.Display("no\n")
440 _LogFailed(context, text, ret)
442 context.Display("yes\n")
445 def _Have(context, key, have):
447 Store result of a test in context.havedict and context.headerfilename.
448 "key" is a "HAVE_abc" name. It is turned into all CAPITALS and non-
449 alphanumerics are replaced by an underscore.
450 The value of "have" can be:
451 1 - Feature is defined, add "#define key".
452 0 - Feature is not defined, add "/* #undef key */".
453 Adding "undef" is what autoconf does. Not useful for the
454 compiler, but it shows that the test was done.
455 number - Feature is defined to this number "#define key have".
456 Doesn't work for 0 or 1, use a string then.
457 string - Feature is defined to this string "#define key have".
458 Give "have" as is should appear in the header file, include quotes
459 when desired and escape special characters!
461 key_up = string.upper(key)
462 key_up = re.sub('[^A-Z0-9_]', '_', key_up)
463 context.havedict[key_up] = have
465 line = "#define %s 1\n" % key_up
467 line = "/* #undef %s */\n" % key_up
468 elif type(have) == IntType:
469 line = "#define %s %d\n" % (key_up, have)
471 line = "#define %s %s\n" % (key_up, str(have))
473 if context.headerfilename:
474 f = open(context.headerfilename, "a")
477 elif hasattr(context,'config_h'):
478 context.config_h = context.config_h + line
481 def _LogFailed(context, text, msg):
483 Write to the log about a failed program.
484 Add line numbers, so that error messages can be understood.
487 context.Log("Failed program was:\n")
488 lines = string.split(text, '\n')
489 if len(lines) and lines[-1] == '':
490 lines = lines[:-1] # remove trailing empty line
493 context.Log("%d: %s\n" % (n, line))
496 context.Log("Error message: %s\n" % msg)
499 def _lang2suffix(lang):
501 Convert a language name to a suffix.
502 When "lang" is empty or None C is assumed.
503 Returns a tuple (lang, suffix, None) when it works.
504 For an unrecognized language returns (None, None, msg).
506 lang = the unified language name
507 suffix = the suffix, including the leading dot
508 msg = an error message
510 if not lang or lang in ["C", "c"]:
511 return ("C", ".c", None)
512 if lang in ["c++", "C++", "cpp", "CXX", "cxx"]:
513 return ("C++", ".cpp", None)
515 return None, None, "Unsupported language: %s" % lang
518 # vim: set sw=4 et sts=4 tw=79 fo+=l: