tor-browser

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

flags.configure (24800B)


      1 # -*- Mode: python; c-basic-offset: 4; 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 # The following flags are explicitly passed to C++ compiler invocations from rust
      8 # even when only passing base flags. If you add more similarly important flags,
      9 # please consider whether they should be handled the same way.
     10 # See config/makefiles/rust.mk.
     11 # We support C++14, but we don't want to enable the sized deallocation
     12 # facilities in C++14 yet.
     13 check_and_add_flag("-fno-sized-deallocation", compiler=cxx_compiler)
     14 # Likewise for C++17 and aligned allocation.  It's not immediately obvious
     15 # from the clang and GCC documentation, but they both support this.
     16 check_and_add_flag("-fno-aligned-new", compiler=cxx_compiler)
     17 
     18 
     19 # Detect static linkage of libstdc++
     20 # ==============================================================
     21 @depends(
     22     cxx_compiler,
     23     extra_toolchain_flags,
     24     linker_ldflags,
     25     llvm_objdump,
     26     when=target_has_linux_kernel,
     27 )
     28 @checking("whether we're trying to statically link with libstdc++")
     29 @imports("os")
     30 @imports("re")
     31 @imports(_from="mozshellutil", _import="split", _as="shell_split")
     32 def link_libstdcxx_statically(
     33     cxx_compiler,
     34     extra_toolchain_flags,
     35     linker_ldflags,
     36     llvm_objdump,
     37 ):
     38     with create_temporary_file(suffix=".out") as bin_path:
     39         # This test is quite conservative: it assumes dynamic linkage if the
     40         # compilation step fails or if the binary format is not supported. But
     41         # it still detects basic issues.
     42 
     43         # FIXME: At some point we should make these dependencies explicit.
     44         # See #1903233.
     45         env_flags = []
     46         if "CXXFLAGS" in os.environ:
     47             env_flags.extend(shell_split(os.environ["CXXFLAGS"]))
     48         if "LDFLAGS" in os.environ:
     49             env_flags.extend(shell_split(os.environ["LDFLAGS"]))
     50 
     51         if (
     52             try_invoke_compiler(
     53                 None,
     54                 [cxx_compiler.compiler]
     55                 + env_flags
     56                 + cxx_compiler.flags
     57                 + linker_ldflags,
     58                 cxx_compiler.language,
     59                 """
     60                     #include <iostream>
     61                     int main() { std::cout << 1;}
     62                 """,
     63                 ["-o", bin_path] + (extra_toolchain_flags or []),
     64                 wrapper=cxx_compiler.wrapper,
     65                 onerror=lambda: None,
     66             )
     67             is not None
     68         ):
     69             objdump_command = [llvm_objdump, "--private-headers", bin_path]
     70             result, stdout, stderr = get_cmd_output(*objdump_command)
     71             # This is very conservative :-).
     72             return (
     73                 result == 0
     74                 and not stderr
     75                 and not re.search("NEEDED.*lib(std)?c\\+\\+", stdout)
     76             )
     77 
     78 
     79 @depends(when=link_libstdcxx_statically)
     80 def check_libstdcxx_linkage():
     81     die("Firefox does not support linking statically with libstdc++")
     82 
     83 
     84 check_and_add_flag(
     85     "-mieee",
     86     when=target_has_linux_kernel & depends(target.cpu)(lambda cpu: cpu == "Alpha"),
     87 )
     88 
     89 # Identical Code Folding
     90 option(
     91     "--enable-icf",
     92     help="{Enable|Disable} Identical Code Folding",
     93     default=~developer_options,
     94 )
     95 enable_icf = depends("--enable-icf")(lambda v: bool(v))
     96 
     97 
     98 with only_when(building_with_gnu_compatible_cc):
     99     with only_when(~developer_options | enable_icf):
    100         add_flag("-ffunction-sections")
    101         add_flag("-fdata-sections")
    102     add_flag("-fno-math-errno")
    103     add_flag("-fno-exceptions", compiler=cxx_compiler)
    104 
    105 add_flag("-D_HAS_EXCEPTIONS=0", when=target_is_windows)
    106 
    107 # We only use -faddrsig with clang on android, and all version of clang we
    108 # support have it.
    109 add_addrsig_flag = depends(c_compiler, when=target_is_android)(
    110     lambda c: c.type == "clang"
    111 )
    112 
    113 
    114 @depends(
    115     c_compiler,
    116     extra_toolchain_flags,
    117     linker_ldflags,
    118     llvm_objdump,
    119     add_addrsig_flag,
    120     when=building_with_gnu_compatible_cc & gcc_use_gnu_ld & enable_icf,
    121 )
    122 @checking("whether the linker supports Identical Code Folding")
    123 @imports("os")
    124 def linker_supports_icf(
    125     c_compiler, extra_toolchain_flags, linker_ldflags, llvm_objdump, add_addrsig_flag
    126 ):
    127     with create_temporary_file(suffix=".out") as bin_path:
    128         if (
    129             try_invoke_compiler(
    130                 None,
    131                 [c_compiler.compiler] + c_compiler.flags + linker_ldflags,
    132                 c_compiler.language,
    133                 """
    134                                  int foo() {return 42;}
    135                                  int bar() {return 42;}
    136                                  int main() {return 0;}
    137                                  """,
    138                 ["-o", bin_path, "-Wl,--icf=safe", "-ffunction-sections"]
    139                 + (["-faddrsig"] if add_addrsig_flag else [])
    140                 + (extra_toolchain_flags or []),
    141                 wrapper=c_compiler.wrapper,
    142                 onerror=lambda: None,
    143             )
    144             is not None
    145         ):
    146             objdump_command = [llvm_objdump, "-t", bin_path]
    147             result = check_cmd_output(*objdump_command, onerror=lambda: None)
    148             if result is not None:
    149                 sym_addr = {
    150                     line[5]: line[0]
    151                     for line in [line.split() for line in result.splitlines()]
    152                     if len(line) >= 6
    153                 }
    154                 foo_addr = sym_addr.get("foo")
    155                 bar_addr = sym_addr.get("bar")
    156                 return foo_addr == bar_addr and foo_addr is not None
    157 
    158 
    159 @depends(compilation_flags, linker_flags, add_addrsig_flag, when=linker_supports_icf)
    160 def add_icf_flags(compilation_flags, linker_flags, add_addrsig_flag):
    161     if add_addrsig_flag:
    162         compilation_flags.cflags.append("-faddrsig")
    163         compilation_flags.cxxflags.append("-faddrsig")
    164     linker_flags.ldflags.append("-Wl,--icf=safe")
    165 
    166 
    167 option(
    168     "--disable-new-pass-manager",
    169     help="Use the legacy LLVM pass manager in clang builds",
    170 )
    171 
    172 
    173 @depends(
    174     "--enable-new-pass-manager",
    175     c_compiler,
    176     host,
    177     target,
    178     "MOZ_PGO",
    179     enable_fuzzing,
    180     ubsan,
    181 )
    182 def pass_manager(enabled, compiler, host, target, pgo, enable_fuzzing, ubsan):
    183     if compiler.type not in ("clang", "clang-cl"):
    184         return None
    185 
    186     # As of clang 13, the default pass manager is the new one.
    187     if compiler.version >= "13.0.0":
    188         if enabled:
    189             return namespace(flags=None, enabled=True)
    190         if compiler.type == "clang":
    191             return namespace(flags=["-flegacy-pass-manager"], enabled=False)
    192         if compiler.type == "clang-cl":
    193             return namespace(flags=["-Xclang", "-flegacy-pass-manager"], enabled=False)
    194 
    195     if not enabled:
    196         if compiler.version >= "15.0.0":
    197             die("--disable-new-pass-manager is only supported with clang < 15")
    198         return None
    199     if compiler.version < "9.0.0":
    200         if enabled.origin != "default":
    201             die("--enable-new-pass-manager is only supported with clang >= 9")
    202         return None
    203 
    204     if host.os == "OSX":
    205         # Some native Mac builds hang with the new pass manager. Given the
    206         # inability to test in CI, don't take the risk of further breakage.
    207         if enabled.origin != "default":
    208             die(
    209                 "--enable-new-pass-manager causes problems on mac hosts with clang < 13"
    210             )
    211         return None
    212     if target.os == "OSX" and not pgo:
    213         # Also disable when cross-compiling to Mac, because plain-ish opt
    214         # builds hang. Variants like asan and ccov work fine, but it would be
    215         # too tedious to test them all here. PGO is the only thing that matters
    216         # enough to make an exception for.
    217         if enabled.origin != "default":
    218             die(
    219                 "--enable-new-pass-manager causes problems on mac builds with clang < 13"
    220             )
    221         return None
    222     if enable_fuzzing and compiler.version < "10.0.0":
    223         # Clang 9 does not seem to play well with libFuzzer
    224         if enabled.origin != "default":
    225             die(
    226                 "--enable-new-pass-manager causes problems on fuzzing builds with clang < 10"
    227             )
    228         return None
    229     if ubsan and compiler.version == "10.0.0":
    230         # Clang 10.0.0 hangs with some ubsan-inserted code constructs.
    231         # This was fixed in 10.0.1 (https://llvm.org/pr45835)
    232         if enabled.origin != "default":
    233             die(
    234                 "--enable-new-pass-manager causes problems with ubsan builds with clang 10.0.0"
    235             )
    236         return None
    237     if compiler.type == "clang":
    238         return namespace(flags=["-fexperimental-new-pass-manager"], enabled=True)
    239     elif compiler.type == "clang-cl":
    240         return namespace(
    241             flags=["-Xclang", "-fexperimental-new-pass-manager"], enabled=True
    242         )
    243 
    244 
    245 set_config("MOZ_PASS_MANAGER_FLAGS", pass_manager.flags)
    246 
    247 # Debugging options
    248 ##
    249 
    250 
    251 @depends(moz_debug, asan, target, "--enable-jemalloc")
    252 def moz_no_debug_rtl(moz_debug, asan, target, enable_jemalloc):
    253     if not moz_debug or asan:
    254         return True
    255     if enable_jemalloc and target.kernel == "WINNT":
    256         return True
    257 
    258 
    259 set_config("MOZ_NO_DEBUG_RTL", moz_no_debug_rtl)
    260 
    261 
    262 @depends(
    263     try_compile(
    264         includes=["stdio.h"],
    265         body='puts("Hello World");',
    266         check_msg="for valid debug flags",
    267         flags=debug_flags,
    268         when=moz_debug,
    269     ),
    270     debug_flags,
    271     when=moz_debug,
    272 )
    273 @imports(_from="mozshellutil", _import="quote")
    274 def check_debug_flags(check, flags):
    275     if not check:
    276         die(f"These compiler flags are invalid: {quote(*flags)}")
    277 
    278 
    279 # Try to make builds more reproducible and allow sharing built artifacts across
    280 # source and object directories by using -ffile-prefix-map and friends.  To
    281 # "unwind" the prefix maps, use:
    282 #
    283 # (gdb) set substitute-path /topsrcdir/ $topsrcdir/
    284 #
    285 # (lldb) settings set target.source-map /topobjdir/ $topobjdir/
    286 #
    287 # See, for example, https://lldb.llvm.org/use/map.html.
    288 @depends(
    289     path_remapping,
    290     path_remappings,
    291     c_compiler,
    292 )
    293 @imports(_from="os", _import="sep")
    294 def file_prefix_map_flags(path_remapping, path_remappings, compiler):
    295     if "c" not in path_remapping:
    296         return []
    297 
    298     if (compiler.type == "gcc" and compiler.version < "8.1") or (
    299         compiler.type in ("clang", "clang-cl") and compiler.version < "10.0.0"
    300     ):
    301         die(
    302             f"Compiler of type {compiler.type} and version {compiler.version} "
    303             "does not support --enable-path-remapping."
    304         )
    305 
    306     flags = []
    307     for old, new in path_remappings:
    308         # We would prefer to use just -ffile-prefix-map, but clang-cl doesn't
    309         # seem to recognize it.
    310         for flag in ("-fdebug-prefix-map", "-fmacro-prefix-map"):
    311             flag = f"{flag}={old}={new}"
    312             if compiler.type in ("gcc", "clang"):
    313                 flags.append(flag)
    314             elif compiler.type == "clang-cl":
    315                 flags.extend(["-Xclang", flag])
    316 
    317     return flags
    318 
    319 
    320 set_config("MOZ_FILE_PREFIX_MAP_FLAGS", file_prefix_map_flags)
    321 
    322 
    323 @depends(developer_options, when=building_with_gnu_compatible_cc)
    324 def check_build_id_uuid(developer_options):
    325     return developer_options
    326 
    327 
    328 @depends(developer_options, when=building_with_gnu_compatible_cc)
    329 def check_build_id_sha1(developer_options):
    330     return not developer_options
    331 
    332 
    333 check_and_add_flag("-pipe", when=building_with_gcc)
    334 
    335 check_and_add_linker_flag("-Wl,--build-id=uuid", when=check_build_id_uuid)
    336 check_and_add_linker_flag("-Wl,--build-id=sha1", when=check_build_id_sha1)
    337 
    338 check_and_add_asm_flag("-Wa,--noexecstack", when=building_with_gnu_compatible_cc)
    339 check_and_add_linker_flag("-Wl,-z,noexecstack", when=building_with_gnu_compatible_cc)
    340 check_and_add_linker_flag("-Wl,-z,text", when=building_with_gnu_compatible_cc)
    341 check_and_add_linker_flag("-Wl,-z,relro", when=building_with_gnu_compatible_cc)
    342 check_and_add_linker_flag("-Wl,-z,now", when=building_with_gnu_compatible_cc)
    343 check_and_add_linker_flag("-Wl,-z,nocopyreloc", when=building_with_gnu_compatible_cc)
    344 
    345 check_and_add_linker_optimize_flag("-Wl,-dead_strip", when=target_is_darwin)
    346 
    347 check_and_add_asm_flag(
    348     "-fPIC", when=building_with_gnu_compatible_cc & ~target_is_windows
    349 )
    350 check_and_add_flag("-fPIC", when=building_with_gnu_compatible_cc & ~target_is_windows)
    351 set_define("PIC", True, when=target_is_netbsd)
    352 
    353 # DSO flags manipulations
    354 have_linker_support_ignore_unresolved = try_link(
    355     flags=["-Wl,--ignore-unresolved-symbol,environ"],
    356     check_msg="for --ignore-unresolved-symbol option to the linker",
    357     when=building_with_gnu_compatible_cc
    358     & gcc_use_gnu_ld
    359     & depends(target)(lambda t: t.os in ("DragonFly", "FreeBSD", "NetBSD", "OpenBSD")),
    360 )
    361 
    362 
    363 @depends(
    364     dso_flags,
    365     gcc_use_gnu_ld,
    366     target,
    367     asan | msan | any_ubsan | tsan | enable_fuzzing_interfaces,
    368     have_linker_support_ignore_unresolved,
    369     when=building_with_gnu_compatible_cc,
    370 )
    371 @imports(_from="os", _import="environ")
    372 def add_gnu_specific_dso_flags(
    373     dso_flags,
    374     use_gnu_ld,
    375     target,
    376     use_sanitizer_runtime,
    377     have_linker_support_ignore_unresolved,
    378 ):
    379     ldopts = []
    380     if target.kernel != "Darwin":
    381         ldopts.append("-shared")
    382 
    383     if use_gnu_ld:
    384         # Some tools like ASan use a runtime library that is only
    385         # linked against executables, so we must allow undefined
    386         # symbols for shared objects in some cases.
    387         if not use_sanitizer_runtime:
    388             if target.os != "WINNT":
    389                 # Don't allow undefined symbols in libraries
    390                 ldopts.append("-Wl,-z,defs")
    391 
    392             # BSDs need `environ' exposed for posix_spawn (bug 753046)
    393             if target.os in ("DragonFly", "FreeBSD", "NetBSD", "OpenBSD"):
    394                 if have_linker_support_ignore_unresolved:
    395                     ldopts.append("-Wl,--ignore-unresolved-symbol,environ")
    396                 else:
    397                     ldopts.append("-Wl,--warn-unresolved-symbols")
    398 
    399                 if librunpath := environ.get("LIBRUNPATH"):
    400                     if target.os == "NetBSD":
    401                         ldopts.insert(0, f"-Wl,-R{librunpath}")
    402                     elif target.os == "OpenBSD":
    403                         ldopts.insert(0, f"-R{librunpath}")
    404 
    405     dso_flags.ldopts.extend(ldopts)
    406 
    407 
    408 @depends(dso_flags, target, when=~building_with_gnu_compatible_cc)
    409 def add_non_gnu_dso_flags(dso_flags, target):
    410     ldopts = ["-SUBSYSTEM:WINDOWS,{}".format(win32_subsystem_version())]
    411     if target.cpu == "x86":
    412         ldopts.append("-MACHINE:X86")
    413     if target.cpu == "x86_64":
    414         ldopts.append("-MACHINE:X64")
    415     if target.cpu == "aarch64":
    416         ldopts.append("-MACHINE:ARM64")
    417 
    418     dso_flags.ldopts.extend(ldopts)
    419 
    420 
    421 @depends(libfuzzer_flags, when=enable_fuzzing)
    422 def sancov(libfuzzer_flags):
    423     for flag in libfuzzer_flags.use_flags:
    424         if "-fsanitize-coverage" in flag or "-fsanitize=fuzzer" in flag:
    425             return True
    426     return False
    427 
    428 
    429 @depends(target, build_environment)
    430 @imports(_from="os", _import="environ")
    431 def moz_fix_link_paths(target, build_env):
    432     dist = build_env.dist
    433     flags = [f"-Wl,-rpath-link,{dist}/bin"]
    434     if target.kernel == "Darwin":
    435         return []
    436     if target.kernel == "WINNT":
    437         return []
    438     if target.kernel == "SunOS":
    439         return [f"-L{dist}/bin"]
    440     if target.os == "WASI":
    441         return []
    442 
    443     return flags
    444 
    445 
    446 set_config("MOZ_FIX_LINK_PATHS", moz_fix_link_paths)
    447 
    448 
    449 @depends("--enable-address-sanitizer", building_with_gnu_compatible_cc)
    450 def check_Bsymbolic(enable_asan, building_with_gnu_compatible_cc):
    451     return enable_asan and building_with_gnu_compatible_cc
    452 
    453 
    454 # ASan assumes no symbols are being interposed, and when that happens,
    455 # it's not happy with it. Inconveniently, since Firefox is exporting
    456 # libffi symbols and Gtk+3 pulls system libffi via libwayland-client,
    457 # system libffi interposes libffi symbols that ASan assumes are in
    458 # libxul, so it barfs about buffer overflows.
    459 # Using -Wl,-Bsymbolic ensures no exported symbol can be interposed.
    460 check_and_add_linker_flag("-Wl,-Bsymbolic", when=check_Bsymbolic)
    461 
    462 
    463 # Check what kind of list files are supported by the linker
    464 @depends(c_compiler, link, linker_ldflags, extra_toolchain_flags)
    465 @checking("what kind of list files are supported by the linker")
    466 @imports("os")
    467 @imports(_from="__builtin__", _import="open")
    468 def expand_libs_list_style(c_compiler, link, linker_flags, extra_flags):
    469     with create_temporary_file(suffix=".o") as objname, create_temporary_file(
    470         suffix=".list"
    471     ) as listname, create_temporary_file(suffix=".out") as outname:
    472         with open(listname, "w") as fd:
    473             fd.write(objname)
    474 
    475         cflags = c_compiler.flags
    476 
    477         if (
    478             try_invoke_compiler(
    479                 # No configure_cache because it would not create the
    480                 # expected output file.
    481                 None,
    482                 [c_compiler.compiler] + cflags,
    483                 c_compiler.language,
    484                 "int main() {}",
    485                 ["-c", "-o", objname],
    486                 wrapper=c_compiler.wrapper,
    487                 onerror=lambda: None,
    488             )
    489             is None
    490         ):
    491             die("couldn't compile a simple C file")
    492 
    493         ldflags = linker_flags + (extra_flags or [])
    494 
    495         if c_compiler.type == "clang-cl":
    496             base_linker_cmd = [link] + ldflags + [f"-OUT:{outname}"]
    497         else:
    498             base_linker_cmd = [c_compiler.compiler] + cflags + ldflags + ["-o", outname]
    499 
    500         # -filelist is for the OS X linker.  We need to try -filelist
    501         # first because clang understands @file, but may pass an
    502         # oversized argument list to the linker depending on the
    503         # contents of @file.
    504         options = [
    505             ("linkerlist", f"-Wl,@{listname}"),
    506             ("filelist", f"-Wl,@{listname}"),
    507             ("list", f"@{listname}"),
    508         ]
    509         for kind, option in options:
    510             linker_cmd = base_linker_cmd + [option]
    511             if check_cmd_output(*linker_cmd, onerror=lambda: None) is not None:
    512                 return kind
    513         die("Couldn't find one that works")
    514 
    515 
    516 set_config("EXPAND_LIBS_LIST_STYLE", expand_libs_list_style)
    517 
    518 
    519 # MOZ_PROGRAM_LDFLAGS
    520 # ---------------------------------
    521 @depends(building_with_gnu_compatible_cc, target)
    522 def moz_program_ldflags(building_with_gnu_compatible_cc, target):
    523     if building_with_gnu_compatible_cc and target.kernel not in ("Darwin", "WASI"):
    524         return ["-pie"]
    525 
    526 
    527 set_config("MOZ_PROGRAM_LDFLAGS", moz_program_ldflags)
    528 
    529 
    530 @depends(host, when=depends(c_compiler)(lambda c: c.type == "clang-cl"))
    531 def moz_debug_ldflags(host):
    532     flags = ["-DEBUG"]
    533     if host.kernel != "WINNT":
    534         # %_PDB% is a special signal to emit only the PDB basename. This
    535         # avoids problems in Windows tools that don't like forward-slashes.
    536         flags.append("-PDBALTPATH:%_PDB%")
    537     return flags
    538 
    539 
    540 set_config("MOZ_DEBUG_LDFLAGS", moz_debug_ldflags)
    541 
    542 
    543 # Objective-C/ Objective-C++ flags.
    544 # ---------------------------------
    545 @depends(compilation_flags, toolkit)
    546 def add_cmflags(compilation_flags, toolkit):
    547     cmflags = ["-x", "objective-c", "-fobjc-exceptions"]
    548     cmmflags = ["-x", "objective-c++", "-fobjc-exceptions"]
    549 
    550     compilation_flags.cmflags.extend(cmflags)
    551     compilation_flags.cmmflags.extend(cmmflags)
    552     if toolkit == "uikit":
    553         uiflags = ["-fobjc-abi-version=2", "-fobjc-legacy-dispatch"]
    554         compilation_flags.cmflags.extend(uiflags)
    555         compilation_flags.cmmflags.extend(uiflags)
    556 
    557 
    558 set_config("OS_COMPILE_CMFLAGS", compilation_flags.cmflags)
    559 set_config("OS_COMPILE_CMMFLAGS", compilation_flags.cmmflags)
    560 
    561 
    562 # Final flags settings
    563 # ---------------------------------
    564 @depends(host_c_compiler)
    565 def host_optimize_flags(compiler):
    566     if compiler.type == "clang-cl":
    567         return ["-O2"]
    568     else:
    569         return ["-O3"]
    570 
    571 
    572 set_config("HOST_OPTIMIZE_FLAGS", host_optimize_flags)
    573 
    574 
    575 @depends("HOST_CPPFLAGS", host, host_c_compiler)
    576 @imports(_from="mozshellutil", _import="split")
    577 def host_cppflags(base_cppflags, host, compiler):
    578     flags = []
    579     if host.kernel == "WINNT":
    580         if compiler.type != "clang-cl":
    581             flags += ["-mwindows"]
    582         flags += ["-DXP_WIN", "-DWIN32", "-D_WIN32", "-D_CRT_SECURE_NO_WARNINGS"]
    583         if host.cpu == "x86_64":
    584             flags += ["-D_AMD64_"]
    585     elif host.kernel == "Darwin":
    586         flags += ["-DXP_UNIX", "-DXP_MACOSX"]
    587     else:
    588         flags += ["-DXP_UNIX"]
    589     if base_cppflags:
    590         flags += split(base_cppflags[0])
    591     return flags
    592 
    593 
    594 @depends("HOST_CFLAGS", compilation_flags)
    595 @imports(_from="mozshellutil", _import="split")
    596 def host_cflags(base_cflags, compilation_flags):
    597     flags = list(compilation_flags.host_cflags)
    598     if base_cflags:
    599         flags += split(base_cflags[0])
    600     return flags
    601 
    602 
    603 @depends("HOST_CXXFLAGS", compilation_flags)
    604 @imports(_from="mozshellutil", _import="split")
    605 def host_cxxflags(base_cxxflags, compilation_flags):
    606     flags = list(compilation_flags.host_cxxflags)
    607     if base_cxxflags:
    608         flags += split(base_cxxflags[0])
    609     return flags
    610 
    611 
    612 @depends("HOST_LDFLAGS", linker_flags, host_linker_ldflags, host, host_c_compiler)
    613 @imports(_from="mozshellutil", _import="split")
    614 def host_ldflags(env_ldflags, linker_flags, host_linker_ldflags, host, compiler):
    615     flags = []
    616     if env_ldflags:
    617         flags += split(env_ldflags[0])
    618     flags += host_linker_ldflags
    619     if host.kernel == "WINNT" and compiler.type == "clang-cl":
    620         if host.cpu == "x86":
    621             flags += ["-MACHINE:X86"]
    622         elif host.cpu == "x86_64":
    623             flags += ["-MACHINE:X64"]
    624     flags += linker_flags.host_ldflags
    625     return flags
    626 
    627 
    628 @depends("CPPFLAGS")
    629 @imports(_from="mozshellutil", _import="split")
    630 def os_cppflags(env_cppflags):
    631     flags = []
    632     if env_cppflags:
    633         flags = split(env_cppflags[0])
    634     return flags
    635 
    636 
    637 @depends("CFLAGS", compilation_flags, android_flags, all_arm_flags)
    638 @imports(_from="mozshellutil", _import="split")
    639 def os_cflags(env_cflags, compilation_flags, android_flags, all_arm_flags):
    640     flags = []
    641     if android_flags:
    642         flags.extend(android_flags.cflags)
    643     if all_arm_flags:
    644         flags.extend(all_arm_flags)
    645     flags.extend(compilation_flags.cflags)
    646     if env_cflags:
    647         flags.extend(split(env_cflags[0]))
    648     return flags
    649 
    650 
    651 @depends("CXXFLAGS", compilation_flags, android_flags, all_arm_flags)
    652 @imports(_from="mozshellutil", _import="split")
    653 def os_cxxflags(env_cxxflags, compilation_flags, android_flags, all_arm_flags):
    654     flags = []
    655     if android_flags:
    656         flags.extend(android_flags.cxxflags)
    657     if all_arm_flags:
    658         flags.extend(all_arm_flags)
    659     flags.extend(compilation_flags.cxxflags)
    660     if env_cxxflags:
    661         flags.extend(split(env_cxxflags[0]))
    662     return flags
    663 
    664 
    665 @depends(
    666     "ASFLAGS",
    667     asm_flags,
    668     android_flags,
    669     all_arm_flags,
    670     defines_cpp_flags,
    671     c_compiler,
    672     build_project,
    673 )
    674 @imports(_from="mozshellutil", _import="split")
    675 def os_asflags(
    676     env_asflags,
    677     asm_flags,
    678     android_flags,
    679     all_arm_flags,
    680     defines_cpp_flags,
    681     c_compiler,
    682     build_project,
    683 ):
    684     flags = []
    685     if android_flags:
    686         flags.extend(android_flags.asflags)
    687         flags.append("-DANDROID")
    688     if all_arm_flags:
    689         flags.extend(all_arm_flags)
    690     flags.extend(asm_flags.asflags)
    691     if build_project != "js" and c_compiler.type != "clang-cl":
    692         flags.extend(defines_cpp_flags)
    693     if env_asflags:
    694         flags.extend(split(env_asflags[0]))
    695     return flags
    696 
    697 
    698 # VS2012+ defaults to -arch:SSE2. We want to target nothing more recent, so set
    699 # that explicitly here unless another target arch has already been set.
    700 @template
    701 def add_sse2_flag_if_needed(flags):
    702     @depends(
    703         flags,
    704         when=~building_with_gnu_compatible_cc
    705         & depends(target.cpu)(lambda cpu: cpu == "x86"),
    706     )
    707     def add_sse2_flag(flags):
    708         is_arch_flag = lambda flag: flag.lower().startswith(("-arch:", "/arch:"))
    709         if not any(is_arch_flag(flag) for flag in flags):
    710             flags.append("-arch:SSE2")
    711 
    712 
    713 add_sse2_flag_if_needed(os_cflags)
    714 add_sse2_flag_if_needed(os_cxxflags)
    715 
    716 
    717 @depends(compilation_flags, when=depends(target.os)(lambda os: os == "WASI"))
    718 def add_thread_model_single(compilation_flags):
    719     compilation_flags.cxxflags.extend(["-mthread-model", "single"])
    720 
    721 
    722 # Please keep these last in this file.
    723 set_config("HOST_CPPFLAGS", host_cppflags)
    724 set_config("HOST_CFLAGS", host_cflags)
    725 set_config("HOST_CXXFLAGS", host_cxxflags)
    726 set_config("HOST_LDFLAGS", host_ldflags)
    727 set_config("OS_CPPFLAGS", os_cppflags)
    728 set_config("OS_CFLAGS", os_cflags)
    729 set_config("OS_CXXFLAGS", os_cxxflags)
    730 set_config("ASFLAGS", os_asflags)
    731 set_config("DSO_LDOPTS", dso_flags.ldopts)
    732 set_config("LIBS", depends("LIBS")(lambda x: x))