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:
782
# indent-tabs-mode:nil
784
# vim: set expandtab tabstop=4 shiftwidth=4: