9221e2faf49f41fe0bf6911f14e000fb54b78f60
[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.PrependLIBS(lib_name_list)
70 #                       Prepend "lib_name_list" to the value of LIBS.
71 #                       "lib_namelist" is a list of strings.
72 #                       Return the value of LIBS before changing it (any type
73 #                       can be used, it is passed to SetLIBS() later.)
74 #
75 # context.SetLIBS(value)
76 #                       Set LIBS to "value".  The type of "value" is what
77 #                       AppendLIBS() returned.
78 #                       Return the value of LIBS before changing it (any type
79 #                       can be used, it is passed to SetLIBS() later.)
80 #
81 # context.headerfilename
82 #                       Name of file to append configure results to, usually
83 #                       "confdefs.h".
84 #                       The file must not exist or be empty when starting.
85 #                       Empty or None to skip this (some tests will not work!).
86 #
87 # context.config_h      (may be missing). If present, must be a string, which
88 #                       will be filled with the contents of a config_h file.
89 #
90 # context.vardict       Dictionary holding variables used for the tests and
91 #                       stores results from the tests, used for the build
92 #                       commands.
93 #                       Normally contains "CC", "LIBS", "CPPFLAGS", etc.
94 #
95 # context.havedict      Dictionary holding results from the tests that are to
96 #                       be used inside a program.
97 #                       Names often start with "HAVE_".  These are zero
98 #                       (feature not present) or one (feature present).  Other
99 #                       variables may have any value, e.g., "PERLVERSION" can
100 #                       be a number and "SYSTEMNAME" a string.
101 #
102
103 import re
104 from types import IntType
105
106 #
107 # PUBLIC VARIABLES
108 #
109
110 LogInputFiles = 1    # Set that to log the input files in case of a failed test
111 LogErrorMessages = 1 # Set that to log Conftest-generated error messages
112
113 #
114 # PUBLIC FUNCTIONS
115 #
116
117 # Generic remarks:
118 # - When a language is specified which is not supported the test fails.  The
119 #   message is a bit different, because not all the arguments for the normal
120 #   message are available yet (chicken-egg problem).
121
122
123 def CheckBuilder(context, text = None, language = None):
124     """
125     Configure check to see if the compiler works.
126     Note that this uses the current value of compiler and linker flags, make
127     sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
128     "language" should be "C" or "C++" and is used to select the compiler.
129     Default is "C".
130     "text" may be used to specify the code to be build.
131     Returns an empty string for success, an error message for failure.
132     """
133     lang, suffix, msg = _lang2suffix(language)
134     if msg:
135         context.Display("%s\n" % msg)
136         return msg
137
138     if not text:
139         text = """
140 int main() {
141     return 0;
142 }
143 """
144
145     context.Display("Checking if building a %s file works... " % lang)
146     ret = context.BuildProg(text, suffix)
147     _YesNoResult(context, ret, None, text)
148     return ret
149
150 def CheckCC(context):
151     """
152     Configure check for a working C compiler.
153
154     This checks whether the C compiler, as defined in the $CC construction
155     variable, can compile a C source file. It uses the current $CCCOM value
156     too, so that it can test against non working flags.
157
158     """
159     context.Display("Checking whether the C compiler works")
160     text = """
161 int main()
162 {
163     return 0;
164 }
165 """
166     ret = _check_empty_program(context, 'CC', text, 'C')
167     _YesNoResult(context, ret, None, text)
168     return ret
169
170 def CheckSHCC(context):
171     """
172     Configure check for a working shared C compiler.
173
174     This checks whether the C compiler, as defined in the $SHCC construction
175     variable, can compile a C source file. It uses the current $SHCCCOM value
176     too, so that it can test against non working flags.
177
178     """
179     context.Display("Checking whether the (shared) C compiler works")
180     text = """
181 int foo()
182 {
183     return 0;
184 }
185 """
186     ret = _check_empty_program(context, 'SHCC', text, 'C', use_shared = True)
187     _YesNoResult(context, ret, None, text)
188     return ret
189
190 def CheckCXX(context):
191     """
192     Configure check for a working CXX compiler.
193
194     This checks whether the CXX compiler, as defined in the $CXX construction
195     variable, can compile a CXX source file. It uses the current $CXXCOM value
196     too, so that it can test against non working flags.
197
198     """
199     context.Display("Checking whether the C++ compiler works")
200     text = """
201 int main()
202 {
203     return 0;
204 }
205 """
206     ret = _check_empty_program(context, 'CXX', text, 'C++')
207     _YesNoResult(context, ret, None, text)
208     return ret
209
210 def CheckSHCXX(context):
211     """
212     Configure check for a working shared CXX compiler.
213
214     This checks whether the CXX compiler, as defined in the $SHCXX construction
215     variable, can compile a CXX source file. It uses the current $SHCXXCOM value
216     too, so that it can test against non working flags.
217
218     """
219     context.Display("Checking whether the (shared) C++ compiler works")
220     text = """
221 int main()
222 {
223     return 0;
224 }
225 """
226     ret = _check_empty_program(context, 'SHCXX', text, 'C++', use_shared = True)
227     _YesNoResult(context, ret, None, text)
228     return ret
229
230 def _check_empty_program(context, comp, text, language, use_shared = False):
231     """Return 0 on success, 1 otherwise."""
232     if comp not in context.env or not context.env[comp]:
233         # The compiler construction variable is not set or empty
234         return 1
235
236     lang, suffix, msg = _lang2suffix(language)
237     if msg:
238         return 1
239
240     if use_shared:
241         return context.CompileSharedObject(text, suffix)
242     else:
243         return context.CompileProg(text, suffix)
244
245
246 def CheckFunc(context, function_name, header = None, language = None):
247     """
248     Configure check for a function "function_name".
249     "language" should be "C" or "C++" and is used to select the compiler.
250     Default is "C".
251     Optional "header" can be defined to define a function prototype, include a
252     header file or anything else that comes before main().
253     Sets HAVE_function_name in context.havedict according to the result.
254     Note that this uses the current value of compiler and linker flags, make
255     sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
256     Returns an empty string for success, an error message for failure.
257     """
258
259     # Remarks from autoconf:
260     # - Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h>
261     #   which includes <sys/select.h> which contains a prototype for select.
262     #   Similarly for bzero.
263     # - assert.h is included to define __stub macros and hopefully few
264     #   prototypes, which can conflict with char $1(); below.
265     # - Override any gcc2 internal prototype to avoid an error.
266     # - We use char for the function declaration because int might match the
267     #   return type of a gcc2 builtin and then its argument prototype would
268     #   still apply.
269     # - The GNU C library defines this for functions which it implements to
270     #   always fail with ENOSYS.  Some functions are actually named something
271     #   starting with __ and the normal name is an alias.
272
273     if context.headerfilename:
274         includetext = '#include "%s"' % context.headerfilename
275     else:
276         includetext = ''
277     if not header:
278         header = """
279 #ifdef __cplusplus
280 extern "C"
281 #endif
282 char %s();""" % function_name
283
284     lang, suffix, msg = _lang2suffix(language)
285     if msg:
286         context.Display("Cannot check for %s(): %s\n" % (function_name, msg))
287         return msg
288
289     text = """
290 %(include)s
291 #include <assert.h>
292 %(hdr)s
293
294 int main() {
295 #if defined (__stub_%(name)s) || defined (__stub___%(name)s)
296   fail fail fail
297 #else
298   %(name)s();
299 #endif
300
301   return 0;
302 }
303 """ % { 'name': function_name,
304         'include': includetext,
305         'hdr': header }
306
307     context.Display("Checking for %s function %s()... " % (lang, function_name))
308     ret = context.BuildProg(text, suffix)
309     _YesNoResult(context, ret, "HAVE_" + function_name, text,
310                  "Define to 1 if the system has the function `%s'." %\
311                  function_name)
312     return ret
313
314
315 def CheckHeader(context, header_name, header = None, language = None,
316                                                         include_quotes = None):
317     """
318     Configure check for a C or C++ header file "header_name".
319     Optional "header" can be defined to do something before including the
320     header file (unusual, supported for consistency).
321     "language" should be "C" or "C++" and is used to select the compiler.
322     Default is "C".
323     Sets HAVE_header_name in context.havedict according to the result.
324     Note that this uses the current value of compiler and linker flags, make
325     sure $CFLAGS and $CPPFLAGS are set correctly.
326     Returns an empty string for success, an error message for failure.
327     """
328     # Why compile the program instead of just running the preprocessor?
329     # It is possible that the header file exists, but actually using it may
330     # fail (e.g., because it depends on other header files).  Thus this test is
331     # more strict.  It may require using the "header" argument.
332     #
333     # Use <> by default, because the check is normally used for system header
334     # files.  SCons passes '""' to overrule this.
335
336     # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
337     if context.headerfilename:
338         includetext = '#include "%s"\n' % context.headerfilename
339     else:
340         includetext = ''
341     if not header:
342         header = ""
343
344     lang, suffix, msg = _lang2suffix(language)
345     if msg:
346         context.Display("Cannot check for header file %s: %s\n"
347                                                           % (header_name, msg))
348         return msg
349
350     if not include_quotes:
351         include_quotes = "<>"
352
353     text = "%s%s\n#include %s%s%s\n\n" % (includetext, header,
354                              include_quotes[0], header_name, include_quotes[1])
355
356     context.Display("Checking for %s header file %s... " % (lang, header_name))
357     ret = context.CompileProg(text, suffix)
358     _YesNoResult(context, ret, "HAVE_" + header_name, text, 
359                  "Define to 1 if you have the <%s> header file." % header_name)
360     return ret
361
362
363 def CheckType(context, type_name, fallback = None,
364                                                header = None, language = None):
365     """
366     Configure check for a C or C++ type "type_name".
367     Optional "header" can be defined to include a header file.
368     "language" should be "C" or "C++" and is used to select the compiler.
369     Default is "C".
370     Sets HAVE_type_name in context.havedict according to the result.
371     Note that this uses the current value of compiler and linker flags, make
372     sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
373     Returns an empty string for success, an error message for failure.
374     """
375
376     # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
377     if context.headerfilename:
378         includetext = '#include "%s"' % context.headerfilename
379     else:
380         includetext = ''
381     if not header:
382         header = ""
383
384     lang, suffix, msg = _lang2suffix(language)
385     if msg:
386         context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
387         return msg
388
389     # Remarks from autoconf about this test:
390     # - Grepping for the type in include files is not reliable (grep isn't
391     #   portable anyway).
392     # - Using "TYPE my_var;" doesn't work for const qualified types in C++.
393     #   Adding an initializer is not valid for some C++ classes.
394     # - Using the type as parameter to a function either fails for K&$ C or for
395     #   C++.
396     # - Using "TYPE *my_var;" is valid in C for some types that are not
397     #   declared (struct something).
398     # - Using "sizeof(TYPE)" is valid when TYPE is actually a variable.
399     # - Using the previous two together works reliably.
400     text = """
401 %(include)s
402 %(header)s
403
404 int main() {
405   if ((%(name)s *) 0)
406     return 0;
407   if (sizeof (%(name)s))
408     return 0;
409 }
410 """ % { 'include': includetext,
411         'header': header,
412         'name': type_name }
413
414     context.Display("Checking for %s type %s... " % (lang, type_name))
415     ret = context.BuildProg(text, suffix)
416     _YesNoResult(context, ret, "HAVE_" + type_name, text,
417                  "Define to 1 if the system has the type `%s'." % type_name)
418     if ret and fallback and context.headerfilename:
419         f = open(context.headerfilename, "a")
420         f.write("typedef %s %s;\n" % (fallback, type_name))
421         f.close()
422
423     return ret
424
425 def CheckTypeSize(context, type_name, header = None, language = None, expect = None):
426     """This check can be used to get the size of a given type, or to check whether
427     the type is of expected size.
428
429     Arguments:
430         - type : str
431             the type to check
432         - includes : sequence
433             list of headers to include in the test code before testing the type
434         - language : str
435             'C' or 'C++'
436         - expect : int
437             if given, will test wether the type has the given number of bytes.
438             If not given, will automatically find the size.
439
440         Returns:
441             status : int
442                 0 if the check failed, or the found size of the type if the check succeeded."""
443     
444     # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
445     if context.headerfilename:
446         includetext = '#include "%s"' % context.headerfilename
447     else:
448         includetext = ''
449
450     if not header:
451         header = ""
452
453     lang, suffix, msg = _lang2suffix(language)
454     if msg:
455         context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
456         return msg
457
458     src = includetext + header 
459     if not expect is None:
460         # Only check if the given size is the right one
461         context.Display('Checking %s is %d bytes... ' % (type_name, expect))
462
463         # test code taken from autoconf: this is a pretty clever hack to find that
464         # a type is of a given size using only compilation. This speeds things up
465         # quite a bit compared to straightforward code using TryRun
466         src = src + r"""
467 typedef %s scons_check_type;
468
469 int main()
470 {
471     static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %d)];
472     test_array[0] = 0;
473
474     return 0;
475 }
476 """
477
478         st = context.CompileProg(src % (type_name, expect), suffix)
479         if not st:
480             context.Display("yes\n")
481             _Have(context, "SIZEOF_%s" % type_name, expect, 
482                   "The size of `%s', as computed by sizeof." % type_name)
483             return expect
484         else:
485             context.Display("no\n")
486             _LogFailed(context, src, st)
487             return 0
488     else:
489         # Only check if the given size is the right one
490         context.Message('Checking size of %s ... ' % type_name)
491
492         # We have to be careful with the program we wish to test here since
493         # compilation will be attempted using the current environment's flags.
494         # So make sure that the program will compile without any warning. For
495         # example using: 'int main(int argc, char** argv)' will fail with the
496         # '-Wall -Werror' flags since the variables argc and argv would not be
497         # used in the program...
498         #
499         src = src + """
500 #include <stdlib.h>
501 #include <stdio.h>
502 int main() {
503     printf("%d", (int)sizeof(""" + type_name + """));
504     return 0;
505 }
506     """
507         st, out = context.RunProg(src, suffix)
508         try:
509             size = int(out)
510         except ValueError:
511             # If cannot convert output of test prog to an integer (the size),
512             # something went wront, so just fail
513             st = 1
514             size = 0
515
516         if not st:
517             context.Display("yes\n")
518             _Have(context, "SIZEOF_%s" % type_name, size,
519                   "The size of `%s', as computed by sizeof." % type_name)
520             return size
521         else:
522             context.Display("no\n")
523             _LogFailed(context, src, st)
524             return 0
525
526     return 0
527
528 def CheckDeclaration(context, symbol, includes = None, language = None):
529     """Checks whether symbol is declared.
530
531     Use the same test as autoconf, that is test whether the symbol is defined
532     as a macro or can be used as an r-value.
533
534     Arguments:
535         symbol : str
536             the symbol to check
537         includes : str
538             Optional "header" can be defined to include a header file.
539         language : str
540             only C and C++ supported.
541
542     Returns:
543         status : bool
544             True if the check failed, False if succeeded."""
545     
546     # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
547     if context.headerfilename:
548         includetext = '#include "%s"' % context.headerfilename
549     else:
550         includetext = ''
551
552     if not includes:
553         includes = ""
554
555     lang, suffix, msg = _lang2suffix(language)
556     if msg:
557         context.Display("Cannot check for declaration %s: %s\n" % (type_name, msg))
558         return msg
559
560     src = includetext + includes 
561     context.Display('Checking whether %s is declared... ' % symbol)
562
563     src = src + r"""
564 int main()
565 {
566 #ifndef %s
567     (void) %s;
568 #endif
569     ;
570     return 0;
571 }
572 """ % (symbol, symbol)
573
574     st = context.CompileProg(src, suffix)
575     _YesNoResult(context, st, "HAVE_DECL_" + symbol, src,
576                  "Set to 1 if %s is defined." % symbol)
577     return st
578
579 def CheckLib(context, libs, func_name = None, header = None,
580              extra_libs = None, call = None, language = None, autoadd = 1,
581              append = True):
582     """
583     Configure check for a C or C++ libraries "libs".  Searches through
584     the list of libraries, until one is found where the test succeeds.
585     Tests if "func_name" or "call" exists in the library.  Note: if it exists
586     in another library the test succeeds anyway!
587     Optional "header" can be defined to include a header file.  If not given a
588     default prototype for "func_name" is added.
589     Optional "extra_libs" is a list of library names to be added after
590     "lib_name" in the build command.  To be used for libraries that "lib_name"
591     depends on.
592     Optional "call" replaces the call to "func_name" in the test code.  It must
593     consist of complete C statements, including a trailing ";".
594     Both "func_name" and "call" arguments are optional, and in that case, just
595     linking against the libs is tested.
596     "language" should be "C" or "C++" and is used to select the compiler.
597     Default is "C".
598     Note that this uses the current value of compiler and linker flags, make
599     sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
600     Returns an empty string for success, an error message for failure.
601     """
602     # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
603     if context.headerfilename:
604         includetext = '#include "%s"' % context.headerfilename
605     else:
606         includetext = ''
607     if not header:
608         header = ""
609
610     text = """
611 %s
612 %s""" % (includetext, header)
613
614     # Add a function declaration if needed.
615     if func_name and func_name != "main":
616         if not header:
617             text = text + """
618 #ifdef __cplusplus
619 extern "C"
620 #endif
621 char %s();
622 """ % func_name
623
624         # The actual test code.
625         if not call:
626             call = "%s();" % func_name
627
628     # if no function to test, leave main() blank
629     text = text + """
630 int
631 main() {
632   %s
633 return 0;
634 }
635 """ % (call or "")
636
637     if call:
638         i = call.find("\n")
639         if i > 0:
640             calltext = call[:i] + ".."
641         elif call[-1] == ';':
642             calltext = call[:-1]
643         else:
644             calltext = call
645
646     for lib_name in libs:
647
648         lang, suffix, msg = _lang2suffix(language)
649         if msg:
650             context.Display("Cannot check for library %s: %s\n" % (lib_name, msg))
651             return msg
652
653         # if a function was specified to run in main(), say it
654         if call:
655                 context.Display("Checking for %s in %s library %s... "
656                                 % (calltext, lang, lib_name))
657         # otherwise, just say the name of library and language
658         else:
659                 context.Display("Checking for %s library %s... "
660                                 % (lang, lib_name))
661
662         if lib_name:
663             l = [ lib_name ]
664             if extra_libs:
665                 l.extend(extra_libs)
666             if append:
667                 oldLIBS = context.AppendLIBS(l)
668             else:
669                 oldLIBS = context.PrependLIBS(l)
670             sym = "HAVE_LIB" + lib_name
671         else:
672             oldLIBS = -1
673             sym = None
674
675         ret = context.BuildProg(text, suffix)
676
677         _YesNoResult(context, ret, sym, text,
678                      "Define to 1 if you have the `%s' library." % lib_name)
679         if oldLIBS != -1 and (ret or not autoadd):
680             context.SetLIBS(oldLIBS)
681             
682         if not ret:
683             return ret
684
685     return ret
686
687 #
688 # END OF PUBLIC FUNCTIONS
689 #
690
691 def _YesNoResult(context, ret, key, text, comment = None):
692     """
693     Handle the result of a test with a "yes" or "no" result.
694     "ret" is the return value: empty if OK, error message when not.
695     "key" is the name of the symbol to be defined (HAVE_foo).
696     "text" is the source code of the program used for testing.
697     "comment" is the C comment to add above the line defining the symbol (the
698     comment is automatically put inside a /* */). If None, no comment is added.
699     """
700     if key:
701         _Have(context, key, not ret, comment)
702     if ret:
703         context.Display("no\n")
704         _LogFailed(context, text, ret)
705     else:
706         context.Display("yes\n")
707
708
709 def _Have(context, key, have, comment = None):
710     """
711     Store result of a test in context.havedict and context.headerfilename.
712     "key" is a "HAVE_abc" name.  It is turned into all CAPITALS and non-
713     alphanumerics are replaced by an underscore.
714     The value of "have" can be:
715     1      - Feature is defined, add "#define key".
716     0      - Feature is not defined, add "/* #undef key */".
717              Adding "undef" is what autoconf does.  Not useful for the
718              compiler, but it shows that the test was done.
719     number - Feature is defined to this number "#define key have".
720              Doesn't work for 0 or 1, use a string then.
721     string - Feature is defined to this string "#define key have".
722              Give "have" as is should appear in the header file, include quotes
723              when desired and escape special characters!
724     """
725     key_up = key.upper()
726     key_up = re.sub('[^A-Z0-9_]', '_', key_up)
727     context.havedict[key_up] = have
728     if have == 1:
729         line = "#define %s 1\n" % key_up
730     elif have == 0:
731         line = "/* #undef %s */\n" % key_up
732     elif type(have) == IntType:
733         line = "#define %s %d\n" % (key_up, have)
734     else:
735         line = "#define %s %s\n" % (key_up, str(have))
736     
737     if comment is not None:
738         lines = "\n/* %s */\n" % comment + line
739     else:
740         lines = "\n" + line
741
742     if context.headerfilename:
743         f = open(context.headerfilename, "a")
744         f.write(lines)
745         f.close()
746     elif hasattr(context,'config_h'):
747         context.config_h = context.config_h + lines
748
749
750 def _LogFailed(context, text, msg):
751     """
752     Write to the log about a failed program.
753     Add line numbers, so that error messages can be understood.
754     """
755     if LogInputFiles:
756         context.Log("Failed program was:\n")
757         lines = text.split('\n')
758         if len(lines) and lines[-1] == '':
759             lines = lines[:-1]              # remove trailing empty line
760         n = 1
761         for line in lines:
762             context.Log("%d: %s\n" % (n, line))
763             n = n + 1
764     if LogErrorMessages:
765         context.Log("Error message: %s\n" % msg)
766
767
768 def _lang2suffix(lang):
769     """
770     Convert a language name to a suffix.
771     When "lang" is empty or None C is assumed.
772     Returns a tuple (lang, suffix, None) when it works.
773     For an unrecognized language returns (None, None, msg).
774     Where:
775         lang   = the unified language name
776         suffix = the suffix, including the leading dot
777         msg    = an error message
778     """
779     if not lang or lang in ["C", "c"]:
780         return ("C", ".c", None)
781     if lang in ["c++", "C++", "cpp", "CXX", "cxx"]:
782         return ("C++", ".cpp", None)
783
784     return None, None, "Unsupported language: %s" % lang
785
786
787 # vim: set sw=4 et sts=4 tw=79 fo+=l:
788
789 # Local Variables:
790 # tab-width:4
791 # indent-tabs-mode:nil
792 # End:
793 # vim: set expandtab tabstop=4 shiftwidth=4: