diff options
Diffstat (limited to 'build/moz.configure/compile-checks.configure')
-rw-r--r-- | build/moz.configure/compile-checks.configure | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/build/moz.configure/compile-checks.configure b/build/moz.configure/compile-checks.configure new file mode 100644 index 000000000..9f0ebcd61 --- /dev/null +++ b/build/moz.configure/compile-checks.configure @@ -0,0 +1,152 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +# Generates a test program and attempts to compile it. In case of failure, the +# resulting check will return None. If the test program succeeds, it will return +# the output of the test program. +# - `includes` are the includes (as file names) that will appear at the top of +# the generated test program. +# - `body` is the code that will appear in the main function of the generated +# test program. `return 0;` is appended to the function body automatically. +# - `language` is the language selection, so that the appropriate compiler is +# used. +# - `flags` are the flags to be passed to the compiler, in addition to `-c`. +# - `check_msg` is the message to be printed to accompany compiling the test +# program. +@template +def try_compile(includes=None, body='', language='C++', flags=None, check_msg=None, + when=None): + compiler = { + 'C': c_compiler, + 'C++': cxx_compiler, + }[language] + + return compiler.try_compile(includes, body, flags, check_msg, when=when) + + +# Checks for the presence of the given header on the target system by compiling +# a test program including that header. The return value of the template is a +# check function returning True if the header is present, and None if it is not. +# The value of this check function is also used to set a variable (with set_define) +# corresponding to the checked header. For instance, HAVE_MALLOC_H will be set in +# defines if check_header if called with 'malloc.h' as input and malloc.h is +# present on the target. +# - `header` is the header, as a file name, to check for. +# - `language` is the language selection, so that the appropriate compiler is +# used. +# - `flags` are the flags to be passed to the compiler, in addition to `-c`. +# - `includes` are additional includes, as file names, to appear before the +# header checked for. +# - `when` is a depends function that if present will make performing the check +# conditional on the value of that function. +@template +def check_header(header, language='C++', flags=None, includes=None, when=None): + when = when or always + + if includes: + includes = includes[:] + else: + includes = [] + includes.append(header) + + have_header = try_compile(includes=includes, language=language, flags=flags, + check_msg='for %s' % header, when=when) + header_var = 'HAVE_%s' % (header.upper() + .replace('-', '_') + .replace('/', '_') + .replace('.', '_')) + set_define(header_var, have_header) + return have_header + +# A convenience wrapper for check_header for checking multiple headers. +# returns an array of the resulting checks in order corresponding to the +# provided headers. +# - `headers` are the headers to be checked. +# - `kwargs` are keyword arguments passed verbatim to check_header. +@template +def check_headers(*headers, **kwargs): + checks = [] + for header in headers: + checks.append(check_header(header, **kwargs)) + return checks + + +@depends(c_compiler) +def warnings_cflags(c_compiler): + return [] + +@depends(cxx_compiler) +def warnings_cxxflags(cxx_compiler): + return [] + + +# Tests whether GCC or clang support the given warning flag, and if it is, +# add it to the list of warning flags for the build. +# - `warning` is the warning flag (e.g. -Wfoo) +# - `compiler` (optional) is the compiler to test against (c_compiler or +# cxx_compiler, from toolchain.configure). When omitted, both compilers +# are tested. +# - `when` (optional) is a @depends function or option name conditioning +# when the warning flag is wanted. +# - `check`, when not set, skips checking whether the flag is supported and +# adds it to the list of warning flags unconditionally. This is only meant +# for add_gcc_warning(). +@template +def check_and_add_gcc_warning(warning, compiler=None, when=None, check=True): + if compiler: + compilers = (compiler,) + else: + compilers = (c_compiler, cxx_compiler) + + when = when or always + + for c in compilers: + assert c in (c_compiler, cxx_compiler) + lang, warnings_flags = { + c_compiler: ('C', warnings_cflags), + cxx_compiler: ('C++', warnings_cxxflags), + }[c] + + # GCC and clang will fail if given an unknown warning option like + # -Wfoobar. But later versions won't fail if given an unknown negated + # warning option like -Wno-foobar. So when we are checking for support + # of a negated warning option, we actually test the positive form, but + # add the negated form to the flags variable. + if (warning.startswith('-Wno-') and + not warning.startswith('-Wno-error=')): + flags = ['-Werror', '-W' + warning[5:]] + elif warning.startswith('-Werror='): + flags = [warning] + else: + flags = ['-Werror', warning] + + @depends(c, when) + def result(c, when): + if when and c.type in ('clang', 'gcc'): + return True + + if check: + result = c.try_compile( + flags=flags, when=result, + check_msg='whether the %s compiler supports %s' % (lang, + warning)) + + @depends(result, warnings_flags) + def maybe_add_flag(result, warnings_flags): + if result: + warnings_flags.append(warning) + +# Add the given warning to the list of warning flags for the build. +# - `warning` is the warning flag (e.g. -Wfoo) +# - `compiler` (optional) is the compiler to add the flag for (c_compiler or +# cxx_compiler, from toolchain.configure). When omitted, the warning flag +# is added for both compilers. +# - `when` (optional) is a @depends function or option name conditioning +# when the warning flag is wanted. +@template +def add_gcc_warning(warning, compiler=None, when=None): + check_and_add_gcc_warning(warning, compiler, when, check=False) |