compilers-util.configure (6610B)
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/. 6 7 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 13 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: 26 27 @depends(dependable(flags)) 28 def flags(flags): 29 flags = list(flags or []) 30 flags.append("-c") 31 return flags 32 33 else: 34 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 ) 41 42 flags = list(flags or []) 43 flags.extend(ldflags) 44 return flags 45 46 @depends(dependable(includes)) 47 def header(includes): 48 includes = includes or [] 49 return ["#include <%s>" % f for f in includes] 50 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 ) 59 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 ) 90 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 ) 111 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 ) 144 145 if check_msg: 146 147 def checking_fn(fn): 148 return checking(check_msg)(fn) 149 150 else: 151 152 def checking_fn(fn): 153 return fn 154 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) 159 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" 186 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 200 201 return func 202 203 compiler.__class__ = Compiler 204 return compiler