mirror of https://github.com/roytam1/UXP
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
6.1 KiB
151 lines
6.1 KiB
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- |
|
# 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)
|
|
|