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