Source code

Revision control

Copy as Markdown

Other Tools

# -*- Mode: python; 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/.
@template
@imports("textwrap")
@imports(_from="mozbuild.configure", _import="SandboxDependsFunction")
def compiler_class(compiler, host_or_target):
is_target = host_or_target is target
class Compiler(SandboxDependsFunction):
def _try_compile_or_link(
self,
includes,
body,
flags,
ldflags,
check_msg,
when,
onerror,
):
if ldflags is None:
@depends(dependable(flags))
def flags(flags):
flags = list(flags or [])
flags.append("-c")
return flags
else:
@depends(compiler, dependable(ldflags), dependable(flags), when=when)
def flags(compiler, ldflags, flags):
if compiler.type == "clang-cl":
configure_error(
"checking linker flags for clang-cl is not supported yet"
)
flags = list(flags or [])
flags.extend(ldflags)
return flags
@depends(dependable(includes))
def header(includes):
includes = includes or []
return ["#include <%s>" % f for f in includes]
return self.try_run(
header=header,
body=body,
flags=flags,
check_msg=check_msg,
when=when,
onerror=onerror,
)
# 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.
# - `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.
def try_compile(
self,
includes=None,
body="",
flags=None,
check_msg=None,
when=None,
onerror=lambda: None,
):
return self._try_compile_or_link(
includes=includes,
body=body,
flags=flags,
ldflags=None,
check_msg=check_msg,
when=when,
onerror=onerror,
)
# Same steps as try_compile but doesn't add "-c"
def try_link(
self,
ldflags,
includes=None,
body="",
flags=None,
check_msg=None,
when=None,
onerror=lambda: None,
):
return self._try_compile_or_link(
includes=includes,
body=body,
flags=flags,
ldflags=ldflags,
check_msg=check_msg,
when=when,
onerror=onerror,
)
# Generates a test program and run the compiler against it. In case of
# failure, the resulting check will return None.
# - `header` is code 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.
# - `flags` are the flags to be passed to the compiler.
# - `check_msg` is the message to be printed to accompany compiling the
# test program.
# - `onerror` is a function called when the check fails.
def try_run(
self,
header=None,
body="",
flags=None,
check_msg=None,
when=None,
onerror=lambda: None,
):
source = textwrap.dedent(
"""\
int
main(void)
{
%s
;
return 0;
}
"""
% body
)
if check_msg:
def checking_fn(fn):
return checking(check_msg)(fn)
else:
def checking_fn(fn):
return fn
# We accept onerror being a @depends function that returns a callable.
# So, create a similar @depends function when it's not already one.
if not isinstance(onerror, SandboxDependsFunction):
onerror = dependable(lambda: onerror)
@depends(
self,
dependable(flags),
extra_toolchain_flags,
dependable(header),
onerror,
configure_cache,
when=when,
)
@checking_fn
def func(
compiler,
flags,
extra_flags,
header,
onerror,
configure_cache,
):
flags = list(flags or [])
if is_target:
flags += extra_flags or []
header = header or ""
if isinstance(header, (list, tuple)):
header = "\n".join(header)
if header:
header += "\n"
if (
try_invoke_compiler(
configure_cache,
[compiler.compiler] + compiler.flags,
compiler.language,
header + source,
flags,
onerror=onerror,
wrapper=compiler.wrapper,
)
is not None
):
return True
return func
compiler.__class__ = Compiler
return compiler