tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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