summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-08-30 07:58:08 (GMT)
committerSteven Knight <knight@baldmt.com>2003-08-30 07:58:08 (GMT)
commitbfc84b0f38ad74bd181df2b0938f0bd94e774cd4 (patch)
tree061589e7604c99b2204bcab8f31b830ab5039d99
parente7bd1d71888221071e97778d1dbd31750d9874cd (diff)
downloadSCons-bfc84b0f38ad74bd181df2b0938f0bd94e774cd4.zip
SCons-bfc84b0f38ad74bd181df2b0938f0bd94e774cd4.tar.gz
SCons-bfc84b0f38ad74bd181df2b0938f0bd94e774cd4.tar.bz2
Split non-SCons-specific parts of SConf.py into a separate Conftest.py module. (Bram Moolenaar)
-rw-r--r--bin/files1
-rw-r--r--doc/man/scons.162
-rw-r--r--src/CHANGES.txt5
-rw-r--r--src/engine/MANIFEST.in1
-rw-r--r--src/engine/SCons/Conftest.py483
-rw-r--r--src/engine/SCons/SConf.py242
-rw-r--r--test/Configure.py34
7 files changed, 685 insertions, 143 deletions
diff --git a/bin/files b/bin/files
index 252c98f..043eadb 100644
--- a/bin/files
+++ b/bin/files
@@ -1,5 +1,6 @@
./SCons/Action.py
./SCons/Builder.py
+./SCons/Conftest.py
./SCons/Defaults.py
./SCons/Environment.py
./SCons/Errors.py
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index 3919a6e..22cedab 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -3739,38 +3739,70 @@ The following Checks are predefined.
goes by and developers contribute new useful tests.)
.TP
-.RI Configure.CheckCHeader( self ", " header ", [" include_quotes ])
+.RI Configure.CheckHeader( self ", " header ", [" include_quotes ", " language ])
Checks if
.I header
-is usable in the C-language. The optional argument
+is usable in the specified language.
+The optional argument
.I include_quotes
must be
a two character string, where the first character denotes the opening
quote and the second character denotes the closing quote (both default
to \N'34')
+The optional argument
+.I language
+should be either
+.B C
+or
+.B C++
+and selects the compiler to be used for the check.
+Returns 1 on success and 0 on failure.
+
+.TP
+.RI Configure.CheckCHeader( self ", " header ", [" include_quotes ])
+This is a wrapper around
+.B Configure.CheckHeader
+which checks if
+.I header
+is usable in the C language. The optional argument
+.I include_quotes
+must be
+a two character string, where the first character denotes the opening
+quote and the second character denotes the closing quote (both default
+to \N'34').
Returns 1 on success and 0 on failure.
.TP
.RI Configure.CheckCXXHeader( self ", " header ", [" include_quotes ])
-Checks if
+This is a wrapper around
+.B Configure.CheckHeader
+which checks if
.I header
is usable in the C++ language. The optional argument
.I include_quotes
must be
a two character string, where the first character denotes the opening
quote and the second character denotes the closing quote (both default
-to \N'34')
+to \N'34').
Returns 1 on success and 0 on failure.
.TP
-.RI Configure.CheckFunc( self ", " function_name )
+.RI Configure.CheckFunc( self ", " function_name ", [" language ])
Checks if the specified
C or C+++ function is available.
.I function_name
is the name of the function to check for.
+The optional
+.I language
+argument should be
+.B C
+or
+.B C++
+and selects the compiler to be used for the check;
+the default is "C".
.TP
-.RI Configure.CheckLib( self ", [" library ", " symbol ", " autoadd ])
+.RI Configure.CheckLib( self ", [" library ", " symbol ", " header ", " language ", " autoadd ])
Checks if
.I library
provides
@@ -3791,6 +3823,14 @@ is "main",
which just check if
you can link against the specified
.IR library .
+The optional
+.I language
+argument should be
+.B C
+or
+.B C++
+and selects the compiler to be used for the check;
+the default is "C".
The default value for
.I autoadd
is 1.
@@ -3817,7 +3857,7 @@ specifies whether to add the library to the environment (only if the check
succeeds). This method returns 1 on success and 0 on error.
.TP
-.RI Configure.CheckType( self ", " type_name ", [" includes ])
+.RI Configure.CheckType( self ", " type_name ", [" includes ", " language ])
Checks for the existence of a type defined by
.BR typedef .
.I type_name
@@ -3827,6 +3867,14 @@ is a string containing one or more
.B #include
lines that will be inserted into the program
that will be run to test for the existence of the type.
+The optional
+.I language
+argument should be
+.B C
+or
+.B C++
+and selects the compiler to be used for the check;
+the default is "C".
.EE
Example of a typical Configure usage:
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 3aad3c1..7dcdaf9 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -30,6 +30,11 @@ RELEASE X.XX - XXX
- Accomodate alphanumeric version strings in EnsurePythonVersion().
+ From Bram Moolenaar:
+
+ - Split the non-SCons-specific functionality from SConf.py to a new,
+ re-usable Conftest.py module.
+
RELEASE 0.92 - Wed, 20 Aug 2003 03:45:28 -0500
diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in
index 4c22f1d..3c71aba 100644
--- a/src/engine/MANIFEST.in
+++ b/src/engine/MANIFEST.in
@@ -1,6 +1,7 @@
SCons/__init__.py
SCons/Action.py
SCons/Builder.py
+SCons/Conftest.py
SCons/Defaults.py
SCons/Environment.py
SCons/Errors.py
diff --git a/src/engine/SCons/Conftest.py b/src/engine/SCons/Conftest.py
new file mode 100644
index 0000000..a6bedf5
--- /dev/null
+++ b/src/engine/SCons/Conftest.py
@@ -0,0 +1,483 @@
+"""SCons.Conftest
+
+Autoconf-like configuration support; low level implementation of tests.
+"""
+
+#
+# Copyright (c) 2003 Stichting NLnet Labs
+# Copyright (c) 2001, 2002, 2003 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+#
+# The purpose of this module is to define how a check is to be performed.
+# Use one of the Check...() functions below.
+#
+
+#
+# A context class is used that defines functions for carrying out the tests,
+# logging and messages. The following methods and members must be present:
+#
+# context.Display(msg) Function called to print messages that are normally
+# displayed for the user. Newlines are explicitly used.
+# The text should also be written to the logfile!
+#
+# context.Log(msg) Function called to write to a log file.
+#
+# context.BuildProg(text, ext)
+# Function called to build a program, using "ext" for the
+# file extention. Must return an empty string for
+# success, an error message for failure.
+# For reliable test results building should be done just
+# like an actual program would be build, using the same
+# command and arguments (including configure results so
+# far).
+#
+# context.CompileProg(text, ext)
+# Function called to compile a program, using "ext" for
+# the file extention. Must return an empty string for
+# success, an error message for failure.
+# For reliable test results compiling should be done just
+# like an actual source file would be compiled, using the
+# same command and arguments (including configure results
+# so far).
+#
+# context.AppendLIBS(lib_name_list)
+# Append "lib_name_list" to the value of LIBS.
+# "lib_namelist" is a list of strings.
+# Return the value of LIBS before changing it (any type
+# can be used, it is passed to SetLIBS() later.
+#
+# context.SetLIBS(value)
+# Set LIBS to "value". The type of "value" is what
+# AppendLIBS() returned.
+# Return the value of LIBS before changing it (any type
+# can be used, it is passed to SetLIBS() later.
+#
+# context.headerfilename
+# Name of file to append configure results to, usually
+# "confdefs.h".
+# The file must not exist or be empty when starting.
+# Empty or None to skip this (some tests will not work!).
+#
+# context.vardict Dictionary holding variables used for the tests and
+# stores results from the tests, used for the build
+# commands.
+# Normally contains "CC", "LIBS", "CPPFLAGS", etc.
+#
+# context.havedict Dictionary holding results from the tests that are to
+# be used inside a program.
+# Names often start with "HAVE_". These are zero
+# (feature not present) or one (feature present). Other
+# variables may have any value, e.g., "PERLVERSION" can
+# be a number and "SYSTEMNAME" a string.
+#
+
+import string
+from types import IntType
+
+#
+# PUBLIC FUNCTIONS
+#
+
+# Generic remarks:
+# - When a language is specified which is not supported the test fails. The
+# message is a bit different, because not all the arguments for the normal
+# message are available yet (chicken-egg problem).
+
+
+def CheckBuilder(context, text = None, language = None):
+ """
+ Configure check to see if the compiler works.
+ Note that this uses the current value of compiler and linker flags, make
+ sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
+ "language" should be "C" or "C++" and is used to select the compiler.
+ Default is "C".
+ "text" may be used to specify the code to be build.
+ Returns an empty string for success, an error message for failure.
+ """
+ lang, suffix, msg = _lang2suffix(language)
+ if msg:
+ context.Display("%s\n" % msg)
+ return msg
+
+ if not text:
+ text = """
+ int main() {
+ return 0;
+ }\n\n"""
+
+ context.Display("Checking if building a %s file works... " % lang)
+ ret = context.BuildProg(text, suffix)
+ _YesNoResult(context, ret, None, text)
+ return ret
+
+
+def CheckFunc(context, function_name, header = None, language = None):
+ """
+ Configure check for a function "function_name".
+ "language" should be "C" or "C++" and is used to select the compiler.
+ Default is "C".
+ Optional "header" can be defined to define a function prototype, include a
+ header file or anything else that comes before main().
+ Sets HAVE_function_name in context.havedict according to the result.
+ Note that this uses the current value of compiler and linker flags, make
+ sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
+ Returns an empty string for success, an error message for failure.
+ """
+
+ # Remarks from autoconf:
+ # - Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h>
+ # which includes <sys/select.h> which contains a prototype for select.
+ # Similarly for bzero.
+ # - assert.h is included to define __stub macros and hopefully few
+ # prototypes, which can conflict with char $1(); below.
+ # - Override any gcc2 internal prototype to avoid an error.
+ # - We use char for the function declaration because int might match the
+ # return type of a gcc2 builtin and then its argument prototype would
+ # still apply.
+ # - The GNU C library defines this for functions which it implements to
+ # always fail with ENOSYS. Some functions are actually named something
+ # starting with __ and the normal name is an alias.
+
+ if context.headerfilename:
+ includetext = '#include "%s"' % context.headerfilename
+ else:
+ includetext = ''
+ if not header:
+ header = """
+ #ifdef __cplusplus
+ extern "C"
+ #endif
+ char %s();""" % function_name
+
+ lang, suffix, msg = _lang2suffix(language)
+ if msg:
+ context.Display("Cannot check for %s(): %s\n" % (function_name, msg))
+ return msg
+
+ text = """
+ %(include)s
+ #include <assert.h>
+ %(hdr)s
+
+ int main() {
+ #if defined (__stub_%(name)s) || defined (__stub___%(name)s)
+ fail fail fail
+ #else
+ %(name)s();
+ #endif
+
+ return 0;
+ }\n\n""" % { 'name': function_name,
+ 'include': includetext,
+ 'hdr': header }
+
+ context.Display("Checking for %s function %s()... " % (lang, function_name))
+ ret = context.BuildProg(text, suffix)
+ _YesNoResult(context, ret, "HAVE_" + function_name, text)
+ return ret
+
+
+def CheckHeader(context, header_name, header = None, language = None,
+ include_quotes = None):
+ """
+ Configure check for a C or C++ header file "header_name".
+ Optional "header" can be defined to do something before including the
+ header file (unusual, supported for consistency).
+ "language" should be "C" or "C++" and is used to select the compiler.
+ Default is "C".
+ Sets HAVE_header_name in context.havedict according to the result.
+ Note that this uses the current value of compiler and linker flags, make
+ sure $CFLAGS and $CPPFLAGS are set correctly.
+ Returns an empty string for success, an error message for failure.
+ """
+ # Why compile the program instead of just running the preprocessor?
+ # It is possible that the header file exists, but actually using it may
+ # fail (e.g., because it depends on other header files). Thus this test is
+ # more strict. It may require using the "header" argument.
+ #
+ # Use <> by default, because the check is normally used for system header
+ # files. SCons passes '""' to overrule this.
+
+ # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
+ if context.headerfilename:
+ includetext = '#include "%s"\n' % context.headerfilename
+ else:
+ includetext = ''
+ if not header:
+ header = ""
+
+ lang, suffix, msg = _lang2suffix(language)
+ if msg:
+ context.Display("Cannot check for header file %s: %s\n"
+ % (header_name, msg))
+ return msg
+
+ if not include_quotes:
+ include_quotes = "<>"
+
+ text = "%s%s\n#include %s%s%s\n\n" % (includetext, header,
+ include_quotes[0], header_name, include_quotes[1])
+
+ context.Display("Checking for %s header file %s... " % (lang, header_name))
+ ret = context.CompileProg(text, suffix)
+ _YesNoResult(context, ret, "HAVE_" + header_name, text)
+ return ret
+
+
+def CheckType(context, type_name, fallback = None,
+ header = None, language = None):
+ """
+ Configure check for a C or C++ type "type_name".
+ Optional "header" can be defined to include a header file.
+ "language" should be "C" or "C++" and is used to select the compiler.
+ Default is "C".
+ Sets HAVE_type_name in context.havedict according to the result.
+ Note that this uses the current value of compiler and linker flags, make
+ sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
+ Returns an empty string for success, an error message for failure.
+ """
+
+ # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
+ if context.headerfilename:
+ includetext = '#include "%s"' % context.headerfilename
+ else:
+ includetext = ''
+ if not header:
+ header = ""
+
+ lang, suffix, msg = _lang2suffix(language)
+ if msg:
+ context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
+ return msg
+
+ # Remarks from autoconf about this test:
+ # - Grepping for the type in include files is not reliable (grep isn't
+ # portable anyway).
+ # - Using "TYPE my_var;" doesn't work for const qualified types in C++.
+ # Adding an initializer is not valid for some C++ classes.
+ # - Using the type as parameter to a function either fails for K&$ C or for
+ # C++.
+ # - Using "TYPE *my_var;" is valid in C for some types that are not
+ # declared (struct something).
+ # - Using "sizeof(TYPE)" is valid when TYPE is actually a variable.
+ # - Using the previous two together works reliably.
+ text = """
+ %(include)s
+ %(header)s
+
+ int main() {
+ if ((%(name)s *) 0)
+ return 0;
+ if (sizeof (%(name)s))
+ return 0;
+ }\n\n""" % { 'include': includetext,
+ 'header': header,
+ 'name': type_name }
+
+ context.Display("Checking for %s type %s... " % (lang, type_name))
+ ret = context.BuildProg(text, suffix)
+ _YesNoResult(context, ret, "HAVE_" + type_name, text)
+ if ret and fallback and context.headerfilename:
+ f = open(context.headerfilename, "a")
+ f.write("typedef %s %s;\n" % (fallback, type_name))
+ f.close()
+
+ return ret
+
+
+def CheckLib(context, lib_name, func_name, header = None,
+ extra_libs = None, call = None, language = None, autoadd = 1):
+ """
+ Configure check for a C or C++ library "lib_name".
+ Tests if "func_name" or "call" exists in the library. Note: if it exists
+ in another library the test succeeds anyway!
+ Optional "header" can be defined to include a header file. If not given a
+ default prototype for "func_name" is added.
+ Optional "extra_libs" is a list of library names to be added after
+ "lib_name" in the build command. To be used for libraries that "lib_name"
+ depends on.
+ Optional "call" replaces the call to "func_name" in the test code. It must
+ consist of complete C statements, including a trailing ";".
+ There must either be a "func_name" or a "call" argument (or both).
+ "language" should be "C" or "C++" and is used to select the compiler.
+ Default is "C".
+ Note that this uses the current value of compiler and linker flags, make
+ sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
+ Returns an empty string for success, an error message for failure.
+ """
+ # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
+ if context.headerfilename:
+ includetext = '#include "%s"' % context.headerfilename
+ else:
+ includetext = ''
+ if not header:
+ header = ""
+
+ lang, suffix, msg = _lang2suffix(language)
+ if msg:
+ context.Display("Cannot check for library %s: %s\n" % (lib_name, msg))
+ return msg
+
+ text = """
+ %s
+ %s """ % (includetext, header)
+
+ # Add a function declaration if needed.
+ if func_name and func_name != "main" and not header:
+ text = text + """
+ #ifdef __cplusplus
+ extern "C"
+ #endif
+ char %s();""" % func_name
+
+ # The actual test code.
+ if not call:
+ call = "%s();" % func_name
+ text = text + """
+ int
+ main() {
+ %s
+ return 0;
+ }
+ \n\n""" % call
+
+ i = string.find(call, "\n")
+ if i > 0:
+ calltext = call[:i] + ".."
+ elif call[-1] == ';':
+ calltext = call[:-1]
+ else:
+ calltext = call
+
+ context.Display("Checking for %s in %s library %s... "
+ % (calltext, lang, lib_name))
+ if lib_name:
+ l = [ lib_name ]
+ if extra_libs:
+ l.extend(extra_libs)
+ oldLIBS = context.AppendLIBS(l)
+ sym = "HAVE_LIB" + lib_name
+ else:
+ oldLIBS = -1
+ sym = None
+
+ ret = context.BuildProg(text, suffix)
+
+ _YesNoResult(context, ret, sym, text)
+ if oldLIBS != -1 and (ret or not autoadd):
+ context.SetLIBS(oldLIBS)
+
+ return ret
+
+
+#
+# END OF PUBLIC FUNCTIONS
+#
+
+def _YesNoResult(context, ret, key, text):
+ """
+ Handle the result of a test with a "yes" or "no" result.
+ "ret" is the return value: empty if OK, error message when not.
+ "key" is the name of the symbol to be defined (HAVE_foo).
+ "text" is the source code of the program used for testing.
+ """
+ if key:
+ _Have(context, key, not ret)
+ if ret:
+ context.Display("no\n")
+ _LogFailed(context, text, ret)
+ else:
+ context.Display("yes\n")
+
+
+def _Have(context, key, have):
+ """
+ Store result of a test in context.havedict and context.headerfilename.
+ "key" is a "HAVE_abc" name. It is turned into all CAPITALS and ":./" are
+ replaced by an underscore.
+ The value of "have" can be:
+ 1 - Feature is defined, add "#define key".
+ 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.
+ number - Feature is defined to this number "#define key have".
+ Doesn't work for 0 or 1, use a string then.
+ string - Feature is defined to this string "#define key have".
+ Give "have" as is should appear in the header file, include quotes
+ when desired and escape special characters!
+ """
+ key_up = string.upper(key)
+ key_up = string.replace(key_up, ':', '_')
+ key_up = string.replace(key_up, '.', '_')
+ key_up = string.replace(key_up, '/', '_')
+ key_up = string.replace(key_up, ' ', '_')
+ context.havedict[key_up] = have
+ if context.headerfilename:
+ f = open(context.headerfilename, "a")
+ if have == 1:
+ f.write("#define %s\n" % key_up)
+ elif have == 0:
+ f.write("/* #undef %s */\n" % key_up)
+ elif type(have) == IntType:
+ f.write("#define %s %d\n" % (key_up, have))
+ else:
+ f.write("#define %s %s\n" % (key_up, str(have)))
+ f.close()
+
+
+def _LogFailed(context, text, msg):
+ """
+ Write to the log about a failed program.
+ Add line numbers, so that error messages can be understood.
+ """
+ context.Log("Failed program was:\n")
+ lines = string.split(text, '\n')
+ if len(lines) and lines[-1] == '':
+ lines = lines[:-1] # remove trailing empty line
+ n = 1
+ for line in lines:
+ context.Log("%d: %s\n" % (n, line))
+ n = n + 1
+ context.Log("Error message: %s\n" % msg)
+
+
+def _lang2suffix(lang):
+ """
+ Convert a language name to a suffix.
+ When "lang" is empty or None C is assumed.
+ Returns a tuple (lang, suffix, None) when it works.
+ For an unrecognized language returns (None, None, msg).
+ Where:
+ lang = the unified language name
+ suffix = the suffix, including the leading dot
+ msg = an error message
+ """
+ if not lang or lang in ["C", "c"]:
+ return ("C", ".c", None)
+ if lang in ["c++", "C++", "cpp", "CXX", "cxx"]:
+ return ("C++", ".cpp", None)
+
+ return None, None, "Unsupported language: %s" % lang
+
+
+# vim: set sw=4 et sts=4 tw=79 fo+=l:
diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py
index fad2dfb..22bcb48 100644
--- a/src/engine/SCons/SConf.py
+++ b/src/engine/SCons/SConf.py
@@ -30,7 +30,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import cPickle
import os
-import shutil
import sys
import traceback
from types import *
@@ -42,6 +41,7 @@ import SCons.Node.FS
import SCons.Taskmaster
import SCons.Util
import SCons.Warnings
+import SCons.Conftest
# First i thought of using a different filesystem as the default_fs,
# but it showed up that there are too many side effects in doing that.
@@ -503,7 +503,12 @@ class CheckContext:
"""Constructor. Pass the corresponding SConf instance."""
self.sconf = sconf
self.cached = 0
- self.show_result = 0
+ self.did_show_result = 0
+
+ # for Conftest.py:
+ self.vardict = {}
+ self.havedict = {}
+ self.headerfilename = None # XXX may cause trouble!
def Message(self, text):
"""Inform about what we are doing right now, e.g.
@@ -513,29 +518,33 @@ class CheckContext:
if self.sconf.logstream != None:
self.sconf.logstream.write(text + '\n')
sys.stdout.write(text)
- self.show_result = 0
+ self.did_show_result = 0
- def Result(self, res ):
+ def Result(self, res):
"""Inform about the result of the test. res may be an integer or a
string. In case of an integer, the written text will be 'ok' or
'failed'.
+ The result is only displayed when self.did_show_result is not set.
"""
- if( type(res) == IntType ):
+ if type(res) == IntType:
if res:
text = "ok"
else:
text = "failed"
- elif( type(res) == StringType ):
+ elif type(res) == StringType:
text = res
else:
raise TypeError, "Expected string or int"
- if( self.cached ):
- text = text + " (cached)"
- if self.show_result == 0:
+
+ if self.did_show_result == 0:
+ if self.cached:
+ text = text + " (cached)"
+
+ # Didn't show result yet, do it now.
if self.sconf.logstream != None:
self.sconf.logstream.write("Result: " + text + "\n\n")
sys.stdout.write(text + "\n")
- self.show_result = 1
+ self.did_show_result = 1
def TryBuild(self, *args, **kw):
@@ -561,110 +570,126 @@ class CheckContext:
else:
raise AttributeError, "CheckContext instance has no attribute '%s'" % attr
-def _header_prog( header, include_quotes ):
- return "#include %s%s%s\n\n" % (include_quotes[0],
- header,
- include_quotes[1])
+ #### Stuff used by Conftest.py (look there for explanations).
-def CheckFunc(context, function_name):
- context.Message("Checking for %s... " % function_name)
+ def BuildProg(self, text, ext):
+ # TODO: should use self.vardict for $CC, $CPPFLAGS, etc.
+ res = self.TryBuild(self.env.Program, text, ext)
+ if type(res) == IntType:
+ if res:
+ ret = ""
+ else:
+ ret = "failed to build test program"
+ elif type(res) == StringType:
+ ret = res
+ else:
+ raise TypeError, "Expected string or int"
+ return ret
- ret = context.TryBuild(context.env.Program, """
- #include <assert.h>
+ def CompileProg(self, text, ext):
+ # TODO: should use self.vardict for $CC, $CPPFLAGS, etc.
+ res = self.TryBuild(self.env.Object, text, ext)
+ if type(res) == IntType:
+ if res:
+ ret = ""
+ else:
+ ret = "failed to compile test program"
+ elif type(res) == StringType:
+ ret = res
+ else:
+ raise TypeError, "Expected string or int"
+ return ret
- #ifdef __cplusplus
- extern "C"
- #endif
- char %(name)s();
+ def AppendLIBS(self, lib_name_list):
+ oldLIBS = self.env.get( 'LIBS', [] )
+ self.env.Append(LIBS = lib_name_list)
+ return oldLIBS
- int main() {
- #if defined (__stub_%(name)s) || defined (__stub___%(name)s)
- fail fail fail
- #else
- %(name)s();
- #endif
+ def SetLIBS(self, val):
+ oldLIBS = self.env.get( 'LIBS', [] )
+ self.env.Replace(LIBS = val)
+ return oldLIBS
- return 0;
- }\n\n""" % { 'name': function_name }, ".cpp")
- context.Result(ret)
+ def Display(self, msg):
+ sys.stdout.write(msg)
+ self.Log(msg)
- return ret
+ def Log(self, msg):
+ if self.sconf.logstream != None:
+ self.sconf.logstream.write(msg)
-def CheckType(context, type_name, includes = ""):
- context.Message("Checking for %s..." % type_name)
+ #### End of stuff used by Conftest.py.
- ret = context.TryBuild(context.env.Program, """
- %(includes)s
- int main() {
- if ((%(name)s *) 0)
- return 0;
- if (sizeof (%(name)s))
- return 0;
- }\n\n""" % { 'name': type_name, 'includes': includes }, ".cpp")
- context.Result(ret)
+def CheckFunc(context, function_name, language = None):
+ res = SCons.Conftest.CheckFunc(context, function_name, language = language)
+ context.did_show_result = 1
+ if not res:
+ return 1 # Ok
+ return 0 # Failed
- return ret
-def CheckCHeader(test, header, include_quotes='""'):
+def CheckType(context, type_name, includes = "", language = None):
+ res = SCons.Conftest.CheckType(context, type_name,
+ header = includes, language = language)
+ context.did_show_result = 1
+ if not res:
+ return 1 # Ok
+ return 0 # Failed
+
+
+def CheckHeader(context, header, include_quotes = '<>', language = None):
"""
- A test for a c header file.
+ A test for a C or C++ header file.
"""
# ToDo: Support also system header files (i.e. #include <header.h>)
- test.Message("Checking for C header %s ... " % header)
- ret = test.TryCompile(_header_prog(header, include_quotes), ".c")
- test.Result( ret )
- return ret
+ res = SCons.Conftest.CheckHeader(context, header, language = language,
+ include_quotes = include_quotes)
+ context.did_show_result = 1
+ if not res:
+ return 1 # Ok
+ return 0 # Failed
-def CheckCXXHeader(test, header, include_quotes='""'):
+# Bram: Make this function obsolete? CheckHeader() is more generic.
+
+def CheckCHeader(context, header, include_quotes = '""'):
"""
- A test for a c++ header file.
+ A test for a C header file.
"""
- # ToDo: Support also system header files (i.e. #include <header.h>)
- test.Message("Checking for C++ header %s ... " % header)
- ret = test.TryCompile(_header_prog(header, include_quotes), ".cpp")
- test.Result( ret )
- return ret
+ return CheckHeader(context, header, include_quotes, language = "C")
-def CheckLib(test, library=None, symbol="main", autoadd=1):
+
+# Bram: Make this function obsolete? CheckHeader() is more generic.
+
+def CheckCXXHeader(context, header, include_quotes = '""'):
+ """
+ A test for a C++ header file.
+ """
+ return CheckHeader(context, header, include_quotes, language = "C++")
+
+
+def CheckLib(context, library = None, symbol = "main", autoadd = 1,
+ header = None, language = None):
"""
A test for a library. See also CheckLibWithHeader.
Note that library may also be None to test whether the given symbol
compiles without flags.
"""
# ToDo: accept path for the library
- test.Message("Checking for %s in library %s ... " % (symbol, library))
- oldLIBS = test.env.get( 'LIBS', [] )
-
- # NOTE: we allow this at in the case that we don't know what the
- # library is called like when we get --libs from a configure script
- if library != None:
- test.env.Append(LIBS = [ library ])
-
- text = ""
- if symbol != "main":
- text = text + """
-#ifdef __cplusplus
-extern "C"
-#endif
-char %s();""" % symbol
- text = text + """
-int
-main() {
-%s();
-return 0;
-}
-\n\n""" % symbol
-
- ret = test.TryLink( text, ".c" )
- if not autoadd or not ret:
- test.env.Replace(LIBS=oldLIBS)
-
- test.Result(ret)
- return ret
-
-def CheckLibWithHeader(test, library, header, language, call="main();", autoadd=1):
+ res = SCons.Conftest.CheckLib(context, library, symbol, header = header,
+ language = language, autoadd = autoadd)
+ context.did_show_result = 1
+ if not res:
+ return 1 # Ok
+ return 0 # Failed
+
+
+# XXX
+# Bram: Can only include one header and can't use #ifdef HAVE_HEADER_H.
+
+def CheckLibWithHeader(context, library, header, language,
+ call = "main();", autoadd = 1):
# ToDo: accept path for library. Support system header files.
"""
Another (more sophisticated) test for a library.
@@ -673,33 +698,12 @@ def CheckLibWithHeader(test, library, header, language, call="main();", autoadd=
As in CheckLib, we support library=None, to test if the call compiles
without extra link flags.
"""
- test.Message("Checking for %s in library %s (header %s) ... " %
- (call, library, header))
- oldLIBS= test.env.get( 'LIBS', [] )
-
- # NOTE: we allow this at in the case that we don't know what the
- # library is called like when we get --libs from a configure script
- if library != None:
- test.env.Append(LIBS = [ library ])
-
- text = """\
-#include "%s"
-int main() {
- %s
- return 0;
-}
-""" % (header, call)
-
- if language in ["C", "c"]:
- extension=".c"
- elif language in ["CXX", "cxx", "C++", "c++"]:
- extension=".cpp"
- else:
- raise SCons.Errors.UserError, "Unknown language!"
-
- ret = test.TryLink( text, extension)
- if not autoadd or not ret:
- test.env.Replace( LIBS = oldLIBS )
-
- test.Result(ret)
- return ret
+
+ res = SCons.Conftest.CheckLib(context, library, "main",
+ header = '#include "%s"' % header,
+ call = call, language = language, autoadd = autoadd)
+ context.did_show_result = 1
+ if not res:
+ return 1 # Ok
+ return 0 # Failed
+
diff --git a/test/Configure.py b/test/Configure.py
index feaea0b..3bad086 100644
--- a/test/Configure.py
+++ b/test/Configure.py
@@ -93,14 +93,15 @@ if not (r1 and r2 and r3 and r4 and r5 and r6):
required_stdout = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
read_str=
- """Checking for main(); in library %s (header math.h) ... ok
-Checking for main(); in library None (header math.h) ... ok
-Checking for main in library %s ... ok
-Checking for main in library None ... ok
-Checking for C header math.h ... ok
-Checking for C++ header vector ... ok
+ """Checking for main() in C library %s... yes
+Checking for main() in C library None... yes
+Checking for main() in C library %s... yes
+Checking for main() in C library None... yes
+Checking for C header file math.h... yes
+Checking for C++ header file vector... yes
""" % (lib, lib))
+
test.run(stdout = required_stdout)
checkLog(test,'config.log', 0, 0 )
@@ -109,8 +110,7 @@ Checking for C++ header vector ... ok
# 1.2 if checks are not ok, the cache mechanism should work as well
# (via explicit cache)
- reset()
-
+ reset(dot = 0) # match exactly, "()" is a regexp thing
test.write( 'SConstruct', """
env = Environment()
@@ -127,10 +127,11 @@ if not (not r1 and not r2):
required_stdout = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
read_str=
- """Checking for C header no_std_c_header.h ... failed
-Checking for main in library no_c_library_SAFFDG ... failed
+ """Checking for C header file no_std_c_header.h... no
+Checking for main() in C library no_c_library_SAFFDG... no
""")
+
test.run(stdout = required_stdout)
checkLog(test, 'config.log', 0, 0 )
@@ -164,11 +165,10 @@ int main() {
printf( "Hello\\n" );
}
""")
- test.match_func = TestCmd.match_re_dotall
required_stdout = test.wrap_stdout(build_str='.*',
read_str=
- """Checking for C header math.h ... ok
-Checking for C header no_std_c_header.h ... failed
+ """Checking for C header file math.h... yes
+Checking for C header file no_std_c_header.h... no
""")
test.run( stdout = required_stdout )
checkLog( test, 'config.log', 0, 0 )
@@ -207,8 +207,8 @@ int main() {
""")
required_stdout = test.wrap_stdout(build_str='.*',
read_str=
- """Checking for C header math.h ... ok
-Checking for C header no_std_c_header.h ... failed
+ """Checking for C header file math.h... yes
+Checking for C header file no_std_c_header.h... no
""")
test.run( stdout = required_stdout )
checkLog( test, 'build/config.log', 0, 0 )
@@ -270,8 +270,8 @@ int main() {
""")
required_stdout = test.wrap_stdout(build_str='.*',
read_str=
- """Checking for C header math.h ... ok
-Checking for C header no_std_c_header.h ... failed
+ """Checking for C header file math.h... yes
+Checking for C header file no_std_c_header.h... no
Executing Custom Test ... ok
""")
# first with SConscriptChdir(0)