Bug 1883861 - Part 1: Move visitMemoryBarrier into the common CodeGenerator file...
[gecko.git] / build / moz.configure / compilers-util.configure
blob598de3dc8054e420f949c5d4b90a62ecb29230dc
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
2 # vim: set filetype=python:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 @template
9 @imports("textwrap")
10 @imports(_from="mozbuild.configure", _import="SandboxDependsFunction")
11 def compiler_class(compiler, host_or_target):
12     is_target = host_or_target is target
14     class Compiler(SandboxDependsFunction):
15         def _try_compile_or_link(
16             self,
17             includes,
18             body,
19             flags,
20             ldflags,
21             check_msg,
22             when,
23             onerror,
24         ):
25             if ldflags is None:
27                 @depends(dependable(flags))
28                 def flags(flags):
29                     flags = list(flags or [])
30                     flags.append("-c")
31                     return flags
33             else:
35                 @depends(compiler, dependable(ldflags), dependable(flags), when=when)
36                 def flags(compiler, ldflags, flags):
37                     if compiler.type == "clang-cl":
38                         configure_error(
39                             "checking linker flags for clang-cl is not supported yet"
40                         )
42                     flags = list(flags or [])
43                     flags.extend(ldflags)
44                     return flags
46             @depends(dependable(includes))
47             def header(includes):
48                 includes = includes or []
49                 return ["#include <%s>" % f for f in includes]
51             return self.try_run(
52                 header=header,
53                 body=body,
54                 flags=flags,
55                 check_msg=check_msg,
56                 when=when,
57                 onerror=onerror,
58             )
60         # Generates a test program and attempts to compile it. In case of
61         # failure, the resulting check will return None. If the test program
62         # succeeds, it will return the output of the test program.
63         # - `includes` are the includes (as file names) that will appear at the
64         #   top of the generated test program.
65         # - `body` is the code that will appear in the main function of the
66         #   generated test program. `return 0;` is appended to the function
67         #   body automatically.
68         # - `flags` are the flags to be passed to the compiler, in addition to
69         #   `-c`.
70         # - `check_msg` is the message to be printed to accompany compiling the
71         #   test program.
72         def try_compile(
73             self,
74             includes=None,
75             body="",
76             flags=None,
77             check_msg=None,
78             when=None,
79             onerror=lambda: None,
80         ):
81             return self._try_compile_or_link(
82                 includes=includes,
83                 body=body,
84                 flags=flags,
85                 ldflags=None,
86                 check_msg=check_msg,
87                 when=when,
88                 onerror=onerror,
89             )
91         # Same steps as try_compile but doesn't add "-c"
92         def try_link(
93             self,
94             ldflags,
95             includes=None,
96             body="",
97             flags=None,
98             check_msg=None,
99             when=None,
100             onerror=lambda: None,
101         ):
102             return self._try_compile_or_link(
103                 includes=includes,
104                 body=body,
105                 flags=flags,
106                 ldflags=ldflags,
107                 check_msg=check_msg,
108                 when=when,
109                 onerror=onerror,
110             )
112         # Generates a test program and run the compiler against it. In case of
113         # failure, the resulting check will return None.
114         # - `header` is code that will appear at the top of the generated test
115         #   program.
116         # - `body` is the code that will appear in the main function of the
117         #   generated test program. `return 0;` is appended to the function
118         #   body automatically.
119         # - `flags` are the flags to be passed to the compiler.
120         # - `check_msg` is the message to be printed to accompany compiling the
121         #   test program.
122         # - `onerror` is a function called when the check fails.
123         def try_run(
124             self,
125             header=None,
126             body="",
127             flags=None,
128             check_msg=None,
129             when=None,
130             onerror=lambda: None,
131         ):
132             source = textwrap.dedent(
133                 """\
134                 int
135                 main(void)
136                 {
137                 %s
138                   ;
139                   return 0;
140                 }
141             """
142                 % body
143             )
145             if check_msg:
147                 def checking_fn(fn):
148                     return checking(check_msg)(fn)
150             else:
152                 def checking_fn(fn):
153                     return fn
155             # We accept onerror being a @depends function that returns a callable.
156             # So, create a similar @depends function when it's not already one.
157             if not isinstance(onerror, SandboxDependsFunction):
158                 onerror = dependable(lambda: onerror)
160             @depends(
161                 self,
162                 dependable(flags),
163                 extra_toolchain_flags,
164                 dependable(header),
165                 onerror,
166                 configure_cache,
167                 when=when,
168             )
169             @checking_fn
170             def func(
171                 compiler,
172                 flags,
173                 extra_flags,
174                 header,
175                 onerror,
176                 configure_cache,
177             ):
178                 flags = list(flags or [])
179                 if is_target:
180                     flags += extra_flags or []
181                 header = header or ""
182                 if isinstance(header, (list, tuple)):
183                     header = "\n".join(header)
184                 if header:
185                     header += "\n"
187                 if (
188                     try_invoke_compiler(
189                         configure_cache,
190                         [compiler.compiler] + compiler.flags,
191                         compiler.language,
192                         header + source,
193                         flags,
194                         onerror=onerror,
195                         wrapper=compiler.wrapper,
196                     )
197                     is not None
198                 ):
199                     return True
201             return func
203     compiler.__class__ = Compiler
204     return compiler