Update items for 0.97.0d20071212.
[scons.git] / src / engine / SCons / Conftest.py
1 """SCons.Conftest
2
3 Autoconf-like configuration support; low level implementation of tests.
4 """
5
6 #
7 # Copyright (c) 2003 Stichting NLnet Labs
8 # Copyright (c) 2001, 2002, 2003 Steven Knight
9 #
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:
17 #
18 # The above copyright notice and this permission notice shall be included
19 # in all copies or substantial portions of the Software.
20 #
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.
28 #
29
30 #
31 # The purpose of this module is to define how a check is to be performed.
32 # Use one of the Check...() functions below.
33 #
34
35 #
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:
38 #
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!
42 #
43 # context.Log(msg)      Function called to write to a log file.
44 #
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
52 #                       far).
53 #
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
61 #                       so far).
62 #
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.
68 #
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.
74 #
75 # context.headerfilename
76 #                       Name of file to append configure results to, usually
77 #                       "confdefs.h".
78 #                       The file must not exist or be empty when starting.
79 #                       Empty or None to skip this (some tests will not work!).
80 #
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.
83 #
84 # context.vardict       Dictionary holding variables used for the tests and
85 #                       stores results from the tests, used for the build
86 #                       commands.
87 #                       Normally contains "CC", "LIBS", "CPPFLAGS", etc.
88 #
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.
95 #
96
97 import re
98 import string
99 from types import IntType
100
101 #
102 # PUBLIC VARIABLES
103 #
104
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
107
108 #
109 # PUBLIC FUNCTIONS
110 #
111
112 # Generic remarks:
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).
116
117
118 def CheckBuilder(context, text = None, language = None):
119     """
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.
124     Default is "C".
125     "text" may be used to specify the code to be build.
126     Returns an empty string for success, an error message for failure.
127     """
128     lang, suffix, msg = _lang2suffix(language)
129     if msg:
130         context.Display("%s\n" % msg)
131         return msg
132
133     if not text:
134         text = """
135 int main() {
136     return 0;
137 }
138 """
139
140     context.Display("Checking if building a %s file works... " % lang)
141     ret = context.BuildProg(text, suffix)
142     _YesNoResult(context, ret, None, text)
143     return ret
144
145
146 def CheckFunc(context, function_name, header = None, language = None):
147     """
148     Configure check for a function "function_name".
149     "language" should be "C" or "C++" and is used to select the compiler.
150     Default is "C".
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.
157     """
158
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
168     #   still apply.
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.
172
173     if context.headerfilename:
174         includetext = '#include "%s"' % context.headerfilename
175     else:
176         includetext = ''
177     if not header:
178         header = """
179 #ifdef __cplusplus
180 extern "C"
181 #endif
182 char %s();""" % function_name
183
184     lang, suffix, msg = _lang2suffix(language)
185     if msg:
186         context.Display("Cannot check for %s(): %s\n" % (function_name, msg))
187         return msg
188
189     text = """
190 %(include)s
191 #include <assert.h>
192 %(hdr)s
193
194 int main() {
195 #if defined (__stub_%(name)s) || defined (__stub___%(name)s)
196   fail fail fail
197 #else
198   %(name)s();
199 #endif
200
201   return 0;
202 }
203 """ % { 'name': function_name,
204         'include': includetext,
205         'hdr': header }
206
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)
210     return ret
211
212
213 def CheckHeader(context, header_name, header = None, language = None,
214                                                         include_quotes = None):
215     """
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.
220     Default is "C".
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.
225     """
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.
230     #
231     # Use <> by default, because the check is normally used for system header
232     # files.  SCons passes '""' to overrule this.
233
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
237     else:
238         includetext = ''
239     if not header:
240         header = ""
241
242     lang, suffix, msg = _lang2suffix(language)
243     if msg:
244         context.Display("Cannot check for header file %s: %s\n"
245                                                           % (header_name, msg))
246         return msg
247
248     if not include_quotes:
249         include_quotes = "<>"
250
251     text = "%s%s\n#include %s%s%s\n\n" % (includetext, header,
252                              include_quotes[0], header_name, include_quotes[1])
253
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)
257     return ret
258
259
260 def CheckType(context, type_name, fallback = None,
261                                                header = None, language = None):
262     """
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.
266     Default is "C".
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.
271     """
272
273     # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
274     if context.headerfilename:
275         includetext = '#include "%s"' % context.headerfilename
276     else:
277         includetext = ''
278     if not header:
279         header = ""
280
281     lang, suffix, msg = _lang2suffix(language)
282     if msg:
283         context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
284         return msg
285
286     # Remarks from autoconf about this test:
287     # - Grepping for the type in include files is not reliable (grep isn't
288     #   portable anyway).
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
292     #   C++.
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.
297     text = """
298 %(include)s
299 %(header)s
300
301 int main() {
302   if ((%(name)s *) 0)
303     return 0;
304   if (sizeof (%(name)s))
305     return 0;
306 }
307 """ % { 'include': includetext,
308         'header': header,
309         'name': type_name }
310
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))
317         f.close()
318
319     return ret
320
321
322 def CheckLib(context, libs, func_name = None, header = None,
323                  extra_libs = None, call = None, language = None, autoadd = 1):
324     """
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"
333     depends on.
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.
339     Default is "C".
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.
343     """
344     # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
345     if context.headerfilename:
346         includetext = '#include "%s"' % context.headerfilename
347     else:
348         includetext = ''
349     if not header:
350         header = ""
351
352     text = """
353 %s
354 %s""" % (includetext, header)
355
356     # Add a function declaration if needed.
357     if func_name and func_name != "main":
358         if not header:
359             text = text + """
360 #ifdef __cplusplus
361 extern "C"
362 #endif
363 char %s();
364 """ % func_name
365
366         # The actual test code.
367         if not call:
368             call = "%s();" % func_name
369
370     # if no function to test, leave main() blank
371     text = text + """
372 int
373 main() {
374   %s
375 return 0;
376 }
377 """ % (call or "")
378
379     if call:
380         i = string.find(call, "\n")
381         if i > 0:
382             calltext = call[:i] + ".."
383         elif call[-1] == ';':
384             calltext = call[:-1]
385         else:
386             calltext = call
387
388     for lib_name in libs:
389
390         lang, suffix, msg = _lang2suffix(language)
391         if msg:
392             context.Display("Cannot check for library %s: %s\n" % (lib_name, msg))
393             return msg
394
395         # if a function was specified to run in main(), say it
396         if call:
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
400         else:
401                 context.Display("Checking for %s library %s... "
402                                 % (lang, lib_name))
403
404         if lib_name:
405             l = [ lib_name ]
406             if extra_libs:
407                 l.extend(extra_libs)
408             oldLIBS = context.AppendLIBS(l)
409             sym = "HAVE_LIB" + lib_name
410         else:
411             oldLIBS = -1
412             sym = None
413
414         ret = context.BuildProg(text, suffix)
415
416         _YesNoResult(context, ret, sym, text)
417         if oldLIBS != -1 and (ret or not autoadd):
418             context.SetLIBS(oldLIBS)
419             
420         if not ret:
421             return ret
422
423     return ret
424
425 #
426 # END OF PUBLIC FUNCTIONS
427 #
428
429 def _YesNoResult(context, ret, key, text):
430     """
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.
435     """
436     if key:
437         _Have(context, key, not ret)
438     if ret:
439         context.Display("no\n")
440         _LogFailed(context, text, ret)
441     else:
442         context.Display("yes\n")
443
444
445 def _Have(context, key, have):
446     """
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!
460     """
461     key_up = string.upper(key)
462     key_up = re.sub('[^A-Z0-9_]', '_', key_up)
463     context.havedict[key_up] = have
464     if have == 1:
465         line = "#define %s 1\n" % key_up
466     elif have == 0:
467         line = "/* #undef %s */\n" % key_up
468     elif type(have) == IntType:
469         line = "#define %s %d\n" % (key_up, have)
470     else:
471         line = "#define %s %s\n" % (key_up, str(have))
472     
473     if context.headerfilename:
474         f = open(context.headerfilename, "a")
475         f.write(line)
476         f.close()
477     elif hasattr(context,'config_h'):
478         context.config_h = context.config_h + line
479
480
481 def _LogFailed(context, text, msg):
482     """
483     Write to the log about a failed program.
484     Add line numbers, so that error messages can be understood.
485     """
486     if LogInputFiles:
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
491         n = 1
492         for line in lines:
493             context.Log("%d: %s\n" % (n, line))
494             n = n + 1
495     if LogErrorMessages:
496         context.Log("Error message: %s\n" % msg)
497
498
499 def _lang2suffix(lang):
500     """
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).
505     Where:
506         lang   = the unified language name
507         suffix = the suffix, including the leading dot
508         msg    = an error message
509     """
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)
514
515     return None, None, "Unsupported language: %s" % lang
516
517
518 # vim: set sw=4 et sts=4 tw=79 fo+=l: