summaryrefslogtreecommitdiffstats
path: root/build/moz.configure/compilers-util.configure
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--build/moz.configure/compilers-util.configure204
1 files changed, 204 insertions, 0 deletions
diff --git a/build/moz.configure/compilers-util.configure b/build/moz.configure/compilers-util.configure
new file mode 100644
index 0000000000..598de3dc80
--- /dev/null
+++ b/build/moz.configure/compilers-util.configure
@@ -0,0 +1,204 @@
+# -*- 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