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