tor-browser

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

BUILD.gn (24456B)


      1 # Copyright 2013 The Chromium Authors
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import("//chromium/build/config/c++/c++.gni")
      6 import("//chromium/build/config/chrome_build.gni")
      7 import("//chromium/build/config/clang/clang.gni")
      8 import("//chromium/build/config/compiler/compiler.gni")
      9 import("//chromium/build/config/rust.gni")
     10 import("//chromium/build/config/sanitizers/sanitizers.gni")
     11 import("//chromium/build/config/win/control_flow_guard.gni")
     12 import("//chromium/build/config/win/visual_studio_version.gni")
     13 import("//chromium/build/timestamp.gni")
     14 import("//chromium/build/toolchain/rbe.gni")
     15 import("//chromium/build/toolchain/toolchain.gni")
     16 
     17 assert(is_win)
     18 
     19 declare_args() {
     20   # Turn this on to have the linker output extra timing information.
     21   win_linker_timing = false
     22 
     23   # possible values for target_winuwp_version:
     24   #   "10" - Windows UWP 10
     25   #   "8.1" - Windows RT 8.1
     26   #   "8.0" - Windows RT 8.0
     27   target_winuwp_version = "10"
     28 
     29   # possible values:
     30   #   "app" - Windows Store Applications
     31   #   "phone" - Windows Phone Applications
     32   #   "system" - Windows Drivers and Tools
     33   #   "server" - Windows Server Applications
     34   #   "desktop" - Windows Desktop Applications
     35   target_winuwp_family = "app"
     36 
     37   # Set this to use clang-style diagnostics format instead of MSVC-style, which
     38   # is useful in e.g. Emacs compilation mode.
     39   # E.g.:
     40   #  Without this, clang emits a diagnostic message like this:
     41   #    foo/bar.cc(12,34): error: something went wrong
     42   #  and with this switch, clang emits it like this:
     43   #    foo/bar.cc:12:34: error: something went wrong
     44   use_clang_diagnostics_format = false
     45 }
     46 
     47 # This is included by reference in the //build/config/compiler config that
     48 # is applied to all targets. It is here to separate out the logic that is
     49 # Windows-only.
     50 config("compiler") {
     51   if (target_cpu == "x86") {
     52     asmflags = [
     53       # When /safeseh is specified, the linker will only produce an image if it
     54       # can also produce a table of the image's safe exception handlers. This
     55       # table specifies for the operating system which exception handlers are
     56       # valid for the image. Note that /SAFESEH isn't accepted on the command
     57       # line, only /safeseh. This is only accepted by ml.exe, not ml64.exe.
     58       "/safeseh",
     59     ]
     60   }
     61 
     62   cflags = [
     63     "/Gy",  # Enable function-level linking.
     64     "/FS",  # Preserve previous PDB behavior.
     65     "/bigobj",  # Some of our files are bigger than the regular limits.
     66     "/utf-8",  # Assume UTF-8 by default to avoid code page dependencies.
     67   ]
     68 
     69   if (is_clang) {
     70     cflags += [
     71       "/Zc:twoPhase",
     72 
     73       # Consistently use backslash as the path separator when expanding the
     74       # __FILE__ macro when targeting Windows regardless of the build
     75       # environment.
     76       "-ffile-reproducible",
     77     ]
     78   }
     79 
     80   # Force C/C++ mode for the given GN detected file type. This is necessary
     81   # for precompiled headers where the same source file is compiled in both
     82   # modes.
     83   cflags_c = [ "/TC" ]
     84   cflags_cc = [ "/TP" ]
     85 
     86   if (is_clang) {
     87     # Required to make the 19041 SDK compatible with clang-cl.
     88     # See https://crbug.com/1089996 issue #2 for details.
     89     cflags += [ "/D__WRL_ENABLE_FUNCTION_STATICS__" ]
     90 
     91     # Tell clang which version of MSVC to emulate.
     92     cflags += [ "-fmsc-version=1934" ]
     93 
     94     if (is_component_build) {
     95       cflags += [
     96         # Do not export inline member functions. This makes component builds
     97         # faster. This is similar to -fvisibility-inlines-hidden.
     98         "/Zc:dllexportInlines-",
     99       ]
    100     }
    101 
    102     if (target_cpu == "x86") {
    103       if (host_cpu == "x86" || host_cpu == "x64") {
    104         cflags += [ "-m32" ]
    105       } else {
    106         cflags += [ "--target=i386-windows" ]
    107       }
    108     } else if (target_cpu == "x64") {
    109       if (host_cpu == "x86" || host_cpu == "x64") {
    110         cflags += [ "-m64" ]
    111       } else {
    112         cflags += [ "--target=x86_64-windows" ]
    113       }
    114     } else if (target_cpu == "arm64") {
    115       cflags += [ "--target=aarch64-pc-windows" ]
    116     } else {
    117       assert(false, "unknown target_cpu " + target_cpu)
    118     }
    119 
    120     # Chrome currently requires SSE3. Clang supports targeting any Intel
    121     # microarchitecture. MSVC only supports a subset of architectures, and the
    122     # next step after SSE2 will be AVX.
    123     if (target_cpu == "x86" || target_cpu == "x64") {
    124       cflags += [ "-msse3" ]
    125     }
    126 
    127     # Enable ANSI escape codes if something emulating them is around (cmd.exe
    128     # doesn't understand ANSI escape codes by default). Make sure to not enable
    129     # this if remoteexec is in use, because this will lower cache hits.
    130     if (!use_remoteexec &&
    131         exec_script("//chromium/build/win/use_ansi_codes.py", [], "trim string") ==
    132         "True") {
    133       cflags += [ "-fansi-escape-codes" ]
    134     }
    135 
    136     if (use_clang_diagnostics_format) {
    137       cflags += [ "/clang:-fdiagnostics-format=clang" ]
    138     }
    139   }
    140 
    141   if (use_lld && !use_thin_lto) {
    142     # /Brepro lets the compiler not write the mtime field in the .obj output.
    143     # link.exe /incremental relies on this field to work correctly, but lld
    144     # never looks at this timestamp, so it's safe to pass this flag with
    145     # lld and get more deterministic compiler output in return.
    146     # In LTO builds, the compiler doesn't write .obj files containing mtimes,
    147     # so /Brepro is ignored there.
    148     cflags += [ "/Brepro" ]
    149   }
    150 
    151   ldflags = []
    152 
    153   if (use_lld) {
    154     # lld defaults to writing the current time in the pe/coff header.
    155     # For build reproducibility, pass an explicit timestamp. See
    156     # build/compute_build_timestamp.py for how the timestamp is chosen.
    157     # (link.exe also writes the current time, but it doesn't have a flag to
    158     # override that behavior.)
    159     ldflags += [ "/TIMESTAMP:" + build_timestamp ]
    160 
    161     # Don't look for libpaths in %LIB%, similar to /X in cflags above.
    162     ldflags += [ "/lldignoreenv" ]
    163   }
    164 
    165   # Some binaries create PDBs larger than 4 GiB. Increasing the PDB page size
    166   # to 8 KiB allows 8 GiB PDBs. The larger page size also allows larger block maps
    167   # which is a PDB limit that was hit in https://crbug.com/1406510. The page size
    168   # can easily be increased in the future to allow even larger PDBs or larger
    169   # block maps.
    170   # This flag requires lld-link.exe or link.exe from VS 2022 or later to create
    171   # the PDBs, and tools from circa 22H2 or later to consume the PDBs.
    172   # Debug component builds can generate PDBs that exceed 8 GiB, so use an
    173   # even larger page size, allowing up to 16 GiB PDBs.
    174   if (is_debug && !is_component_build) {
    175     ldflags += [ "/pdbpagesize:16384" ]
    176   } else {
    177     ldflags += [ "/pdbpagesize:8192" ]
    178   }
    179 
    180   if (!is_debug && !is_component_build) {
    181     # Enable standard linker optimizations like GC (/OPT:REF) and ICF in static
    182     # release builds.
    183     # Release builds always want these optimizations, so enable them explicitly.
    184     ldflags += [
    185       "/OPT:REF",
    186       "/OPT:ICF",
    187       "/INCREMENTAL:NO",
    188       "/FIXED:NO",
    189     ]
    190 
    191     if (use_lld) {
    192       # String tail merging leads to smaller binaries, but they don't compress
    193       # as well, leading to increased mini_installer size (crbug.com/838449).
    194       ldflags += [ "/OPT:NOLLDTAILMERGE" ]
    195     }
    196 
    197     # TODO(siggi): Is this of any use anymore?
    198     # /PROFILE ensures that the PDB file contains FIXUP information (growing the
    199     # PDB file by about 5%) but does not otherwise alter the output binary. It
    200     # is enabled opportunistically for builds where it is not prohibited (not
    201     # supported when incrementally linking, or using /debug:fastlink).
    202     ldflags += [ "/PROFILE" ]
    203   }
    204 
    205   # arflags apply only to static_libraries. The normal linker configs are only
    206   # set for executable and shared library targets so arflags must be set
    207   # elsewhere. Since this is relatively contained, we just apply them in this
    208   # more general config and they will only have an effect on static libraries.
    209   arflags = [
    210     # "No public symbols found; archive member will be inaccessible." This
    211     # means that one or more object files in the library can never be
    212     # pulled in to targets that link to this library. It's just a warning that
    213     # the source file is a no-op.
    214     "/ignore:4221",
    215   ]
    216 }
    217 
    218 # This is included by reference in the //build/config/compiler:runtime_library
    219 # config that is applied to all targets. It is here to separate out the logic
    220 # that is Windows-only. Please see that target for advice on what should go in
    221 # :runtime_library vs. :compiler.
    222 config("runtime_library") {
    223   cflags = []
    224   cflags_cc = []
    225 
    226   # Defines that set up the CRT.
    227   defines = [
    228     "__STD_C",
    229     "_CRT_RAND_S",
    230     "_CRT_SECURE_NO_DEPRECATE",
    231     "_SCL_SECURE_NO_DEPRECATE",
    232   ]
    233 
    234   # Defines that set up the Windows SDK.
    235   defines += [
    236     "_ATL_NO_OPENGL",
    237     "_WINDOWS",
    238     "CERT_CHAIN_PARA_HAS_EXTRA_FIELDS",
    239     "PSAPI_VERSION=2",
    240     "WIN32",
    241     "_SECURE_ATL",
    242   ]
    243 
    244   if (current_os == "winuwp") {
    245     # When targeting Windows Runtime, certain compiler/linker flags are
    246     # necessary.
    247     defines += [
    248       "WINUWP",
    249       "__WRL_NO_DEFAULT_LIB__",
    250     ]
    251     if (target_winuwp_family == "app") {
    252       defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_PC_APP" ]
    253     } else if (target_winuwp_family == "phone") {
    254       defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" ]
    255     } else if (target_winuwp_family == "system") {
    256       defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_SYSTEM" ]
    257     } else if (target_winuwp_family == "server") {
    258       defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_SERVER" ]
    259     } else {
    260       defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP" ]
    261     }
    262     cflags_cc += [ "/EHsc" ]
    263 
    264     # This warning is given because the linker cannot tell the difference
    265     # between consuming WinRT APIs versus authoring WinRT within static
    266     # libraries as such this warning is always given by the linker. Since
    267     # consuming WinRT APIs within a library is legitimate but authoring
    268     # WinRT APis is not allowed, this warning is disabled to ignore the
    269     # legitimate consumption of WinRT APIs within static library builds.
    270     arflags = [ "/IGNORE:4264" ]
    271 
    272     if (target_winuwp_version == "10") {
    273       defines += [ "WIN10=_WIN32_WINNT_WIN10" ]
    274     } else if (target_winuwp_version == "8.1") {
    275       defines += [ "WIN8_1=_WIN32_WINNT_WINBLUE" ]
    276     } else if (target_winuwp_version == "8.0") {
    277       defines += [ "WIN8=_WIN32_WINNT_WIN8" ]
    278     }
    279   } else {
    280     # When not targeting Windows Runtime, make sure the WINAPI family is set
    281     # to desktop.
    282     defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP" ]
    283   }
    284 }
    285 
    286 # Chromium only supports Windowes 10+.
    287 # Some third-party libraries assume that these defines set what version of
    288 # Windows is available at runtime. Targets using these libraries need to
    289 # manually override this config for their compiles.
    290 config("winver") {
    291   defines = [
    292     "NTDDI_VERSION=0x0A000000",
    293 
    294     # We can't say `=_WIN32_WINNT_WIN10` here because some files do
    295     # `#if WINVER < 0x0600` without including windows.h before,
    296     # and then _WIN32_WINNT_WIN10 isn't yet known to be 0x0A00.
    297     "_WIN32_WINNT=0x0A00",
    298     "WINVER=0x0A00",
    299   ]
    300 }
    301 
    302 # Linker flags for Windows SDK setup, this is applied only to EXEs and DLLs.
    303 config("sdk_link") {
    304   if (target_cpu == "x86") {
    305     ldflags = [
    306       "/SAFESEH",  # Not compatible with x64 so use only for x86.
    307       "/largeaddressaware",
    308     ]
    309   }
    310 }
    311 
    312 # This default linker setup is provided separately from the SDK setup so
    313 # targets who want different library configurations can remove this and specify
    314 # their own.
    315 config("common_linker_setup") {
    316   ldflags = [
    317     "/FIXED:NO",
    318     "/ignore:4199",
    319     "/ignore:4221",
    320     "/NXCOMPAT",
    321     "/DYNAMICBASE",
    322   ]
    323 
    324   if (win_linker_timing) {
    325     ldflags += [
    326       "/time",
    327       "/verbose:incr",
    328     ]
    329   }
    330 }
    331 
    332 config("default_cfg_compiler") {
    333   # Emit table of address-taken functions for Control-Flow Guard (CFG).
    334   # This is needed to allow functions to be called by code that is built
    335   # with CFG enabled, such as system libraries.
    336   # The CFG guards are only emitted if |win_enable_cfg_guards| is enabled.
    337   if (win_enable_cfg_guards) {
    338     if (is_clang) {
    339       cflags = [ "/guard:cf" ]
    340     }
    341     rustflags = [ "-Ccontrol-flow-guard" ]
    342   } else {
    343     if (is_clang) {
    344       cflags = [ "/guard:cf,nochecks" ]
    345     }
    346     rustflags = [ "-Ccontrol-flow-guard=nochecks" ]
    347   }
    348 }
    349 
    350 # To disable CFG guards for a target, remove the "default_cfg_compiler"
    351 # config, and add "disable_guards_cfg_compiler" config.
    352 config("disable_guards_cfg_compiler") {
    353   # Emit table of address-taken functions for Control-Flow Guard (CFG).
    354   # This is needed to allow functions to be called by code that is built
    355   # with CFG enabled, such as system libraries.
    356   if (is_clang) {
    357     cflags = [ "/guard:cf,nochecks" ]
    358   }
    359   rustflags = [ "-Ccontrol-flow-guard=nochecks" ]
    360 }
    361 
    362 config("cfi_linker") {
    363   # Control Flow Guard (CFG)
    364   # https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065.aspx
    365   # /DYNAMICBASE (ASLR) is turned off in debug builds, therefore CFG cannot be
    366   # turned on either.
    367   # ASan and CFG leads to slow process startup. Chromium's test runner uses
    368   # lots of child processes, so this means things are really slow. Disable CFG
    369   # for now. https://crbug.com/846966
    370   if (!is_debug && !is_asan) {
    371     # Turn on CFG bitmap generation and CFG load config.
    372     ldflags = [ "/guard:cf" ]
    373   }
    374 }
    375 
    376 # This is a superset of all the delayloads needed for chrome.exe, chrome.dll,
    377 # and chrome_elf.dll. The linker will automatically ignore anything which is not
    378 # linked to the binary at all (it is harmless to have an unmatched /delayload).
    379 #
    380 # We delayload most libraries as the dlls are simply not required at startup (or
    381 # at all, depending on the process type). In unsandboxed process they will load
    382 # when first needed.
    383 #
    384 # Some dlls open handles when they are loaded, and we may not want them to be
    385 # loaded in renderers or other sandboxed processes. Conversely, some dlls must
    386 # be loaded before sandbox lockdown.
    387 #
    388 # Some dlls themselves load others - in particular, to avoid unconditionally
    389 # loading user32.dll - we require that the following dlls are all delayloaded:
    390 # user32, gdi32, comctl32, comdlg32, cryptui, d3d9, dwmapi, imm32, msi, ole32,
    391 # oleacc, rstrtmgr, shell32, shlwapi, and uxtheme.
    392 #
    393 # Advapi32.dll is unconditionally loaded at process startup on Windows 10, but
    394 # on Windows 11 it is not, which makes it worthwhile to delay load it.
    395 # Additionally, advapi32.dll exports several functions that are forwarded to
    396 # other DLLs such as cryptbase.dll. If calls to those functions are present but
    397 # there are some processes where the functions are never called then delay
    398 # loading of advapi32.dll avoids pulling in those DLLs (such as cryptbase.dll)
    399 # unnecessarily, even if advapi32.dll itself is loaded.
    400 #
    401 # This config applies to chrome.exe, chrome.dll, chrome_elf.dll (& others).
    402 #
    403 # This config should also be used for any test binary whose goal is to run
    404 # tests with the full browser.
    405 config("delayloads") {
    406   ldflags = [
    407     "/DELAYLOAD:api-ms-win-core-synch-l1-2-0.dll",
    408     "/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll",
    409     "/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
    410     "/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll",
    411     "/DELAYLOAD:advapi32.dll",
    412     "/DELAYLOAD:bcryptprimitives.dll",
    413     "/DELAYLOAD:comctl32.dll",
    414     "/DELAYLOAD:comdlg32.dll",
    415     "/DELAYLOAD:credui.dll",
    416     "/DELAYLOAD:cryptui.dll",
    417     "/DELAYLOAD:d3d11.dll",
    418     "/DELAYLOAD:d3d12.dll",
    419     "/DELAYLOAD:d3d9.dll",
    420     "/DELAYLOAD:dcomp.dll",
    421     "/DELAYLOAD:dwmapi.dll",
    422     "/DELAYLOAD:dxgi.dll",
    423     "/DELAYLOAD:dxva2.dll",
    424     "/DELAYLOAD:esent.dll",
    425     "/DELAYLOAD:fontsub.dll",
    426     "/DELAYLOAD:gdi32.dll",
    427     "/DELAYLOAD:hid.dll",
    428     "/DELAYLOAD:imagehlp.dll",
    429     "/DELAYLOAD:imm32.dll",
    430     "/DELAYLOAD:msi.dll",
    431     "/DELAYLOAD:netapi32.dll",
    432     "/DELAYLOAD:ncrypt.dll",
    433     "/DELAYLOAD:ole32.dll",
    434     "/DELAYLOAD:oleacc.dll",
    435     "/DELAYLOAD:pdh.dll",
    436     "/DELAYLOAD:propsys.dll",
    437     "/DELAYLOAD:psapi.dll",
    438     "/DELAYLOAD:rpcrt4.dll",
    439     "/DELAYLOAD:rstrtmgr.dll",
    440     "/DELAYLOAD:setupapi.dll",
    441     "/DELAYLOAD:shell32.dll",
    442     "/DELAYLOAD:shlwapi.dll",
    443     "/DELAYLOAD:uiautomationcore.dll",
    444     "/DELAYLOAD:urlmon.dll",
    445     "/DELAYLOAD:user32.dll",
    446     "/DELAYLOAD:usp10.dll",
    447     "/DELAYLOAD:uxtheme.dll",
    448     "/DELAYLOAD:wer.dll",
    449     "/DELAYLOAD:wevtapi.dll",
    450     "/DELAYLOAD:wininet.dll",
    451     "/DELAYLOAD:winusb.dll",
    452     "/DELAYLOAD:wsock32.dll",
    453     "/DELAYLOAD:wtsapi32.dll",
    454   ]
    455 }
    456 
    457 # This config (along with `:delayloads`) applies to chrome.exe & chrome_elf.dll.
    458 # Entries should not appear in both configs.
    459 config("delayloads_not_for_child_dll") {
    460   ldflags = [
    461     "/DELAYLOAD:crypt32.dll",
    462     "/DELAYLOAD:dbghelp.dll",
    463     "/DELAYLOAD:dhcpcsvc.dll",
    464     "/DELAYLOAD:dwrite.dll",
    465     "/DELAYLOAD:iphlpapi.dll",
    466     "/DELAYLOAD:oleaut32.dll",
    467     "/DELAYLOAD:secur32.dll",
    468     "/DELAYLOAD:userenv.dll",
    469     "/DELAYLOAD:winhttp.dll",
    470     "/DELAYLOAD:winmm.dll",
    471     "/DELAYLOAD:winspool.drv",
    472     "/DELAYLOAD:wintrust.dll",
    473     "/DELAYLOAD:ws2_32.dll",
    474   ]
    475 }
    476 
    477 # ACLs are placed on the filesystem in order to allow chrome to launch
    478 # sandboxed processes in an app container when run from the out directory.
    479 group("maybe_set_appcontainer_acls") {
    480   # Exclude setting ACLs when build is not happening on chromium, or with a different toolchain.
    481   if (build_with_chromium && target_cpu == target_cpu && host_os == "win") {
    482     deps = [ ":set_appcontainer_acls" ]
    483   }
    484 }
    485 
    486 if (build_with_chromium && target_cpu == target_cpu && host_os == "win") {
    487   action("set_appcontainer_acls") {
    488     script = "//chromium/build/win/set_appcontainer_acls.py"
    489     stamp_file = "$target_out_dir/acls.stamp"
    490     inputs = [ script ]
    491     outputs = [ stamp_file ]
    492 
    493     args = [
    494       "--stamp=" + rebase_path(stamp_file, root_out_dir),
    495       "--dir=" + rebase_path(root_out_dir, root_out_dir),
    496     ]
    497   }
    498 }
    499 
    500 # CRT --------------------------------------------------------------------------
    501 
    502 # Configures how the runtime library (CRT) is going to be used.
    503 # See https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx for a reference of
    504 # what each value does.
    505 config("default_crt") {
    506   if (is_component_build) {
    507     # Component mode: dynamic CRT. Since the library is shared, it requires
    508     # exceptions or will give errors about things not matching, so keep
    509     # exceptions on.
    510     configs = [ ":dynamic_crt" ]
    511   } else {
    512     if (current_os == "winuwp") {
    513       # https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/
    514       # contains a details explanation of what is happening with the Windows
    515       # CRT in Visual Studio releases related to Windows store applications.
    516       configs = [ ":dynamic_crt" ]
    517     } else {
    518       # Desktop Windows: static CRT.
    519       configs = [ ":static_crt" ]
    520     }
    521   }
    522 }
    523 
    524 # Use this to force use of the release CRT when building perf-critical build
    525 # tools that need to be fully optimized even in debug builds, for those times
    526 # when the debug CRT is part of the bottleneck. This also avoids *implicitly*
    527 # defining _DEBUG.
    528 config("release_crt") {
    529   if (is_component_build) {
    530     cflags = [ "/MD" ]
    531 
    532     # /MD specifies msvcrt.lib as the CRT library, which is the dynamic+release
    533     # version. Rust needs to agree, and its default mode is dynamic+release, so
    534     # we do nothing here. See https://github.com/rust-lang/rust/issues/39016.
    535 
    536     if (use_custom_libcxx) {
    537       # On Windows, including libcpmt[d]/msvcprt[d] explicitly links the C++
    538       # standard library, which libc++ needs for exception_ptr internals.
    539       ldflags = [ "/DEFAULTLIB:msvcprt.lib" ]
    540     }
    541   } else {
    542     cflags = [ "/MT" ]
    543 
    544     # /MT specifies libcmt.lib as the CRT library, which is the static+release
    545     # version. Rust needs to agree, so we tell it to use the static+release CRT
    546     # as well. See https://github.com/rust-lang/rust/issues/39016.
    547     rustflags = [ "-Ctarget-feature=+crt-static" ]
    548 
    549     if (use_custom_libcxx) {
    550       ldflags = [ "/DEFAULTLIB:libcpmt.lib" ]
    551     }
    552   }
    553 }
    554 
    555 config("dynamic_crt") {
    556   if (is_debug) {
    557     # This pulls in the DLL debug CRT and defines _DEBUG
    558     cflags = [ "/MDd" ]
    559 
    560     # /MDd specifies msvcrtd.lib as the CRT library. Rust needs to agree, so we
    561     # specify it explicitly. Rust defaults to the dynamic+release library, which
    562     # we remove here, and then replace. See
    563     # https://github.com/rust-lang/rust/issues/39016.
    564     rustflags = [
    565       "-Clink-arg=/nodefaultlib:msvcrt.lib",
    566       "-Clink-arg=msvcrtd.lib",
    567     ]
    568 
    569     if (use_custom_libcxx) {
    570       ldflags = [ "/DEFAULTLIB:msvcprtd.lib" ]
    571     }
    572   } else {
    573     cflags = [ "/MD" ]
    574 
    575     # /MD specifies msvcrt.lib as the CRT library, which is the dynamic+release
    576     # version. Rust needs to agree, and its default mode is dynamic+release, so
    577     # we do nothing here. See https://github.com/rust-lang/rust/issues/39016.
    578 
    579     if (use_custom_libcxx) {
    580       ldflags = [ "/DEFAULTLIB:msvcprt.lib" ]
    581     }
    582   }
    583 }
    584 
    585 config("static_crt") {
    586   if (is_debug) {
    587     # This pulls in the static debug CRT and defines _DEBUG
    588     cflags = [ "/MTd" ]
    589 
    590     # /MTd specifies libcmtd.lib as the CRT library. Rust needs to agree, so we
    591     # specify it explicitly. We tell Rust that we're using the static CRT but
    592     # remove the release library that it chooses, and replace with the debug
    593     # library. See https://github.com/rust-lang/rust/issues/39016.
    594     rustflags = [
    595       "-Ctarget-feature=+crt-static",
    596       "-Clink-arg=/nodefaultlib:libcmt.lib",
    597       "-Clink-arg=libcmtd.lib",
    598     ]
    599 
    600     if (use_custom_libcxx) {
    601       ldflags = [ "/DEFAULTLIB:libcpmtd.lib" ]
    602     }
    603   } else {
    604     cflags = [ "/MT" ]
    605 
    606     # /MT specifies libcmt.lib as the CRT library, which is the static+release
    607     # version. Rust needs to agree, so we tell it to use the static+release CRT
    608     # as well. See https://github.com/rust-lang/rust/issues/39016.
    609     rustflags = [ "-Ctarget-feature=+crt-static" ]
    610 
    611     if (use_custom_libcxx) {
    612       ldflags = [ "/DEFAULTLIB:libcpmt.lib" ]
    613     }
    614   }
    615 }
    616 
    617 # Subsystem --------------------------------------------------------------------
    618 
    619 # This is appended to the subsystem to specify a minimum version.
    620 # The number after the comma is the minimum required OS version.
    621 # Set to 10.0 since we only support >= Win10 since M110.
    622 subsystem_version_suffix = ",10.0"
    623 
    624 config("console") {
    625   ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ]
    626 }
    627 config("windowed") {
    628   ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ]
    629 }
    630 
    631 # Incremental linking ----------------------------------------------------------
    632 
    633 # Applies incremental linking or not depending on the current configuration.
    634 config("default_incremental_linking") {
    635   # Enable incremental linking for debug builds and all component builds - any
    636   # builds where performance is not job one.
    637   # TODO(thakis): Always turn this on with lld, no reason not to.
    638   if (is_debug || is_component_build) {
    639     ldflags = [ "/INCREMENTAL" ]
    640     if (use_lld) {
    641       # lld doesn't use ilk files and doesn't really have an incremental link
    642       # mode; the only effect of the flag is that the .lib file timestamp isn't
    643       # updated if the .lib doesn't change.
    644       # TODO(thakis): Why pass /OPT:NOREF for lld, but not otherwise?
    645       # TODO(thakis): /INCREMENTAL is on by default in link.exe, but not in
    646       # lld.
    647       ldflags += [ "/OPT:NOREF" ]
    648 
    649       # TODO(crbug.com/40267564): Mixing incrememntal and icf produces an error
    650       # in lld-link.
    651       ldflags += [ "/OPT:NOICF" ]
    652     }
    653   } else {
    654     ldflags = [ "/INCREMENTAL:NO" ]
    655   }
    656 }
    657 
    658 # Character set ----------------------------------------------------------------
    659 
    660 # Not including this config means "ansi" (8-bit system codepage).
    661 config("unicode") {
    662   defines = [
    663     "_UNICODE",
    664     "UNICODE",
    665   ]
    666 }
    667 
    668 # Lean and mean ----------------------------------------------------------------
    669 
    670 # Some third party code might not compile with WIN32_LEAN_AND_MEAN so we have
    671 # to have a separate config for it. Remove this config from your target to
    672 # get the "bloaty and accommodating" version of windows.h.
    673 config("lean_and_mean") {
    674   defines = [ "WIN32_LEAN_AND_MEAN" ]
    675 }
    676 
    677 # Nominmax --------------------------------------------------------------------
    678 
    679 # Some third party code defines NOMINMAX before including windows.h, which
    680 # then causes warnings when it's been previously defined on the command line.
    681 # For such targets, this config can be removed.
    682 
    683 config("nominmax") {
    684   defines = [ "NOMINMAX" ]
    685 }