summaryrefslogtreecommitdiff
path: root/build/moz.configure/compile-checks.configure
diff options
context:
space:
mode:
Diffstat (limited to 'build/moz.configure/compile-checks.configure')
-rw-r--r--build/moz.configure/compile-checks.configure152
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 0000000000..9f0ebcd61d
--- /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)