xref: /aosp_15_r20/external/angle/build/config/compiler/BUILD.gn (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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/buildflag_header.gni")
6import("//build/config/android/config.gni")
7import("//build/config/c++/c++.gni")
8import("//build/config/chrome_build.gni")
9import("//build/config/chromeos/args.gni")
10import("//build/config/chromeos/ui_mode.gni")
11import("//build/config/clang/clang.gni")
12import("//build/config/compiler/compiler.gni")
13import("//build/config/coverage/coverage.gni")
14import("//build/config/dcheck_always_on.gni")
15import("//build/config/gclient_args.gni")
16import("//build/config/host_byteorder.gni")
17import("//build/config/pch.gni")
18import("//build/config/rust.gni")
19import("//build/config/ui.gni")
20import("//build/config/unwind.gni")
21import("//build/toolchain/cros/cros_config.gni")
22import("//build/toolchain/rbe.gni")
23import("//build/toolchain/toolchain.gni")
24import("//build_overrides/build.gni")
25
26if (current_cpu == "arm" || current_cpu == "arm64") {
27  import("//build/config/arm.gni")
28}
29if (current_cpu == "mipsel" || current_cpu == "mips64el" ||
30    current_cpu == "mips" || current_cpu == "mips64") {
31  import("//build/config/mips.gni")
32}
33if (is_mac) {
34  import("//build/config/apple/symbols.gni")
35}
36if (is_ios) {
37  import("//build/config/ios/ios_sdk.gni")
38}
39if (is_nacl) {
40  # To keep NaCl variables out of builds that don't include NaCl, all
41  # variables defined in nacl/config.gni referenced here should be protected by
42  # is_nacl conditions.
43  import("//build/config/nacl/config.gni")
44}
45
46lld_path = ""
47if (!is_clang) {
48  declare_args() {
49    # This allows overriding the location of lld.
50    lld_path = rebase_path("$clang_base_path/bin", root_build_dir)
51  }
52} else {
53  # clang looks for lld next to it, no need for -B.
54  lld_path = ""
55}
56
57declare_args() {
58  # Normally, Android builds are lightly optimized, even for debug builds, to
59  # keep binary size down. Setting this flag to true disables such optimization
60  android_full_debug = false
61
62  # Compile in such a way as to make it possible for the profiler to unwind full
63  # stack frames. Setting this flag has a large effect on the performance of the
64  # generated code than just setting profiling, but gives the profiler more
65  # information to analyze.
66  # Requires profiling to be set to true.
67  enable_full_stack_frames_for_profiling = false
68
69  # Enable fatal linker warnings. Building Chromium with certain versions
70  # of binutils can cause linker warning.
71  fatal_linker_warnings = true
72
73  # Build with C++ RTTI enabled. Chromium builds without RTTI by default,
74  # but some sanitizers are known to require it, like CFI diagnostics
75  # and UBsan variants.
76  use_rtti = use_cfi_diag || is_ubsan_vptr || is_ubsan_security
77
78  # AFDO (Automatic Feedback Directed Optimizer) is a form of profile-guided
79  # optimization that GCC supports. It used by ChromeOS in their official
80  # builds. To use it, set auto_profile_path to the path to a file containing
81  # the needed gcov profiling data.
82  auto_profile_path = ""
83
84  # Optimize for coverage guided fuzzing (balance between speed and number of
85  # branches)
86  optimize_for_fuzzing = false
87
88  # Path to an AFDO profile to use while building with clang, if any. Empty
89  # implies none.
90  clang_sample_profile_path = ""
91
92  # Some configurations have default sample profiles. If this is true and
93  # clang_sample_profile_path is empty, we'll fall back to the default.
94  #
95  # We currently only have default profiles for Chromium in-tree, so we disable
96  # this by default for all downstream projects, since these profiles are likely
97  # nonsensical for said projects.
98  clang_use_default_sample_profile =
99      chrome_pgo_phase == 0 && build_with_chromium && is_official_build &&
100      ((is_android && !is_high_end_android) || chromeos_is_browser_only)
101
102  # This configuration is used to select a default profile in Chrome OS based on
103  # the microarchitectures we are using. This is only used if
104  # clang_use_default_sample_profile is true and clang_sample_profile_path is
105  # empty.
106  chromeos_afdo_platform = "atom"
107
108  # Emit debug information for profiling wile building with clang.
109  # Only enable this for ChromeOS official builds for AFDO.
110  clang_emit_debug_info_for_profiling = is_chromeos_device && is_official_build
111
112  # Turn this on to have the compiler output extra timing information.
113  compiler_timing = false
114
115  # Turn this on to use ghash feature of lld for faster debug link on Windows.
116  # http://blog.llvm.org/2018/01/improving-link-time-on-windows-with.html
117  use_ghash = true
118
119  # Whether to enable ThinLTO optimizations. Turning ThinLTO optimizations on
120  # can substantially increase link time and binary size, but they generally
121  # also make binaries a fair bit faster.
122  #
123  # TODO(gbiv): We disable optimizations by default on most platforms because
124  # the space overhead is too great. We should use some mixture of profiles and
125  # optimization settings to better tune the size increase.
126  thin_lto_enable_optimizations =
127      (is_chromeos || is_android || is_win || is_linux || is_mac ||
128       (is_ios && use_lld)) && is_official_build
129
130  # Whether to enable thin lto incremental builds.
131  # See: https://clang.llvm.org/docs/ThinLTO.html#incremental
132  # The cache can lead to non-determinism: https://crbug.com/1486045
133  thin_lto_enable_cache = true
134
135  # Initialize all local variables with a pattern. This flag will fill
136  # uninitialized floating-point types (and 32-bit pointers) with 0xFF and the
137  # rest with 0xAA. This makes behavior of uninitialized memory bugs consistent,
138  # recognizable in the debugger, and crashes on memory accesses through
139  # uninitialized pointers.
140  #
141  # Flag discussion: https://crbug.com/977230
142  #
143  # TODO(crbug.com/40721698): This regresses binary size by ~1MB on Android and
144  # needs to be evaluated before enabling it there as well.
145  init_stack_vars = !(is_android && is_official_build)
146
147  # Zero init has favorable performance/size tradeoffs for Chrome OS
148  # but was not evaluated for other platforms.
149  init_stack_vars_zero = is_chromeos
150
151  # This argument is to control whether enabling text section splitting in the
152  # final binary. When enabled, the separated text sections with prefix
153  # '.text.hot', '.text.unlikely', '.text.startup' and '.text.exit' will not be
154  # merged to '.text' section. This allows us to identify the hot code section
155  # ('.text.hot') in the binary, which allows our data collection pipelines to
156  # more easily identify code that we assume to be hot/cold that doesn't turn
157  # out to be such in the field.
158  use_text_section_splitting = is_chromeos
159
160  # Enable DWARF v5.
161  use_dwarf5 = false
162
163  # Override this to put full paths to PDBs in Windows PE files. This helps
164  # windbg and Windows Performance Analyzer with finding the PDBs in some local-
165  # build scenarios. This is never needed for bots or official builds. Because
166  # this puts the output directory in the DLLs/EXEs it breaks build determinism.
167  # Bugs have been reported to the windbg/WPA teams and this workaround will be
168  # removed when they are fixed.
169  use_full_pdb_paths = false
170
171  # Enable -H, which prints the include tree during compilation.
172  # For use by tools/clang/scripts/analyze_includes.py
173  show_includes = false
174
175  # Enable Profi algorithm. Profi can infer block and edge counts.
176  # https://clang.llvm.org/docs/UsersManual.html#using-sampling-profilers
177  # TODO(crbug.com/1375958i:) Possibly enable this for Android too.
178  use_profi = is_chromeos
179
180  # If true, linker crashes will be rerun with `--reproduce` which causes
181  # a reproducer file to be saved.
182  save_reproducers_on_lld_crash = false
183
184  # Enable ShadowCallStack for compiled binaries. SCS stores a pointer to a
185  # shadow call stack in register x18. Hence, x18 must not be used by the OS
186  # or libraries. We assume that to be the case for high end Android
187  # configurations. For more details see
188  # https://clang.llvm.org/docs/ShadowCallStack.html
189  enable_shadow_call_stack = false
190
191  # Use DWARF simple template names, with the following exceptions:
192  #
193  # * Windows is not supported as it doesn't use DWARF.
194  # * Apple platforms (e.g. MacOS, iPhone, iPad) aren't supported because xcode
195  #   lldb doesn't have the needed changes yet.
196  # TODO(crbug.com/40244196): Remove if the upstream default ever changes.
197  #
198  # This greatly reduces the size of debug builds, at the cost of
199  # debugging information which is required by some specialized
200  # debugging tools.
201  simple_template_names = is_clang && !is_nacl && !is_win && !is_apple
202}
203
204declare_args() {
205  # Set to true to use icf, Identical Code Folding.
206  use_icf = (is_posix || is_fuchsia) && !is_debug && !using_sanitizer &&
207            !use_clang_coverage && current_os != "zos" &&
208            !(is_android && use_order_profiling) && use_lld
209}
210
211if (is_android) {
212  # Set the path to use orderfile for linking Chrome
213  # Note that this is for using only one orderfile for linking
214  # the Chrome binary/library.
215  declare_args() {
216    chrome_orderfile_path = ""
217
218    # The orderfile is trained on PGO builds (for arm64) and AFDO builds (for
219    # arm32), so apply them only in these cases.
220    if (defined(default_chrome_orderfile)) {
221      if (((current_cpu == "arm64" || current_cpu == "x64") &&
222           chrome_pgo_phase == 2) ||
223          ((current_cpu == "arm" || current_cpu == "x86") &&
224           clang_use_default_sample_profile)) {
225        chrome_orderfile_path = default_chrome_orderfile
226      }
227    }
228  }
229}
230
231declare_args() {
232  # Turn off the --call-graph-profile-sort flag for lld by default. Enable
233  # selectively for targets where it's beneficial.
234  enable_call_graph_profile_sort =
235      chrome_pgo_phase == 2 ||
236      (is_chromeos &&
237       (clang_use_default_sample_profile || clang_sample_profile_path != ""))
238}
239
240assert(!(llvm_force_head_revision && use_remoteexec && host_os != "linux"),
241       "rbe with locally built clang only works on linux")
242
243# default_include_dirs ---------------------------------------------------------
244#
245# This is a separate config so that third_party code (which would not use the
246# source root and might have conflicting versions of some headers) can remove
247# this and specify their own include paths.
248config("default_include_dirs") {
249  include_dirs = [
250    "//",
251    root_gen_dir,
252  ]
253}
254
255# Compiler instrumentation can introduce dependencies in DSOs to symbols in
256# the executable they are loaded into, so they are unresolved at link-time.
257config("no_unresolved_symbols") {
258  if (!using_sanitizer &&
259      (is_linux || is_chromeos || is_android || is_fuchsia)) {
260    ldflags = [
261      "-Wl,-z,defs",
262      "-Wl,--as-needed",
263    ]
264  }
265}
266
267# compiler ---------------------------------------------------------------------
268#
269# Base compiler configuration.
270#
271# See also "runtime_library" below for related stuff and a discussion about
272# where stuff should go. Put warning related stuff in the "warnings" config.
273
274config("compiler") {
275  asmflags = []
276  cflags = []
277  cflags_c = []
278  cflags_cc = []
279  cflags_objc = []
280  cflags_objcc = []
281  rustflags = []
282  ldflags = []
283  defines = []
284  configs = []
285
286  # System-specific flags. If your compiler flags apply to one of the
287  # categories here, add it to the associated file to keep this shared config
288  # smaller.
289  if (is_win) {
290    configs += [ "//build/config/win:compiler" ]
291  } else if (is_android) {
292    configs += [ "//build/config/android:compiler" ]
293  } else if (is_linux || is_chromeos) {
294    configs += [ "//build/config/linux:compiler" ]
295  } else if (is_nacl) {
296    configs += [ "//build/config/nacl:compiler" ]
297  } else if (is_mac) {
298    configs += [ "//build/config/mac:compiler" ]
299  } else if (is_ios) {
300    configs += [ "//build/config/ios:compiler" ]
301  } else if (is_fuchsia) {
302    configs += [ "//build/config/fuchsia:compiler" ]
303  } else if (current_os == "aix") {
304    configs += [ "//build/config/aix:compiler" ]
305  } else if (current_os == "zos") {
306    configs += [ "//build/config/zos:compiler" ]
307  }
308
309  configs += [
310    # See the definitions below.
311    ":clang_revision",
312    ":rustc_revision",
313    ":compiler_cpu_abi",
314    ":compiler_codegen",
315    ":compiler_deterministic",
316  ]
317
318  # Here we enable -fno-delete-null-pointer-checks, which makes various nullptr
319  # operations (e.g. dereferencing) into defined behavior. This avoids deletion
320  # of some security-critical code: see https://crbug.com/1139129.
321  # The older NaCl toolchain does not support the flag. And, we still want UBSan
322  # to catch undefined behavior related to nullptrs, so do not add this flag if
323  # UBSan is enabled. GCC seems to have some bugs compiling constexpr code when
324  # this is defined, so only enable it if using_clang.
325  # See: https://gcc.gnu.org/PR97913
326  # TODO(mpdenton): remove is_clang once GCC bug is fixed.
327  if ((!is_nacl || is_nacl_saigo) && !is_ubsan && is_clang) {
328    cflags += [ "-fno-delete-null-pointer-checks" ]
329  }
330
331  # Don't emit the GCC version ident directives, they just end up in the
332  # .comment section or debug info taking up binary size, and makes comparing
333  # .o files built with different compiler versions harder.
334  if (!is_win || is_clang) {
335    cflags += [ "-fno-ident" ]
336  }
337
338  # In general, Windows is totally different, but all the other builds share
339  # some common compiler and linker configuration.
340  if (!is_win) {
341    # Common POSIX compiler flags setup.
342    # --------------------------------
343    cflags += [ "-fno-strict-aliasing" ]  # See http://crbug.com/32204
344
345    # Stack protection. ShadowCallStack and Stack protector address the same
346    # problems. Therefore, we only enable one or the other. Clang advertises SCS as
347    # a stronger alternative to StackProtector, so we give SCS precedence over SP.
348    if (enable_shadow_call_stack) {
349      # On Aarch64, SCS requires the x18 register to be unused because it will hold
350      # a pointer to the shadow stack. For Android we know that Clang doesn't use
351      # x18 by default. On other OSs adding "-ffixed-x18" might be required.
352      assert(is_android)
353
354      scs_parameters = [
355        "-fsanitize=shadow-call-stack",
356        "-fno-stack-protector",
357      ]
358      cflags += scs_parameters
359      ldflags += scs_parameters
360    } else {
361      if (is_apple) {
362        # The strong variant of the stack protector significantly increases
363        # binary size, so only enable it in debug mode.
364        if (is_debug) {
365          cflags += [ "-fstack-protector-strong" ]
366        } else {
367          cflags += [ "-fstack-protector" ]
368        }
369      } else if (is_chromeos) {
370        cflags += [ "-fstack-protector-strong" ]
371      } else if ((is_posix && !is_nacl) || is_fuchsia) {
372        if (current_os != "aix") {
373          # Not available on aix.
374          cflags += [ "-fstack-protector" ]
375        }
376      }
377    }
378
379    if (use_lld) {
380      ldflags += [ "-fuse-ld=lld" ]
381      if (lld_path != "") {
382        ldflags += [ "-B$lld_path" ]
383      }
384    }
385
386    # Linker warnings.
387    if (fatal_linker_warnings && !is_apple && current_os != "aix" &&
388        current_os != "zos") {
389      ldflags += [ "-Wl,--fatal-warnings" ]
390    }
391    if (fatal_linker_warnings && is_apple) {
392      ldflags += [ "-Wl,-fatal_warnings" ]
393    }
394  }
395
396  if (is_clang && is_debug) {
397    # Allow comparing the address of references and 'this' against 0
398    # in debug builds. Technically, these can never be null in
399    # well-defined C/C++ and Clang can optimize such checks away in
400    # release builds, but they may be used in asserts in debug builds.
401    cflags_cc += [
402      "-Wno-undefined-bool-conversion",
403      "-Wno-tautological-undefined-compare",
404    ]
405  }
406
407  # Non-Apple Posix and Fuchsia compiler flags setup.
408  # -----------------------------------
409  if ((is_posix && !is_apple) || is_fuchsia) {
410    if (enable_profiling) {
411      if (!is_debug) {
412        cflags += [ "-g" ]
413
414        if (enable_full_stack_frames_for_profiling) {
415          cflags += [
416            "-fno-inline",
417            "-fno-optimize-sibling-calls",
418          ]
419        }
420      }
421    }
422
423    # Explicitly pass --build-id to ld. Compilers used to always pass this
424    # implicitly but don't any more (in particular clang when built without
425    # ENABLE_LINKER_BUILD_ID=ON).
426    if (is_official_build) {
427      # The sha1 build id has lower risk of collision but is more expensive to
428      # compute, so only use it in the official build to avoid slowing down
429      # links.
430      ldflags += [ "-Wl,--build-id=sha1" ]
431    } else if (current_os != "aix" && current_os != "zos") {
432      if (use_lld && !is_nacl) {
433        ldflags += [ "-Wl,--build-id=fast" ]
434      } else {
435        ldflags += [ "-Wl,--build-id" ]
436      }
437    }
438
439    if (!is_android) {
440      defines += [
441        # _FILE_OFFSET_BITS=64 should not be set on Android in order to maintain
442        # the behavior of the Android NDK from earlier versions.
443        # See https://android-developers.googleblog.com/2017/09/introducing-android-native-development.html
444        "_FILE_OFFSET_BITS=64",
445        "_LARGEFILE_SOURCE",
446        "_LARGEFILE64_SOURCE",
447      ]
448    }
449
450    if (!is_nacl) {
451      if (exclude_unwind_tables) {
452        cflags += [
453          "-fno-unwind-tables",
454          "-fno-asynchronous-unwind-tables",
455        ]
456        rustflags += [ "-Cforce-unwind-tables=no" ]
457        defines += [ "NO_UNWIND_TABLES" ]
458      } else {
459        cflags += [ "-funwind-tables" ]
460        rustflags += [ "-Cforce-unwind-tables=yes" ]
461      }
462    }
463  }
464
465  # Apple compiler flags setup.
466  # ---------------------------------
467  if (is_apple) {
468    # On Intel, clang emits both Apple's "compact unwind" information and
469    # DWARF eh_frame unwind information by default, for compatibility reasons.
470    # This flag limits emission of eh_frame information to functions
471    # whose unwind information can't be expressed in the compact unwind format
472    # (which in practice means almost everything gets only compact unwind
473    # entries). This reduces object file size a bit and makes linking a bit
474    # faster.
475    # On arm64, this is already the default behavior.
476    if (current_cpu == "x64") {
477      asmflags += [ "-femit-dwarf-unwind=no-compact-unwind" ]
478      cflags += [ "-femit-dwarf-unwind=no-compact-unwind" ]
479    }
480
481    # dsymutil is not available in the system, on bots, for rustc to call. Our
482    # linker_driver.py script runs dsymutil itself, which is set to be the
483    # linker for Rust targets as well.
484    rustflags += [ "-Csplit-debuginfo=unpacked" ]
485  }
486
487  # Linux/Android/Fuchsia common flags setup.
488  # ---------------------------------
489  if (is_linux || is_chromeos || is_android || is_fuchsia) {
490    asmflags += [ "-fPIC" ]
491    cflags += [ "-fPIC" ]
492    ldflags += [ "-fPIC" ]
493    rustflags += [ "-Crelocation-model=pic" ]
494
495    if (!is_clang) {
496      # Use pipes for communicating between sub-processes. Faster.
497      # (This flag doesn't do anything with Clang.)
498      cflags += [ "-pipe" ]
499    }
500
501    ldflags += [
502      "-Wl,-z,noexecstack",
503      "-Wl,-z,relro",
504    ]
505
506    if (!is_component_build) {
507      ldflags += [ "-Wl,-z,now" ]
508    }
509  }
510
511  # Linux-specific compiler flags setup.
512  # ------------------------------------
513  if (use_icf && (!is_apple || use_lld)) {
514    ldflags += [ "-Wl,--icf=all" ]
515  }
516
517  if (is_linux || is_chromeos) {
518    cflags += [ "-pthread" ]
519    # Do not use the -pthread ldflag here since it becomes a no-op
520    # when using -nodefaultlibs, which would cause an unused argument
521    # error.  "-lpthread" is added in //build/config:default_libs.
522  }
523
524  # ChromeOS-specific compiler flags setup.
525  # ---------------------------------------
526  if (is_chromeos) {
527    cflags += [ "-Werror=poison-system-directories" ]
528  }
529
530  # Clang-specific compiler flags setup.
531  # ------------------------------------
532  if (is_clang) {
533    cflags += [ "-fcolor-diagnostics" ]
534
535    # Enable -fmerge-all-constants. This used to be the default in clang
536    # for over a decade. It makes clang non-conforming, but is fairly safe
537    # in practice and saves some binary size. We might want to consider
538    # disabling this (https://bugs.llvm.org/show_bug.cgi?id=18538#c13),
539    # but for now it looks like our build might rely on it
540    # (https://crbug.com/829795).
541    cflags += [ "-fmerge-all-constants" ]
542
543    # TODO(crbug.com/345541122): investigate the fuchsia binary size increase.
544    if (is_win) {
545      cflags += [ "/Zc:sizedDealloc-" ]
546    } else {
547      cflags += [ "-fno-sized-deallocation" ]
548    }
549  }
550
551  if (use_lld) {
552    # TODO(thakis): Make the driver pass --color-diagnostics to the linker
553    # if -fcolor-diagnostics is passed to it, and pass -fcolor-diagnostics
554    # in ldflags instead.
555    if (is_win) {
556      # On Windows, we call the linker directly, instead of calling it through
557      # the driver.
558      ldflags += [ "--color-diagnostics" ]
559    } else {
560      ldflags += [ "-Wl,--color-diagnostics" ]
561    }
562  }
563
564  # Enable text section splitting only on linux when using lld for now. Other
565  # platforms can be added later if needed.
566  if ((is_linux || is_chromeos) && use_lld && use_text_section_splitting) {
567    ldflags += [ "-Wl,-z,keep-text-section-prefix" ]
568  }
569
570  if (is_clang && !is_nacl) {
571    cflags += [ "-fcrash-diagnostics-dir=" + clang_diagnostic_dir ]
572    if (save_reproducers_on_lld_crash && use_lld) {
573      ldflags += [
574        "-fcrash-diagnostics=all",
575        "-fcrash-diagnostics-dir=" + clang_diagnostic_dir,
576      ]
577    }
578
579    # TODO(hans): Remove this once Clang generates better optimized debug info
580    # by default. https://crbug.com/765793
581    cflags += [
582      "-mllvm",
583      "-instcombine-lower-dbg-declare=0",
584    ]
585    if (!is_debug && use_thin_lto && is_a_target_toolchain) {
586      if (is_win) {
587        ldflags += [ "-mllvm:-instcombine-lower-dbg-declare=0" ]
588      } else {
589        ldflags += [ "-Wl,-mllvm,-instcombine-lower-dbg-declare=0" ]
590      }
591    }
592
593    # TODO(crbug.com/40283598): This causes binary size growth and potentially
594    # other problems.
595    # TODO(crbug.com/40284925): This isn't supported by Cronet's mainline llvm version.
596    if (default_toolchain != "//build/toolchain/cros:target" &&
597        !llvm_android_mainline) {
598      cflags += [
599        "-mllvm",
600        "-split-threshold-for-reg-with-hint=0",
601      ]
602      if (use_thin_lto && is_a_target_toolchain) {
603        if (is_win) {
604          ldflags += [ "-mllvm:-split-threshold-for-reg-with-hint=0" ]
605        } else {
606          ldflags += [ "-Wl,-mllvm,-split-threshold-for-reg-with-hint=0" ]
607        }
608      }
609    }
610
611    # TODO(crbug.com/40192287): Investigate why/if this should be needed.
612    if (is_win) {
613      cflags += [ "/clang:-ffp-contract=off" ]
614    } else {
615      cflags += [ "-ffp-contract=off" ]
616    }
617
618    # Enable ELF CREL (see crbug.com/357878242) for all platforms that use ELF
619    # (excluding toolchains that use an older version of LLVM).
620    # TODO(crbug.com/376278218): This causes segfault on Linux ARM builds.
621    if (is_linux && !llvm_android_mainline && current_cpu != "arm" &&
622        default_toolchain != "//build/toolchain/cros:target") {
623      cflags += [ "-Wa,--crel,--allow-experimental-crel" ]
624    }
625  }
626
627  # C11/C++11 compiler flags setup.
628  # ---------------------------
629  if (is_linux || is_chromeos || is_android || (is_nacl && is_clang) ||
630      current_os == "aix") {
631    if (is_clang) {
632      standard_prefix = "c"
633
634      # Since we build with -std=c* and not -std=gnu*, _GNU_SOURCE will not be
635      # defined by the compiler.  However, lots of code relies on the
636      # non-standard features that _GNU_SOURCE enables, so define it manually.
637      defines += [ "_GNU_SOURCE" ]
638
639      if (is_nacl) {
640        # Undefine __STRICT_ANSI__ to get non-standard features which would
641        # otherwise not be enabled by NaCl's sysroots.
642        cflags += [ "-U__STRICT_ANSI__" ]
643      }
644    } else {
645      # Gcc does not support ##__VA_ARGS__ when in standards-conforming mode,
646      # but we use this feature in several places in Chromium.
647      # TODO(thomasanderson): Replace usages of ##__VA_ARGS__ with the
648      # standard-compliant __VA_OPT__ added by C++20, and switch the gcc build
649      # to -std=c*.
650      standard_prefix = "gnu"
651    }
652
653    cflags_c += [ "-std=${standard_prefix}11" ]
654    if (is_nacl && !is_nacl_saigo) {
655      # This is for the pnacl_newlib toolchain. It's only used to build
656      # a few independent ppapi test files that don't pull in any other
657      # dependencies.
658      cflags_cc += [ "-std=${standard_prefix}++14" ]
659      if (is_clang) {
660        cflags_cc += [ "-fno-trigraphs" ]
661      }
662    } else if (is_clang) {
663      if (defined(use_cxx17) && use_cxx17) {
664        cflags_cc += [ "-std=${standard_prefix}++17" ]
665      } else {
666        cflags_cc += [ "-std=${standard_prefix}++20" ]
667      }
668    } else {
669      # The gcc bots are currently using GCC 9, which is not new enough to
670      # support "c++20"/"gnu++20".
671      cflags_cc += [ "-std=${standard_prefix}++2a" ]
672    }
673  } else if (is_win) {
674    cflags_c += [ "/std:c11" ]
675    if (defined(use_cxx17) && use_cxx17) {
676      cflags_cc += [ "/std:c++17" ]
677    } else {
678      cflags_cc += [ "/std:c++20" ]
679    }
680    if (!is_clang) {
681      # Required for the __cplusplus macro definition to match the C++ version
682      # on MSVC. clang-cl defines it by default and doesn't need this flag.
683      # See: https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus
684      cflags_cc += [ "/Zc:__cplusplus" ]
685    }
686  } else if (!is_nacl) {
687    # TODO(mcgrathr) - the NaCl GCC toolchain doesn't support either
688    # gnu11/gnu++11 or c11/c++11; we technically don't need this toolchain any
689    # more, but there are still a few buildbots using it, so until those are
690    # turned off we need the !is_nacl clause and the (is_nacl && is_clang)
691    # clause, above.
692    cflags_c += [ "-std=c11" ]
693
694    if (defined(use_cxx17) && use_cxx17) {
695      cflags_cc += [ "-std=c++17" ]
696    } else {
697      cflags_cc += [ "-std=c++20" ]
698    }
699  }
700
701  if (is_clang) {
702    # C++17 removes trigraph support, but clang still warns that it ignores
703    # them when seeing them.  Don't.
704    cflags_cc += [ "-Wno-trigraphs" ]
705  }
706
707  if (use_relative_vtables_abi) {
708    cflags_cc += [ "-fexperimental-relative-c++-abi-vtables" ]
709    ldflags += [ "-fexperimental-relative-c++-abi-vtables" ]
710  }
711
712  # Add flags for link-time optimization. These flags enable
713  # optimizations/transformations that require whole-program visibility at link
714  # time, so they need to be applied to all translation units, and we may end up
715  # with miscompiles if only part of the program is compiled with LTO flags. For
716  # that reason, we cannot allow targets to enable or disable these flags, for
717  # example by disabling the optimize configuration.
718  # TODO(pcc): Make this conditional on is_official_build rather than on gn
719  # flags for specific features.
720  #
721  # High-end Android: While Full LTO provides a small performance improvement
722  # (according to Speedometer), it also results in an unacceptable increase in
723  # build time. Thin LTO appears to provide the best build time-optimization
724  # tradeoff. As of April 2024, Full LTO:
725  #   - Increases build time by ~1:30 hours, to ~2:40 hours (from ~1:10 hours
726  #     with Thin LTO) on Chromium builders.
727  #   - Increases Speedometer 2.1 score by 1.1% [0].
728  #   - Increases Speedometer 3.0 score by 1.2% [1].
729  # ... over Thin LTO.
730  #
731  # [0]: https://pinpoint-dot-chromeperf.appspot.com/job/15efb0313e0000
732  # [1]: https://pinpoint-dot-chromeperf.appspot.com/job/157f0b42be0000
733  if (!is_debug && use_thin_lto && is_a_target_toolchain) {
734    assert(use_lld, "LTO is only supported with lld")
735
736    cflags += [
737      "-flto=thin",
738      "-fsplit-lto-unit",
739    ]
740
741    if (thin_lto_enable_cache) {
742      # Limit the size of the ThinLTO cache to the lesser of 10% of
743      # available disk space, 40GB and 100000 files.
744      cache_policy =
745          "cache_size=10%:cache_size_bytes=40g:cache_size_files=100000"
746      cache_dir = rebase_path("$root_out_dir/thinlto-cache", root_build_dir)
747      if (is_win) {
748        ldflags += [
749          "/lldltocache:$cache_dir",
750          "/lldltocachepolicy:$cache_policy",
751        ]
752      } else {
753        if (is_apple) {
754          ldflags += [ "-Wl,-cache_path_lto,$cache_dir" ]
755        } else {
756          ldflags += [ "-Wl,--thinlto-cache-dir=$cache_dir" ]
757        }
758        ldflags += [ "-Wl,--thinlto-cache-policy=$cache_policy" ]
759      }
760    }
761
762    # An import limit of 30 has better performance (per speedometer) and lower
763    # binary size than the default setting of 100.
764    # TODO(gbiv): We ideally shouldn't need to specify this; ThinLTO
765    # should be able to better manage binary size increases on its own.
766    #
767    # For high-end Android, 30 seems to be the right trade-off between performance
768    # and binary size, at least based on Speedometer. For example, increasing
769    # `import_instr_limit`to 50 improves Speedometer 2.1 score by 0.7% [0], while
770    # Speedometer 3.0 score remains roughly the same (-0.1%) [1]. The binary size
771    # increases by about 2MB [2] (or 1.1%: the arm64 native code size in M124 is
772    # 178MB).
773    # [0]: https://pinpoint-dot-chromeperf.appspot.com/job/16984a18be0000
774    # [1]: https://pinpoint-dot-chromeperf.appspot.com/job/11984a18be0000
775    # [2]: https://ci.chromium.org/ui/p/chromium/builders/try/android-binary-size/1848442
776    import_instr_limit = 30
777
778    if (is_win) {
779      ldflags += [
780        "/opt:lldltojobs=all",
781        "-mllvm:-import-instr-limit=$import_instr_limit",
782        "-mllvm:-disable-auto-upgrade-debug-info",
783      ]
784    } else {
785      ldflags += [ "-flto=thin" ]
786
787      # Enabling ThinLTO on Chrome OS too, in an effort to reduce the memory
788      # usage in crbug.com/1038040. Note this will increase build time in
789      # Chrome OS.
790
791      # In ThinLTO builds, we run at most one link process at a time,
792      # and let it use all cores.
793      # TODO(thakis): Check if '=0' (that is, number of cores, instead
794      # of "all" which means number of hardware threads) is faster.
795      ldflags += [ "-Wl,--thinlto-jobs=all" ]
796
797      if (is_chromeos) {
798        # ARM was originally set lower than x86 to keep the size
799        # bloat of ThinLTO to <10%, but that's potentially no longer true.
800        # FIXME(inglorion): maybe tune these?
801        # TODO(b/271459198): Revert limit on amd64 to 30 when fixed.
802        import_instr_limit = 20
803      } else if (is_android && optimize_for_size) {
804        # TODO(crbug.com/40219076): Investigate if we can get the > 6% perf win
805        # of import_instr_limit 30 with a binary size hit smaller than ~2 MiB.
806        import_instr_limit = 5
807      }
808
809      ldflags += [ "-Wl,-mllvm,-import-instr-limit=$import_instr_limit" ]
810
811      if (is_apple) {
812        ldflags += [ "-Wcrl,object_path_lto" ]
813      }
814
815      # We only use one version of LLVM within a build so there's no need to
816      # upgrade debug info, which can be expensive since it runs the verifier.
817      ldflags += [ "-Wl,-mllvm,-disable-auto-upgrade-debug-info" ]
818    }
819
820    if (!optimize_for_size) {
821      # Ideally the compiler would handle this automatically with PGO (see
822      # comments at https://crrev.com/c/5440500).
823      cflags += [
824        "-mllvm",
825        "-inlinehint-threshold=360",
826      ]
827      if (is_win) {
828        ldflags += [ "-mllvm:-inlinehint-threshold=360" ]
829      } else {
830        ldflags += [ "-Wl,-mllvm,-inlinehint-threshold=360" ]
831      }
832    }
833
834    # TODO(crbug.com/40182783): investigate why this isn't effective on
835    # arm32.
836    if (!is_android || current_cpu == "arm64") {
837      cflags += [ "-fwhole-program-vtables" ]
838
839      if (toolchain_supports_rust_thin_lto) {
840        # whole-program-vtables implies -fsplit-lto-unit, and Rust needs to match
841        # behaviour. Rust needs to know the linker will be doing LTO in this case
842        # or it rejects the Zsplit-lto-unit flag.
843        rustflags += [
844          "-Zsplit-lto-unit",
845          "-Clinker-plugin-lto=yes",
846        ]
847      } else {
848        # Don't include bitcode if it won't be used.
849        rustflags += [ "-Cembed-bitcode=no" ]
850      }
851
852      if (!is_win) {
853        ldflags += [ "-fwhole-program-vtables" ]
854      }
855    }
856
857    # This flag causes LTO to create an .ARM.attributes section with the correct
858    # architecture. This is necessary because LLD will refuse to link a program
859    # unless the architecture revision in .ARM.attributes is sufficiently new.
860    # TODO(pcc): The contents of .ARM.attributes should be based on the
861    # -march flag passed at compile time (see llvm.org/pr36291).
862    if (current_cpu == "arm") {
863      ldflags += [ "-march=$arm_arch" ]
864    }
865  }
866
867  if (compiler_timing) {
868    if (is_clang && !is_nacl) {
869      cflags += [ "-ftime-trace" ]
870      if (use_lld && is_mac) {
871        ldflags += [ "-Wl,--time-trace" ]
872      }
873    } else if (is_win) {
874      cflags += [
875        # "Documented" here:
876        # http://aras-p.info/blog/2017/10/23/Best-unknown-MSVC-flag-d2cgsummary/
877        "/d2cgsummary",
878      ]
879    }
880  }
881
882  # Pass flag to LLD so Android builds can allow debuggerd to properly symbolize
883  # stack crashes (http://crbug.com/919499).
884  if (use_lld && is_android) {
885    ldflags += [ "-Wl,--no-rosegment" ]
886  }
887
888  # TODO(crbug.com/40242425): Cleanup undefined symbol errors caught by
889  # --no-undefined-version.
890  if (use_lld && !is_win && !is_mac && !is_ios) {
891    ldflags += [ "-Wl,--undefined-version" ]
892  }
893
894  if (use_lld && is_apple) {
895    ldflags += [ "-Wl,--strict-auto-link" ]
896  }
897
898  # LLD does call-graph-sorted binary layout by default when profile data is
899  # present. On Android this increases binary size due to more thinks for long
900  # jumps. Turn it off by default and enable selectively for targets where it's
901  # beneficial.
902  if (use_lld && !enable_call_graph_profile_sort) {
903    if (is_win) {
904      ldflags += [ "/call-graph-profile-sort:no" ]
905    } else {
906      ldflags += [ "-Wl,--no-call-graph-profile-sort" ]
907    }
908  }
909
910  if (is_clang && !is_nacl && show_includes) {
911    if (is_win) {
912      cflags += [
913        "/clang:-H",
914        "/clang:-fshow-skipped-includes",
915      ]
916    } else {
917      cflags += [
918        "-H",
919        "-fshow-skipped-includes",
920      ]
921    }
922  }
923
924  # This flag enforces that member pointer base types are complete. It helps
925  # prevent us from running into problems in the Microsoft C++ ABI (see
926  # https://crbug.com/847724).
927  if (is_clang && !is_nacl && target_os != "chromeos" &&
928      (is_win || use_custom_libcxx)) {
929    cflags += [ "-fcomplete-member-pointers" ]
930  }
931
932  # Use DWARF simple template names.
933  if (simple_template_names) {
934    cflags_cc += [ "-gsimple-template-names" ]
935  }
936
937  # MLGO specific flags. These flags enable an ML-based inliner trained on
938  # Chrome on Android (arm32) with ThinLTO enabled, optimizing for size.
939  # The "release" ML model is embedded into clang as part of its build.
940  # Currently, the ML inliner is only enabled when targeting Android due to:
941  # a) Android is where size matters the most.
942  # b) MLGO presently has the limitation of only being able to embed one model
943  #    at a time; It is unclear if the embedded model is beneficial for
944  #    non-Android targets.
945  # MLGO is only officially supported on linux.
946  if (use_ml_inliner && is_a_target_toolchain) {
947    assert(
948        is_android && host_os == "linux",
949        "MLGO is currently only supported for targeting Android on a linux host")
950    if (use_thin_lto) {
951      ldflags += [ "-Wl,-mllvm,-enable-ml-inliner=release" ]
952      if (is_high_end_android) {
953        # Besides using the arm64 - trained model, instruct the inline advisor
954        # to not use the ML policy (which will aim to reduce size) for any
955        # callsites where the caller is not cold. This avoids performance
956        # regressions while still bringing size benefits.
957        # Profile quality is essential here.
958        ldflags += [
959          "-Wl,-mllvm,-ml-inliner-model-selector=arm64-mixed",
960          "-Wl,-mllvm,-ml-inliner-skip-policy=if-caller-not-cold",
961        ]
962      } else {
963        ldflags += [ "-Wl,-mllvm,-ml-inliner-model-selector=arm32-size" ]
964      }
965    }
966  }
967
968  if (clang_embed_bitcode) {
969    assert(!use_thin_lto,
970           "clang_embed_bitcode is only supported in non-ThinLTO builds")
971    cflags += [
972      "-Xclang",
973      "-fembed-bitcode=all",
974    ]
975  }
976
977  if (lld_emit_indexes_and_imports) {
978    assert(use_thin_lto,
979           "lld_emit_indexes_and_imports is only supported with ThinLTO builds")
980    ldflags += [
981      "-Wl,--save-temps=import",
982      "-Wl,--thinlto-emit-index-files",
983    ]
984  }
985
986  # Pass the same C/C++ flags to the objective C/C++ compiler.
987  cflags_objc += cflags_c
988  cflags_objcc += cflags_cc
989
990  # Assign any flags set for the C compiler to asmflags so that they are sent
991  # to the assembler. The Windows assembler takes different types of flags
992  # so only do so for posix platforms.
993  if (is_posix || is_fuchsia) {
994    asmflags += cflags
995    asmflags += cflags_c
996  }
997
998  if (is_chromeos_device && !is_nacl) {
999    # On ChromeOS devices, we want to ensure we're using Chrome's allocator
1000    # symbols for all C++ new/delete operator overloads. PartitionAlloc
1001    # and other local allocators should always take precedence over system or
1002    # preloaded allocators. These are the mangled symbol names.
1003    # See b/280115910 for details.
1004    ldflags += [
1005      "-Wl,--export-dynamic-symbol=_ZdaPv,-u,_ZdaPv",
1006      "-Wl,--export-dynamic-symbol=_ZdaPvRKSt9nothrow_t,-u,_ZdaPvRKSt9nothrow_t",
1007      "-Wl,--export-dynamic-symbol=_ZdlPv,-u,_ZdlPv",
1008      "-Wl,--export-dynamic-symbol=_ZdlPvm,-u,_ZdlPvm",
1009      "-Wl,--export-dynamic-symbol=_ZdlPvRKSt9nothrow_t,-u,_ZdlPvRKSt9nothrow_t",
1010      "-Wl,--export-dynamic-symbol=_Znam,-u,_Znam",
1011      "-Wl,--export-dynamic-symbol=_ZnamRKSt9nothrow_t,-u,_ZnamRKSt9nothrow_t",
1012      "-Wl,--export-dynamic-symbol=_Znwm,-u,_Znwm",
1013      "-Wl,--export-dynamic-symbol=_ZnwmRKSt9nothrow_t,-u,_ZnwmRKSt9nothrow_t",
1014      "-Wl,--export-dynamic-symbol=_ZdaPvmSt11align_val_t,-u,_ZdaPvmSt11align_val_t",
1015      "-Wl,--export-dynamic-symbol=_ZdaPvSt11align_val_t,-u,_ZdaPvSt11align_val_t",
1016      "-Wl,--export-dynamic-symbol=_ZdaPvSt11align_val_tRKSt9nothrow_t,-u,_ZdaPvSt11align_val_tRKSt9nothrow_t",
1017      "-Wl,--export-dynamic-symbol=_ZdlPvmSt11align_val_t,-u,_ZdlPvmSt11align_val_t",
1018      "-Wl,--export-dynamic-symbol=_ZdlPvSt11align_val_t,-u,_ZdlPvSt11align_val_t",
1019      "-Wl,--export-dynamic-symbol=_ZdlPvSt11align_val_tRKSt9nothrow_t,-u,_ZdlPvSt11align_val_tRKSt9nothrow_t",
1020      "-Wl,--export-dynamic-symbol=_ZnamSt11align_val_t,-u,_ZnamSt11align_val_t",
1021      "-Wl,--export-dynamic-symbol=_ZnamSt11align_val_tRKSt9nothrow_t,-u,_ZnamSt11align_val_tRKSt9nothrow_t",
1022      "-Wl,--export-dynamic-symbol=_ZnwmSt11align_val_t,-u,_ZnwmSt11align_val_t",
1023      "-Wl,--export-dynamic-symbol=_ZnwmSt11align_val_tRKSt9nothrow_t,-u,_ZnwmSt11align_val_tRKSt9nothrow_t",
1024    ]
1025  }
1026
1027  # Rust compiler flags setup.
1028  # ---------------------------
1029  rustflags += [
1030    # Overflow checks are optional in Rust, but even if switched
1031    # off they do not cause undefined behavior (the overflowing
1032    # behavior is defined). Because containers are bounds-checked
1033    # in safe Rust, they also can't provoke buffer overflows.
1034    # As such these checks may be less important in Rust than C++.
1035    # But in (simplistic) testing they have negligible performance
1036    # overhead, and this helps to provide consistent behavior
1037    # between different configurations, so we'll keep them on until
1038    # we discover a reason to turn them off.
1039    "-Coverflow-checks=on",
1040
1041    # By default Rust passes `-nodefaultlibs` to the linker, however this
1042    # conflicts with our `--unwind=none` flag for Android dylibs, as the latter
1043    # is then unused and produces a warning/error. So this removes the
1044    # `-nodefaultlibs` from the linker invocation from Rust, which would be used
1045    # to compile dylibs on Android, such as for constructing unit test APKs.
1046    "-Cdefault-linker-libraries",
1047
1048    # To make Rust .d files compatible with ninja
1049    "-Zdep-info-omit-d-target",
1050
1051    # If a macro panics during compilation, show which macro and where it is
1052    # defined.
1053    "-Zmacro-backtrace",
1054
1055    # For deterministic builds, keep the local machine's current working
1056    # directory from appearing in build outputs.
1057    "-Zremap-cwd-prefix=.",
1058
1059    # We use clang-rt sanitizer runtimes.
1060    "-Zexternal-clangrt",
1061  ]
1062
1063  if (!is_win || force_rustc_color_output) {
1064    # Colorize error output. The analogous flag is passed for clang. This must
1065    # be platform-gated since rustc will unconditionally output ANSI escape
1066    # sequences, ignoring the platform, when stderr is not a terminal.
1067    rustflags += [ "--color=always" ]
1068  }
1069  if (rust_abi_target != "") {
1070    rustflags += [ "--target=$rust_abi_target" ]
1071  }
1072  if (!use_thin_lto || !toolchain_supports_rust_thin_lto) {
1073    # Don't include bitcode if it won't be used.
1074    rustflags += [ "-Cembed-bitcode=no" ]
1075
1076    # Disable "automatic" ThinLTO between codegen units. The weak symbol
1077    # resolution across units can have surprising effects on linking, see
1078    # crbug.com/324126269 and github.com/rust-lang/rust/issues/120842.
1079    rustflags += [ "-Clto=no" ]
1080  }
1081  if (is_official_build) {
1082    rustflags += [ "-Ccodegen-units=1" ]
1083  }
1084  if (!rust_prebuilt_stdlib) {
1085    # When building against the Chromium Rust stdlib (which we compile) always
1086    # abort instead of unwinding when panic occurs. In official builds, panics
1087    # abort immediately (this is configured in the stdlib) to keep binary size
1088    # down. So we unconditionally match behaviour in unofficial too.
1089    rustflags += [
1090      "-Cpanic=abort",
1091      "-Zpanic_abort_tests",
1092    ]
1093  }
1094
1095  # 64-bit Android sometimes defines __ARM_NEON but not __ARM_NEON__.
1096  # 32-bit Android builds and macOS, however, define __ARM_NEON__,
1097  # and code typically checks for this.
1098  #
1099  # Reduce confusion by making the __ARM_NEON__ #define always available,
1100  # as NEON is a mandatory part of ARMv8 anyway.
1101  if (current_cpu == "arm64") {
1102    defines += [ "__ARM_NEON__=1" ]
1103  }
1104}
1105
1106# Don't allow unstable features to be enabled by `#![feature()]` without
1107# additional command line flags.
1108config("disallow_unstable_features") {
1109  rustflags = [ "-Zallow-features=" ]
1110}
1111
1112config("libcxx_hardening") {
1113  # Normally, this would be defined in the `runtime_library` config but NaCl
1114  # saigo libc++ does not use the custom hermetic libc++. Unfortunately, there
1115  # isn't really a better config to add this define for the define to
1116  # consistently apply in both Chromium and non-Chromium code *and* non-NaCl and
1117  # NaCl code.
1118  #
1119  # TODO(crbug.com/40511454): Move this back to the `runtime_library` config
1120  # when NaCl is removed.
1121  if (use_safe_libcxx) {
1122    # TODO(crbug.com/40275904): Switch saigo to hardened mode once it's rolled
1123    # in.
1124    if (is_nacl_saigo) {
1125      defines = [ "_LIBCPP_ENABLE_ASSERTIONS=1" ]
1126    } else {
1127      defines = [ "_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE" ]
1128    }
1129  } else {
1130    defines = [ "_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE" ]
1131  }
1132
1133  # Enable libstdc++ hardening lightweight assertions. Those have a low
1134  # performance penalty but are considered a bare minimum for security.
1135  if (use_safe_libstdcxx) {
1136    defines += [ "_GLIBCXX_ASSERTIONS=1" ]
1137  }
1138}
1139
1140# The BUILDCONFIG file sets this config on targets by default, which means when
1141# building with ThinLTO, no optimization is performed in the link step.
1142config("thinlto_optimize_default") {
1143  if (!is_debug && use_thin_lto && is_a_target_toolchain) {
1144    lto_opt_level = 0
1145
1146    if (is_win) {
1147      ldflags = [ "/opt:lldlto=" + lto_opt_level ]
1148    } else {
1149      ldflags = [ "-Wl,--lto-O" + lto_opt_level ]
1150    }
1151
1152    if (toolchain_supports_rust_thin_lto) {
1153      # We always point Rust to a linker that performs LTO, so we don't want Rust
1154      # to preemptively do so during compilation too or they conflict. But we do
1155      # want Rust to generate LTO metadata in order for the linker to do its job.
1156      rustflags = [ "-Clinker-plugin-lto=yes" ]
1157    } else {
1158      # Don't include bitcode if it won't be used.
1159      rustflags = [ "-Cembed-bitcode=no" ]
1160    }
1161  }
1162}
1163
1164# Use this to enable optimization in the ThinLTO link step for select targets
1165# when thin_lto_enable_optimizations is set by doing:
1166#
1167#   configs -= [ "//build/config/compiler:thinlto_optimize_default" ]
1168#   configs += [ "//build/config/compiler:thinlto_optimize_max" ]
1169#
1170# Since it makes linking significantly slower and more resource intensive, only
1171# use it on important targets such as the main browser executable or dll.
1172config("thinlto_optimize_max") {
1173  if (!is_debug && use_thin_lto && is_a_target_toolchain) {
1174    if (thin_lto_enable_optimizations) {
1175      lto_opt_level = 2
1176    } else {
1177      lto_opt_level = 0
1178    }
1179
1180    if (is_win) {
1181      ldflags = [ "/opt:lldlto=" + lto_opt_level ]
1182    } else {
1183      ldflags = [ "-Wl,--lto-O" + lto_opt_level ]
1184    }
1185
1186    if (toolchain_supports_rust_thin_lto) {
1187      # We always point Rust to a linker that performs LTO, so we don't want Rust
1188      # to preemptively do so during compilation too or they conflict. But we do
1189      # want Rust to generate LTO metadata in order for the linker to do its job.
1190      rustflags = [ "-Clinker-plugin-lto=yes" ]
1191    } else {
1192      # Don't include bitcode if it won't be used.
1193      rustflags = [ "-Cembed-bitcode=no" ]
1194    }
1195  }
1196}
1197
1198# This provides the basic options to select the target CPU and ABI.
1199# It is factored out of "compiler" so that special cases can use this
1200# without using everything that "compiler" brings in.  Options that
1201# tweak code generation for a particular CPU do not belong here!
1202# See "compiler_codegen", below.
1203config("compiler_cpu_abi") {
1204  cflags = []
1205  ldflags = []
1206  defines = []
1207
1208  configs = []
1209  if (is_chromeos) {
1210    configs += [ "//build/config/chromeos:compiler_cpu_abi" ]
1211  }
1212
1213  if ((is_posix && !is_apple) || is_fuchsia) {
1214    # CPU architecture. We may or may not be doing a cross compile now, so for
1215    # simplicity we always explicitly set the architecture.
1216    if (current_cpu == "x64") {
1217      cflags += [
1218        "-m64",
1219        "-msse3",
1220      ]
1221
1222      # Minimum SIMD support for devices running lacros.
1223      # See https://crbug.com/1475858
1224      if (is_chromeos_lacros) {
1225        cflags += [
1226          "-mssse3",
1227          "-msse4",
1228          "-msse4.1",
1229          "-msse4.2",
1230        ]
1231      }
1232      ldflags += [ "-m64" ]
1233    } else if (current_cpu == "x86") {
1234      cflags += [ "-m32" ]
1235      ldflags += [ "-m32" ]
1236      if (!is_nacl) {
1237        cflags += [
1238          "-mfpmath=sse",
1239          "-msse3",
1240        ]
1241      }
1242    } else if (current_cpu == "arm") {
1243      if (is_clang && !is_android && !is_nacl && !is_chromeos_device) {
1244        cflags += [ "--target=arm-linux-gnueabihf" ]
1245        ldflags += [ "--target=arm-linux-gnueabihf" ]
1246      }
1247      if (!is_nacl) {
1248        cflags += [
1249          "-march=$arm_arch",
1250          "-mfloat-abi=$arm_float_abi",
1251        ]
1252      }
1253      if (arm_tune != "") {
1254        cflags += [ "-mtune=$arm_tune" ]
1255      }
1256    } else if (current_cpu == "arm64") {
1257      if (is_clang && !is_android && !is_nacl && !is_fuchsia &&
1258          !is_chromeos_device) {
1259        cflags += [ "--target=aarch64-linux-gnu" ]
1260        ldflags += [ "--target=aarch64-linux-gnu" ]
1261      }
1262    } else if (current_cpu == "mipsel" && !is_nacl) {
1263      ldflags += [ "-Wl,--hash-style=sysv" ]
1264      if (custom_toolchain == "") {
1265        if (is_clang) {
1266          if (is_android) {
1267            cflags += [ "--target=mipsel-linux-android" ]
1268            ldflags += [ "--target=mipsel-linux-android" ]
1269          } else {
1270            cflags += [ "--target=mipsel-linux-gnu" ]
1271            ldflags += [ "--target=mipsel-linux-gnu" ]
1272          }
1273        } else {
1274          cflags += [ "-EL" ]
1275          ldflags += [ "-EL" ]
1276        }
1277      }
1278
1279      if (mips_arch_variant == "r6") {
1280        cflags += [ "-mno-odd-spreg" ]
1281        ldflags += [ "-mips32r6" ]
1282        if (is_clang) {
1283          cflags += [
1284            "-march=mipsel",
1285            "-mcpu=mips32r6",
1286          ]
1287        } else {
1288          cflags += [
1289            "-mips32r6",
1290            "-Wa,-mips32r6",
1291          ]
1292          if (is_android) {
1293            ldflags += [ "-Wl,-melf32ltsmip" ]
1294          }
1295        }
1296        if (mips_use_msa == true) {
1297          cflags += [
1298            "-mmsa",
1299            "-mfp64",
1300          ]
1301        }
1302      } else if (mips_arch_variant == "r2") {
1303        ldflags += [ "-mips32r2" ]
1304        if (is_clang) {
1305          cflags += [
1306            "-march=mipsel",
1307            "-mcpu=mips32r2",
1308          ]
1309        } else {
1310          cflags += [
1311            "-mips32r2",
1312            "-Wa,-mips32r2",
1313          ]
1314          if (mips_float_abi == "hard" && mips_fpu_mode != "") {
1315            cflags += [ "-m$mips_fpu_mode" ]
1316          }
1317        }
1318      } else if (mips_arch_variant == "r1") {
1319        ldflags += [ "-mips32" ]
1320        if (is_clang) {
1321          cflags += [
1322            "-march=mipsel",
1323            "-mcpu=mips32",
1324          ]
1325        } else {
1326          cflags += [
1327            "-mips32",
1328            "-Wa,-mips32",
1329          ]
1330        }
1331      } else if (mips_arch_variant == "loongson3") {
1332        defines += [ "_MIPS_ARCH_LOONGSON" ]
1333        cflags += [
1334          "-march=loongson3a",
1335          "-mno-branch-likely",
1336          "-Wa,-march=loongson3a",
1337        ]
1338      }
1339
1340      if (mips_dsp_rev == 1) {
1341        cflags += [ "-mdsp" ]
1342      } else if (mips_dsp_rev == 2) {
1343        cflags += [ "-mdspr2" ]
1344      }
1345
1346      cflags += [ "-m${mips_float_abi}-float" ]
1347    } else if (current_cpu == "mips" && !is_nacl) {
1348      ldflags += [ "-Wl,--hash-style=sysv" ]
1349      if (custom_toolchain == "") {
1350        if (is_clang) {
1351          cflags += [ "--target=mips-linux-gnu" ]
1352          ldflags += [ "--target=mips-linux-gnu" ]
1353        } else {
1354          cflags += [ "-EB" ]
1355          ldflags += [ "-EB" ]
1356        }
1357      }
1358
1359      if (mips_arch_variant == "r6") {
1360        cflags += [
1361          "-mips32r6",
1362          "-Wa,-mips32r6",
1363        ]
1364        if (mips_use_msa == true) {
1365          cflags += [
1366            "-mmsa",
1367            "-mfp64",
1368          ]
1369        }
1370      } else if (mips_arch_variant == "r2") {
1371        cflags += [
1372          "-mips32r2",
1373          "-Wa,-mips32r2",
1374        ]
1375        if (mips_float_abi == "hard" && mips_fpu_mode != "") {
1376          cflags += [ "-m$mips_fpu_mode" ]
1377        }
1378      } else if (mips_arch_variant == "r1") {
1379        cflags += [
1380          "-mips32",
1381          "-Wa,-mips32",
1382        ]
1383      }
1384
1385      if (mips_dsp_rev == 1) {
1386        cflags += [ "-mdsp" ]
1387      } else if (mips_dsp_rev == 2) {
1388        cflags += [ "-mdspr2" ]
1389      }
1390
1391      cflags += [ "-m${mips_float_abi}-float" ]
1392    } else if (current_cpu == "mips64el") {
1393      cflags += [ "-D__SANE_USERSPACE_TYPES__" ]
1394      ldflags += [ "-Wl,--hash-style=sysv" ]
1395      if (custom_toolchain == "") {
1396        if (is_clang) {
1397          if (is_android) {
1398            cflags += [ "--target=mips64el-linux-android" ]
1399            ldflags += [ "--target=mips64el-linux-android" ]
1400          } else {
1401            cflags += [ "--target=mips64el-linux-gnuabi64" ]
1402            ldflags += [ "--target=mips64el-linux-gnuabi64" ]
1403          }
1404        } else {
1405          cflags += [
1406            "-EL",
1407            "-mabi=64",
1408          ]
1409          ldflags += [
1410            "-EL",
1411            "-mabi=64",
1412          ]
1413        }
1414      }
1415
1416      if (mips_arch_variant == "r6") {
1417        if (is_clang) {
1418          cflags += [
1419            "-march=mips64el",
1420            "-mcpu=mips64r6",
1421          ]
1422        } else {
1423          cflags += [
1424            "-mips64r6",
1425            "-Wa,-mips64r6",
1426          ]
1427          ldflags += [ "-mips64r6" ]
1428        }
1429        if (mips_use_msa == true) {
1430          cflags += [
1431            "-mmsa",
1432            "-mfp64",
1433          ]
1434        }
1435      } else if (mips_arch_variant == "r2") {
1436        ldflags += [ "-mips64r2" ]
1437        if (is_clang) {
1438          cflags += [
1439            "-march=mips64el",
1440            "-mcpu=mips64r2",
1441          ]
1442        } else {
1443          cflags += [
1444            "-mips64r2",
1445            "-Wa,-mips64r2",
1446          ]
1447        }
1448      } else if (mips_arch_variant == "loongson3") {
1449        defines += [ "_MIPS_ARCH_LOONGSON" ]
1450        cflags += [
1451          "-march=loongson3a",
1452          "-mno-branch-likely",
1453          "-Wa,-march=loongson3a",
1454        ]
1455      }
1456    } else if (current_cpu == "mips64") {
1457      ldflags += [ "-Wl,--hash-style=sysv" ]
1458      if (custom_toolchain == "") {
1459        if (is_clang) {
1460          cflags += [ "--target=mips64-linux-gnuabi64" ]
1461          ldflags += [ "--target=mips64-linux-gnuabi64" ]
1462        } else {
1463          cflags += [
1464            "-EB",
1465            "-mabi=64",
1466          ]
1467          ldflags += [
1468            "-EB",
1469            "-mabi=64",
1470          ]
1471        }
1472      }
1473
1474      if (mips_arch_variant == "r6") {
1475        cflags += [
1476          "-mips64r6",
1477          "-Wa,-mips64r6",
1478        ]
1479        ldflags += [ "-mips64r6" ]
1480
1481        if (mips_use_msa == true) {
1482          cflags += [
1483            "-mmsa",
1484            "-mfp64",
1485          ]
1486        }
1487      } else if (mips_arch_variant == "r2") {
1488        cflags += [
1489          "-mips64r2",
1490          "-Wa,-mips64r2",
1491        ]
1492        ldflags += [ "-mips64r2" ]
1493      }
1494    } else if (current_cpu == "ppc64") {
1495      if (current_os == "aix") {
1496        cflags += [ "-maix64" ]
1497        ldflags += [ "-maix64" ]
1498      } else {
1499        cflags += [ "-m64" ]
1500        ldflags += [ "-m64" ]
1501      }
1502    } else if (current_cpu == "riscv64") {
1503      if (is_clang && !is_android) {
1504        cflags += [ "--target=riscv64-linux-gnu" ]
1505        ldflags += [ "--target=riscv64-linux-gnu" ]
1506      }
1507      cflags += [ "-mabi=lp64d" ]
1508    } else if (current_cpu == "loong64") {
1509      if (is_clang) {
1510        cflags += [ "--target=loongarch64-linux-gnu" ]
1511        ldflags += [ "--target=loongarch64-linux-gnu" ]
1512      }
1513      cflags += [
1514        "-mabi=lp64d",
1515        "-mcmodel=medium",
1516      ]
1517    } else if (current_cpu == "s390x") {
1518      cflags += [ "-m64" ]
1519      ldflags += [ "-m64" ]
1520    }
1521  }
1522
1523  asmflags = cflags
1524}
1525
1526# This provides options to tweak code generation that are necessary
1527# for particular Chromium code or for working around particular
1528# compiler bugs (or the combination of the two).
1529config("compiler_codegen") {
1530  configs = []
1531  cflags = []
1532  ldflags = []
1533
1534  if (is_nacl) {
1535    configs += [ "//build/config/nacl:compiler_codegen" ]
1536  }
1537
1538  if (current_cpu == "arm64" && !is_win && is_clang) {
1539    # Disable outlining everywhere on arm64 except Win. For more information see
1540    # crbug.com/931297 for Android and crbug.com/1410297 for iOS.
1541    # TODO(crbug.com/40890229): Enable this on Windows if possible.
1542    cflags += [ "-mno-outline" ]
1543
1544    # This can be removed once https://bugs.llvm.org/show_bug.cgi?id=40348
1545    # has been resolved, and -mno-outline is obeyed by the linker during
1546    # ThinLTO.
1547    ldflags += [ "-Wl,-mllvm,-enable-machine-outliner=never" ]
1548  }
1549
1550  asmflags = cflags
1551}
1552
1553# This provides options that make the build deterministic, so that the same
1554# revision produces the same output, independent of the name of the build
1555# directory and of the computer the build is done on.
1556# The relative path from build dir to source dir makes it into the build
1557# outputs, so it's recommended that you use a build dir two levels deep
1558# (e.g. "out/Release") so that you get the same "../.." path as all the bots
1559# in your build outputs.
1560config("compiler_deterministic") {
1561  cflags = []
1562  ldflags = []
1563  swiftflags = []
1564
1565  # Eliminate build metadata (__DATE__, __TIME__ and __TIMESTAMP__) for
1566  # deterministic build.  See https://crbug.com/314403
1567  if (!is_official_build) {
1568    if (is_win && !is_clang) {
1569      cflags += [
1570        "/wd4117",  # Trying to define or undefine a predefined macro.
1571        "/D__DATE__=",
1572        "/D__TIME__=",
1573        "/D__TIMESTAMP__=",
1574      ]
1575    } else {
1576      cflags += [
1577        "-Wno-builtin-macro-redefined",
1578        "-D__DATE__=",
1579        "-D__TIME__=",
1580        "-D__TIMESTAMP__=",
1581      ]
1582    }
1583  }
1584
1585  # Makes builds independent of absolute file path.
1586  if (is_clang && strip_absolute_paths_from_debug_symbols) {
1587    # If debug option is given, clang includes $cwd in debug info by default.
1588    # For such build, this flag generates reproducible obj files even we use
1589    # different build directory like "out/feature_a" and "out/feature_b" if
1590    # we build same files with same compile flag.
1591    # Other paths are already given in relative, no need to normalize them.
1592    if (is_nacl) {
1593      # TODO(https://crbug.com/1231236): Use -ffile-compilation-dir= here.
1594      cflags += [
1595        "-Xclang",
1596        "-fdebug-compilation-dir",
1597        "-Xclang",
1598        ".",
1599      ]
1600    } else {
1601      # -ffile-compilation-dir is an alias for both -fdebug-compilation-dir=
1602      # and -fcoverage-compilation-dir=.
1603      cflags += [ "-ffile-compilation-dir=." ]
1604
1605      # Convert absolute paths to relative paths. Expands to, for example:
1606      #   -file-prefix-map /path/to/chromium/src=../..
1607      swiftflags += [
1608        "-file-prefix-map",
1609        rebase_path("//.", "") + "=" + rebase_path("//.", root_build_dir),
1610      ]
1611    }
1612    if (!is_win) {
1613      # We don't use clang -cc1as on Windows (yet? https://crbug.com/762167)
1614      asmflags = [ "-Wa,-fdebug-compilation-dir,." ]
1615    }
1616
1617    if (is_win && use_lld) {
1618      if (symbol_level == 2 || (is_clang && using_sanitizer)) {
1619        # Absolutize source file paths for PDB. Pass the real build directory
1620        # if the pdb contains source-level debug information and if linker
1621        # reproducibility is not critical.
1622        ldflags += [ "/PDBSourcePath:" + rebase_path(root_build_dir) ]
1623      } else {
1624        # Use a fake fixed base directory for paths in the pdb to make the pdb
1625        # output fully deterministic and independent of the build directory.
1626        ldflags += [ "/PDBSourcePath:o:\fake\prefix" ]
1627      }
1628    }
1629  }
1630
1631  # Tells the compiler not to use absolute paths when passing the default
1632  # paths to the tools it invokes. We don't want this because we don't
1633  # really need it and it can mess up the RBE cache entries.
1634  if (is_clang && (!is_nacl || is_nacl_saigo)) {
1635    cflags += [ "-no-canonical-prefixes" ]
1636
1637    # Same for links: Let the compiler driver invoke the linker
1638    # with a relative path and pass relative paths to built-in
1639    # libraries. Not needed on Windows because we call the linker
1640    # directly there, not through the compiler driver.
1641    # We don't link on RBE, so this change is just for cleaner
1642    # internal linker invocations, for people who work on the build.
1643    if (!is_win) {
1644      ldflags += [ "-no-canonical-prefixes" ]
1645    }
1646  }
1647}
1648
1649config("clang_revision") {
1650  if (is_clang && clang_base_path == default_clang_base_path &&
1651      current_os != "zos") {
1652    update_args = [
1653      "--print-revision",
1654      "--verify-version=$clang_version",
1655    ]
1656    if (llvm_force_head_revision) {
1657      update_args += [ "--llvm-force-head-revision" ]
1658    }
1659    clang_revision = exec_script("//tools/clang/scripts/update.py",
1660                                 update_args,
1661                                 "trim string")
1662
1663    # This is here so that all files get recompiled after a clang roll and
1664    # when turning clang on or off. (defines are passed via the command line,
1665    # and build system rebuild things when their commandline changes). Nothing
1666    # should ever read this define.
1667    defines = [ "CR_CLANG_REVISION=\"$clang_revision\"" ]
1668  }
1669}
1670
1671config("rustc_revision") {
1672  if (rustc_revision != "") {
1673    # Similar to the above config, this is here so that all files get recompiled
1674    # after a rustc roll. Nothing should ever read this cfg. This will not be
1675    # set if a custom toolchain is used.
1676    rustflags = [
1677      "--cfg",
1678      "cr_rustc_revision=\"$rustc_revision\"",
1679    ]
1680  }
1681}
1682
1683config("compiler_arm_fpu") {
1684  if (current_cpu == "arm" && !is_ios && !is_nacl) {
1685    cflags = [ "-mfpu=$arm_fpu" ]
1686    if (!arm_use_thumb) {
1687      cflags += [ "-marm" ]
1688    }
1689    asmflags = cflags
1690  }
1691}
1692
1693config("compiler_arm_thumb") {
1694  if (current_cpu == "arm" && arm_use_thumb && is_posix &&
1695      !(is_apple || is_nacl)) {
1696    cflags = [ "-mthumb" ]
1697  }
1698}
1699
1700config("compiler_arm") {
1701  if (current_cpu == "arm" && is_chromeos) {
1702    # arm is normally the default mode for clang, but on chromeos a wrapper
1703    # is used to pass -mthumb, and therefor change the default.
1704    cflags = [ "-marm" ]
1705  }
1706}
1707
1708config("libcxx_module") {
1709  if (use_libcxx_modules) {
1710    modulemap = rebase_path("//third_party/libc++/src/include/module.modulemap",
1711                            root_build_dir)
1712    cflags_cc = [
1713      "-fmodules",
1714      "-fmodule-map-file=" + modulemap,
1715      "-fno-implicit-module-maps",
1716      "-fbuiltin-module-map",
1717      "-fmodules-cache-path=" +
1718          rebase_path("$libcxx_module_prefix/module_cache", root_build_dir),
1719
1720      "-Xclang",
1721      "-fmodules-local-submodule-visibility",  # required for builtins
1722
1723      # TODO(crbug.com/1456385): Figure out if this can be removed.
1724      "-Wno-modules-ambiguous-internal-linkage",
1725
1726      # TODO(crbug.com/40440396): Clean up.
1727      "-Wno-modules-import-nested-redundant",
1728
1729      # Needed to allow using builtin modules when the headers are
1730      # unnecessarily using extern "C".
1731      "-Wno-module-import-in-extern-c",
1732    ]
1733  }
1734}
1735
1736# runtime_library -------------------------------------------------------------
1737#
1738# Sets the runtime library and associated options.
1739#
1740# How do you determine what should go in here vs. "compiler" above? Consider if
1741# a target might choose to use a different runtime library (ignore for a moment
1742# if this is possible or reasonable on your system). If such a target would want
1743# to change or remove your option, put it in the runtime_library config. If a
1744# target wants the option regardless, put it in the compiler config.
1745
1746config("runtime_library") {
1747  configs = []
1748
1749  # The order of this config is important: it must appear before
1750  # android:runtime_library.  This is to ensure libc++ appears before
1751  # libandroid_support in the -isystem include order.  Otherwise, there will be
1752  # build errors related to symbols declared in math.h.
1753  if (use_custom_libcxx) {
1754    configs += [ "//build/config/c++:runtime_library" ]
1755  }
1756
1757  # Rust and C++ both provide intrinsics for LLVM to call for math operations. We
1758  # want to use the C++ intrinsics, not the ones in the Rust compiler_builtins
1759  # library. The Rust symbols are marked as weak, so that they can be replaced by
1760  # the C++ symbols. This config ensures the C++ symbols exist and are strong in
1761  # order to cause that replacement to occur by explicitly linking in clang's
1762  # compiler-rt library.
1763  if (is_clang && !is_nacl && !is_cronet_build) {
1764    configs += [ "//build/config/clang:compiler_builtins" ]
1765  }
1766
1767  # TODO(crbug.com/40570904): Come up with a better name for is POSIX + Fuchsia
1768  # configuration.
1769  if (is_posix || is_fuchsia) {
1770    configs += [ "//build/config/posix:runtime_library" ]
1771
1772    if (use_custom_libunwind) {
1773      # Instead of using an unwind lib from the toolchain,
1774      # buildtools/third_party/libunwind will be built and used directly.
1775      ldflags = [ "--unwindlib=none" ]
1776    }
1777  }
1778
1779  # System-specific flags. If your compiler flags apply to one of the
1780  # categories here, add it to the associated file to keep this shared config
1781  # smaller.
1782  if (is_win) {
1783    configs += [ "//build/config/win:runtime_library" ]
1784  } else if (is_linux || is_chromeos) {
1785    configs += [ "//build/config/linux:runtime_library" ]
1786    if (is_chromeos) {
1787      configs += [ "//build/config/chromeos:runtime_library" ]
1788    }
1789  } else if (is_ios) {
1790    configs += [ "//build/config/ios:runtime_library" ]
1791  } else if (is_mac) {
1792    configs += [ "//build/config/mac:runtime_library" ]
1793  } else if (is_android) {
1794    configs += [ "//build/config/android:runtime_library" ]
1795  }
1796
1797  if (is_component_build) {
1798    defines = [ "COMPONENT_BUILD" ]
1799  }
1800}
1801
1802# treat_warnings_as_errors ----------------------------------------------------
1803#
1804# Adding this config causes the compiler to treat warnings as fatal errors.
1805# This is used as a subconfig of both chromium_code and no_chromium_code, and
1806# is broken out separately so nocompile tests can force-enable this setting
1807# independently of the default warning flags.
1808config("treat_warnings_as_errors") {
1809  if (is_win) {
1810    cflags = [ "/WX" ]
1811  } else {
1812    cflags = [ "-Werror" ]
1813
1814    # The compiler driver can sometimes (rarely) emit warnings before calling
1815    # the actual linker.  Make sure these warnings are treated as errors as
1816    # well.
1817    ldflags = [ "-Werror" ]
1818  }
1819
1820  # Turn rustc warnings into the "deny" lint level, which produce compiler
1821  # errors. The equivalent of -Werror for clang/gcc.
1822  #
1823  # Note we apply the actual lint flags in config("compiler"). All warnings
1824  # are suppressed in third-party crates.
1825  rustflags = [ "-Dwarnings" ]
1826
1827  # TODO(https://crbug.com/326247202): Fix unused imports and remove this flag.
1828  rustflags += [ "-Aunused-imports" ]
1829}
1830
1831# default_warnings ------------------------------------------------------------
1832#
1833# Collects all warning flags that are used by default.  This is used as a
1834# subconfig of both chromium_code and no_chromium_code.  This way these
1835# flags are guaranteed to appear on the compile command line after -Wall.
1836config("default_warnings") {
1837  cflags = []
1838  cflags_c = []
1839  cflags_cc = []
1840  ldflags = []
1841  configs = []
1842
1843  if (is_win) {
1844    if (fatal_linker_warnings) {
1845      arflags = [ "/WX" ]
1846      ldflags = [ "/WX" ]
1847    }
1848    defines = [
1849      # Without this, Windows headers warn that functions like wcsnicmp
1850      # should be spelled _wcsnicmp. But all other platforms keep spelling
1851      # it wcsnicmp, making this warning unhelpful. We don't want it.
1852      "_CRT_NONSTDC_NO_WARNINGS",
1853
1854      # TODO(thakis): winsock wants us to use getaddrinfo instead of
1855      # gethostbyname. Fires mostly in non-Chromium code. We probably
1856      # want to remove this define eventually.
1857      "_WINSOCK_DEPRECATED_NO_WARNINGS",
1858    ]
1859    if (!is_clang) {
1860      # TODO(thakis): Remove this once
1861      # https://swiftshader-review.googlesource.com/c/SwiftShader/+/57968 has
1862      # rolled into angle.
1863      cflags += [ "/wd4244" ]
1864    }
1865  } else {
1866    if ((is_apple || is_android) && !is_nacl) {
1867      # Warns if a method is used whose availability is newer than the
1868      # deployment target.
1869      cflags += [ "-Wunguarded-availability" ]
1870    }
1871
1872    if (is_ios) {
1873      # When compiling Objective-C, warns if a selector named via @selector has
1874      # not been defined in any visible interface.
1875      cflags += [ "-Wundeclared-selector" ]
1876
1877      # Blink builds use a higher deployment target than non-Blink builds, so
1878      # suppress deprecation warnings in these builds.
1879      if (use_blink) {
1880        cflags += [ "-Wno-deprecated-declarations" ]
1881      }
1882    }
1883
1884    # Suppress warnings about ABI changes on ARM (Clang doesn't give this
1885    # warning).
1886    if (current_cpu == "arm" && !is_clang) {
1887      cflags += [ "-Wno-psabi" ]
1888    }
1889
1890    if (!is_clang) {
1891      cflags_cc += [
1892        # See comment for -Wno-c++11-narrowing.
1893        "-Wno-narrowing",
1894      ]
1895
1896      # -Wno-class-memaccess warns about hash table and vector in blink.
1897      # But the violation is intentional.
1898      if (!is_nacl) {
1899        cflags_cc += [ "-Wno-class-memaccess" ]
1900      }
1901
1902      # -Wunused-local-typedefs is broken in gcc,
1903      # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63872
1904      cflags += [ "-Wno-unused-local-typedefs" ]
1905
1906      # Don't warn about "maybe" uninitialized. Clang doesn't include this
1907      # in -Wall but gcc does, and it gives false positives.
1908      cflags += [ "-Wno-maybe-uninitialized" ]
1909      cflags += [ "-Wno-deprecated-declarations" ]
1910
1911      # -Wcomment gives too many false positives in the case a
1912      # backslash ended comment line is followed by a new line of
1913      # comments
1914      # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61638
1915      cflags += [ "-Wno-comments" ]
1916
1917      # -Wpacked-not-aligned complains all generated mojom-shared-internal.h
1918      # files.
1919      cflags += [ "-Wno-packed-not-aligned" ]
1920    }
1921  }
1922
1923  # Common Clang and GCC warning setup.
1924  if (!is_win || is_clang) {
1925    cflags += [
1926      # Disables.
1927      "-Wno-missing-field-initializers",  # "struct foo f = {0};"
1928      "-Wno-unused-parameter",  # Unused function parameters.
1929    ]
1930
1931    cflags_cc += [
1932      # Disables for C++ only
1933      "-Wno-invalid-offsetof",  # offsetof on non-standard-layout type
1934                                # (crbug.com/40285259)
1935    ]
1936
1937    if (!is_nacl || is_nacl_saigo) {
1938      cflags += [
1939        # An ABI compat warning we don't care about, https://crbug.com/1102157
1940        # TODO(thakis): Push this to the (few) targets that need it,
1941        # instead of having a global flag.
1942        "-Wno-psabi",
1943      ]
1944    }
1945  }
1946
1947  if (is_clang) {
1948    cflags += [
1949      "-Wloop-analysis",
1950
1951      # TODO(thakis): This used to be implied by -Wno-unused-function,
1952      # which we no longer use. Check if it makes sense to remove
1953      # this as well. http://crbug.com/316352
1954      "-Wno-unneeded-internal-declaration",
1955    ]
1956
1957    if (!is_nacl || is_nacl_saigo) {
1958      if (is_win) {
1959        # TODO(thakis): https://crbug.com/617318
1960        # Currently RBE can not handle case sensitiveness for windows well.
1961        cflags += [ "-Wno-nonportable-include-path" ]
1962      }
1963
1964      if (is_fuchsia) {
1965        cflags_cc += [
1966          # TODO(crbug.com/42050603): fix and reenable
1967          "-Wno-missing-field-initializers",
1968        ]
1969      }
1970
1971      cflags += [
1972        # TODO(crbug.com/330524456): -Wcast-function-type is under -Wextra now.
1973        "-Wno-cast-function-type",
1974
1975        # TODO(crbug.com/40284799): Fix and re-enable.
1976        "-Wno-thread-safety-reference-return",
1977      ]
1978
1979      cflags_cc += [
1980        # TODO(crbug.com/328490295): Fix and re-enable for C flags.
1981        "-Wenum-compare-conditional",
1982      ]
1983
1984      if (!is_nacl) {
1985        cflags_cc += [
1986          # TODO(crbug.com/41486292): Fix and re-enable.
1987          "-Wno-c++11-narrowing-const-reference",
1988        ]
1989
1990        # TODO(crbug.com/344680447): Fix and re-enable.
1991        cflags_cc += [ "-Wno-missing-template-arg-list-after-template-kw" ]
1992
1993        # TODO(crbug.com/356172342): Fix and re-enable.
1994        cflags_cc += [ "-Wno-dangling-assignment-gsl" ]
1995
1996        # TODO(crbug.com/376641662): Fix and re-enable.
1997        cflags += [ "-Wno-nontrivial-memaccess" ]
1998      }
1999    }
2000
2001    # Some builders, such as Cronet, use a different version of Clang than
2002    # Chromium. This can cause minor errors when compiling Chromium changes. We
2003    # want to avoid these errors.
2004    if (llvm_android_mainline) {
2005      cflags += [
2006        "-Wno-error=unknown-warning-option",
2007        "-Wno-error=unused-command-line-argument",
2008        "-Wno-error=unknown-pragmas",
2009      ]
2010    }
2011  }
2012
2013  # TODO(crbug.com/354162568): Clean up and enable.
2014  if (is_apple && use_lld) {
2015    ldflags += [ "-Wl,--no-warn-duplicate-rpath" ]
2016  }
2017
2018  # TODO(crbug.com/355446806): Clean up and enable.
2019  if (is_apple) {
2020    ldflags += [ "-Wl,-no_warn_duplicate_libraries" ]
2021  }
2022
2023  # Rust warnings
2024
2025  # Require `unsafe` blocks even in `unsafe` fns. This is intended to become
2026  # an error by default eventually; see
2027  # https://github.com/rust-lang/rust/issues/71668
2028  rustflags = [ "-Dunsafe_op_in_unsafe_fn" ]
2029}
2030
2031# prevent_unsafe_narrowing ----------------------------------------------------
2032#
2033# Warnings that prevent narrowing or comparisons of integer types that are
2034# likely to cause out-of-bound read/writes or Undefined Behaviour. In
2035# particular, size_t is used for memory sizes, allocation, indexing, and
2036# offsets. Using other integer types along with size_t produces risk of
2037# memory-safety bugs and thus security exploits.
2038#
2039# In order to prevent these bugs, allocation sizes were historically limited to
2040# sizes that can be represented within 31 bits of information, allowing `int` to
2041# be safely misused instead of `size_t` (https://crbug.com/169327). In order to
2042# support increasing the allocation limit we require strictly adherence to
2043# using the correct types, avoiding lossy conversions, and preventing overflow.
2044# To do so, enable this config and fix errors by converting types to be
2045# `size_t`, which is both large enough and unsigned, when dealing with memory
2046# sizes, allocations, indices, or offsets.In cases where type conversion is not
2047# possible or is superfluous, use base::strict_cast<> or base::checked_cast<>
2048# to convert to size_t as needed.
2049# See also: https://docs.google.com/document/d/1CTbQ-5cQjnjU8aCOtLiA7G6P0i5C6HpSDNlSNq6nl5E
2050#
2051# To enable in a GN target, use:
2052#   configs += [ "//build/config/compiler:prevent_unsafe_narrowing" ]
2053
2054config("prevent_unsafe_narrowing") {
2055  if (is_clang) {
2056    cflags = [
2057      "-Wshorten-64-to-32",
2058      "-Wimplicit-int-conversion",
2059      "-Wsign-compare",
2060      "-Wsign-conversion",
2061    ]
2062    if (!is_nacl) {
2063      cflags += [
2064        # Avoid bugs of the form `if (size_t i = size; i >= 0; --i)` while
2065        # fixing types to be sign-correct.
2066        "-Wtautological-unsigned-zero-compare",
2067      ]
2068    }
2069  }
2070}
2071
2072# chromium_code ---------------------------------------------------------------
2073#
2074# Toggles between higher and lower warnings for code that is (or isn't)
2075# part of Chromium.
2076
2077config("chromium_code") {
2078  if (is_win) {
2079    if (is_clang) {
2080      cflags = [ "/W4" ]  # Warning level 4.
2081
2082      # Opt in to additional [[nodiscard]] on standard library methods.
2083      defines = [ "_HAS_NODISCARD" ]
2084    }
2085  } else {
2086    cflags = [ "-Wall" ]
2087    if (is_clang) {
2088      # Enable extra warnings for chromium_code when we control the compiler.
2089      cflags += [ "-Wextra" ]
2090    }
2091
2092    # In Chromium code, we define __STDC_foo_MACROS in order to get the
2093    # C99 macros on Mac and Linux.
2094    defines = [
2095      "__STDC_CONSTANT_MACROS",
2096      "__STDC_FORMAT_MACROS",
2097    ]
2098
2099    if (!is_debug && !using_sanitizer && current_cpu != "s390x" &&
2100        current_cpu != "s390" && current_cpu != "ppc64" &&
2101        current_cpu != "mips" && current_cpu != "mips64" &&
2102        current_cpu != "riscv64" && current_cpu != "loong64") {
2103      # Non-chromium code is not guaranteed to compile cleanly with
2104      # _FORTIFY_SOURCE. Also, fortified build may fail when optimizations are
2105      # disabled, so only do that for Release build.
2106      fortify_level = "2"
2107
2108      # ChromeOS's toolchain supports a high-quality _FORTIFY_SOURCE=3
2109      # implementation with a few custom glibc patches. Use that if it's
2110      # available.
2111      if (is_chromeos_device && !lacros_use_chromium_toolchain) {
2112        fortify_level = "3"
2113      }
2114      defines += [ "_FORTIFY_SOURCE=" + fortify_level ]
2115    }
2116
2117    if (is_apple) {
2118      cflags_objc = [ "-Wimplicit-retain-self" ]
2119      cflags_objcc = [ "-Wimplicit-retain-self" ]
2120    }
2121
2122    if (is_mac) {
2123      cflags_objc += [ "-Wobjc-missing-property-synthesis" ]
2124      cflags_objcc += [ "-Wobjc-missing-property-synthesis" ]
2125    }
2126
2127    if (is_ios) {
2128      cflags_objc += [ "-Widiomatic-parentheses" ]
2129      cflags_objcc += [ "-Widiomatic-parentheses" ]
2130    }
2131  }
2132
2133  if (is_clang) {
2134    cflags += [
2135      # Warn on missing break statements at the end of switch cases.
2136      # For intentional fallthrough, use [[fallthrough]].
2137      "-Wimplicit-fallthrough",
2138
2139      # Warn on unnecessary extra semicolons outside of function definitions.
2140      "-Wextra-semi",
2141
2142      # Warn on unreachable code, including unreachable breaks and returns.
2143      # See https://crbug.com/346399#c148 for suppression strategies.
2144      "-Wunreachable-code-aggressive",
2145    ]
2146
2147    # Thread safety analysis is broken under nacl: https://crbug.com/982423.
2148    if (!is_nacl || is_nacl_saigo) {
2149      cflags += [
2150        # Thread safety analysis. See base/thread_annotations.h and
2151        # https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
2152        "-Wthread-safety",
2153
2154        # Warn on GNU extensions.
2155        "-Wgnu",
2156
2157        # TODO(crbug.com/357081796): Try to enable these.
2158        "-Wno-gnu-anonymous-struct",
2159        "-Wno-gnu-conditional-omitted-operand",
2160        "-Wno-gnu-include-next",
2161        "-Wno-gnu-label-as-value",
2162        "-Wno-gnu-redeclared-enum",
2163        "-Wno-gnu-statement-expression",
2164        "-Wno-gnu-zero-variadic-macro-arguments",
2165        "-Wno-zero-length-array",
2166      ]
2167
2168      if (is_chromeos) {
2169        cflags += [ "-Wno-gnu-offsetof-extensions" ]
2170      }
2171      if (is_ios) {
2172        cflags += [ "-Wno-gnu-case-range" ]
2173      }
2174    }
2175  }
2176
2177  configs = [
2178    ":default_warnings",
2179    ":noshadowing",
2180  ]
2181  if (treat_warnings_as_errors) {
2182    configs += [ ":treat_warnings_as_errors" ]
2183  }
2184}
2185
2186config("no_chromium_code") {
2187  cflags = []
2188  cflags_cc = []
2189  defines = []
2190
2191  if (is_win) {
2192    if (is_clang) {
2193      cflags += [ "/W3" ]  # Warning level 3.
2194    }
2195    cflags += [
2196      "/wd4800",  # Disable warning when forcing value to bool.
2197      "/wd4267",  # TODO(jschuh): size_t to int.
2198    ]
2199  } else {
2200    if (is_clang && !is_nacl) {
2201      # TODO(thakis): Remove !is_nacl once
2202      # https://codereview.webrtc.org/1552863002/ made its way into chromium.
2203      cflags += [ "-Wall" ]
2204    }
2205  }
2206
2207  if (is_clang) {
2208    cflags += [
2209      # Lots of third-party libraries have unused variables. Instead of
2210      # suppressing them individually, we just blanket suppress them here.
2211      "-Wno-unused-variable",
2212
2213      # Similarly, we're not going to fix all the C++11 narrowing issues in
2214      # third-party libraries.
2215      "-Wno-c++11-narrowing",
2216    ]
2217    if (!is_nacl) {
2218      cflags += [
2219        # Disabled for similar reasons as -Wunused-variable.
2220        "-Wno-unused-but-set-variable",
2221
2222        # TODO(crbug.com/40762742): Clean up and enable.
2223        "-Wno-misleading-indentation",
2224      ]
2225    }
2226  }
2227
2228  # Suppress all warnings in third party, as Cargo does:
2229  # https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints
2230  rustflags = [ "--cap-lints=allow" ]
2231
2232  configs = [ ":default_warnings" ]
2233
2234  # GCC may emit unsuppressible warnings so only apply this config when
2235  # building with clang. crbug.com/589724
2236  if (treat_warnings_as_errors && is_clang) {
2237    configs += [ ":treat_warnings_as_errors" ]
2238  }
2239}
2240
2241# noshadowing -----------------------------------------------------------------
2242#
2243# Allows turning -Wshadow on.
2244
2245config("noshadowing") {
2246  # This flag has to be disabled for nacl because the nacl compiler is too
2247  # strict about shadowing.
2248  if (is_clang && (!is_nacl || is_nacl_saigo)) {
2249    cflags = [ "-Wshadow" ]
2250  }
2251}
2252
2253# rtti ------------------------------------------------------------------------
2254#
2255# Allows turning Run-Time Type Identification on or off.
2256
2257config("rtti") {
2258  if (is_win) {
2259    cflags_cc = [ "/GR" ]
2260  } else {
2261    cflags_cc = [ "-frtti" ]
2262  }
2263}
2264
2265config("no_rtti") {
2266  # Some sanitizer configs may require RTTI to be left enabled globally
2267  if (!use_rtti) {
2268    if (is_win) {
2269      cflags_cc = [ "/GR-" ]
2270    } else {
2271      cflags_cc = [ "-fno-rtti" ]
2272      cflags_objcc = cflags_cc
2273    }
2274  }
2275}
2276
2277# export_dynamic ---------------------------------------------------------------
2278#
2279# Ensures all exported symbols are added to the dynamic symbol table.  This is
2280# necessary to expose Chrome's custom operator new() and operator delete() (and
2281# other memory-related symbols) to libraries.  Otherwise, they might
2282# (de)allocate memory on a different heap, which would spell trouble if pointers
2283# to heap-allocated memory are passed over shared library boundaries.
2284config("export_dynamic") {
2285  # TODO(crbug.com/40118868): Revisit after target_os flip is completed.
2286  if (is_linux || is_chromeos_lacros || export_libcxxabi_from_executables) {
2287    ldflags = [ "-rdynamic" ]
2288  }
2289}
2290
2291# thin_archive -----------------------------------------------------------------
2292#
2293# Enables thin archives on posix, and on windows when the lld linker is used.
2294# Regular archives directly include the object files used to generate it.
2295# Thin archives merely reference the object files.
2296# This makes building them faster since it requires less disk IO, but is
2297# inappropriate if you wish to redistribute your static library.
2298# This config is added to the global config, so thin archives should already be
2299# enabled.  If you want to make a distributable static library, you need to do 2
2300# things:
2301# 1. Set complete_static_lib so that all dependencies of the library make it
2302#    into the library. See `gn help complete_static_lib` for details.
2303# 2. Remove the thin_archive config, so that the .a file actually contains all
2304#    .o files, instead of just references to .o files in the build directoy
2305config("thin_archive") {
2306  if ((is_apple && use_lld) || (is_linux && !is_clang)) {
2307    # The macOS and iOS linker ld64.ldd doesn't support thin archive without
2308    # symbol table, gcc on linux also throws the error `archive has no index`.
2309    arflags = [
2310      "-T",
2311      "-s",
2312    ]
2313  } else if ((is_posix && !is_nacl && (!is_apple || use_lld)) || is_fuchsia) {
2314    # The macOS and iOS default linker ld64 does not support reading thin
2315    # archives.
2316    arflags = [
2317      "-T",
2318      "-S",
2319    ]
2320  } else if (is_win && use_lld) {
2321    arflags = [ "/llvmlibthin" ]
2322  }
2323}
2324
2325# exceptions -------------------------------------------------------------------
2326#
2327# Allows turning Exceptions on or off.
2328# Note: exceptions are disallowed in Google code.
2329
2330config("exceptions") {
2331  if (is_win) {
2332    # Enables exceptions in the STL.
2333    if (!use_custom_libcxx) {
2334      defines = [ "_HAS_EXCEPTIONS=1" ]
2335    }
2336    cflags_cc = [ "/EHsc" ]
2337  } else {
2338    cflags_cc = [ "-fexceptions" ]
2339    cflags_objcc = cflags_cc
2340  }
2341}
2342
2343config("no_exceptions") {
2344  if (is_win) {
2345    # Disables exceptions in the STL.
2346    # libc++ uses the __has_feature macro to control whether to use exceptions,
2347    # so defining this macro is unnecessary. Defining _HAS_EXCEPTIONS to 0 also
2348    # breaks libc++ because it depends on MSVC headers that only provide certain
2349    # declarations if _HAS_EXCEPTIONS is 1. Those MSVC headers do not use
2350    # exceptions, despite being conditional on _HAS_EXCEPTIONS.
2351    if (!use_custom_libcxx) {
2352      defines = [ "_HAS_EXCEPTIONS=0" ]
2353    }
2354  } else {
2355    cflags_cc = [ "-fno-exceptions" ]
2356    cflags_objcc = cflags_cc
2357  }
2358}
2359
2360# Warnings ---------------------------------------------------------------------
2361
2362# Generate a warning for code that might emit a static initializer.
2363# See: //docs/static_initializers.md
2364# See: https://groups.google.com/a/chromium.org/d/topic/chromium-dev/B9Q5KTD7iCo/discussion
2365config("wglobal_constructors") {
2366  if (is_clang) {
2367    cflags = [ "-Wglobal-constructors" ]
2368  }
2369}
2370
2371# This will generate warnings when using Clang if code generates exit-time
2372# destructors, which will slow down closing the program.
2373# TODO(thakis): Make this a blocklist instead, http://crbug.com/101600
2374config("wexit_time_destructors") {
2375  if (is_clang) {
2376    cflags = [ "-Wexit-time-destructors" ]
2377  }
2378}
2379
2380# Some code presumes that pointers to structures/objects are compatible
2381# regardless of whether what they point to is already known to be valid.
2382# gcc 4.9 and earlier had no way of suppressing this warning without
2383# suppressing the rest of them.  Here we centralize the identification of
2384# the gcc 4.9 toolchains.
2385config("no_incompatible_pointer_warnings") {
2386  cflags = []
2387  if (is_clang) {
2388    cflags += [ "-Wno-incompatible-pointer-types" ]
2389  } else if (current_cpu == "mipsel" || current_cpu == "mips64el") {
2390    cflags += [ "-w" ]
2391  } else if (is_chromeos_ash && current_cpu == "arm") {
2392    cflags += [ "-w" ]
2393  }
2394}
2395
2396# Optimization -----------------------------------------------------------------
2397#
2398# The BUILDCONFIG file sets the "default_optimization" config on targets by
2399# default. It will be equivalent to either "optimize" (release) or
2400# "no_optimize" (debug) optimization configs.
2401#
2402# You can override the optimization level on a per-target basis by removing the
2403# default config and then adding the named one you want:
2404#
2405#   configs -= [ "//build/config/compiler:default_optimization" ]
2406#   configs += [ "//build/config/compiler:optimize_max" ]
2407
2408# Shared settings for both "optimize" and "optimize_max" configs.
2409# IMPORTANT: On Windows "/O1" and "/O2" must go before the common flags.
2410if (is_win) {
2411  common_optimize_on_cflags = [
2412    "/Oy-",  # Disable omitting frame pointers, must be after /O2.
2413    "/Zc:inline",  # Remove unreferenced COMDAT (faster links).
2414  ]
2415  if (!is_asan) {
2416    common_optimize_on_cflags += [
2417      # Put data in separate COMDATs. This allows the linker
2418      # to put bit-identical constants at the same address even if
2419      # they're unrelated constants, which saves binary size.
2420      # This optimization can't be used when ASan is enabled because
2421      # it is not compatible with the ASan ODR checker.
2422      "/Gw",
2423    ]
2424  }
2425  common_optimize_on_ldflags = []
2426
2427  # /OPT:ICF is not desirable in Debug builds, since code-folding can result in
2428  # misleading symbols in stack traces.
2429  if (!is_debug && !is_component_build) {
2430    common_optimize_on_ldflags += [ "/OPT:ICF" ]  # Redundant COMDAT folding.
2431  }
2432
2433  if (is_official_build) {
2434    common_optimize_on_ldflags += [ "/OPT:REF" ]  # Remove unreferenced data.
2435  }
2436
2437  if (is_clang) {
2438    # See below.
2439    common_optimize_on_cflags += [ "/clang:-fno-math-errno" ]
2440  }
2441} else {
2442  common_optimize_on_cflags = []
2443  common_optimize_on_ldflags = []
2444
2445  if (is_android) {
2446    # TODO(jdduke) Re-enable on mips after resolving linking
2447    # issues with libc++ (crbug.com/456380).
2448    if (current_cpu != "mipsel" && current_cpu != "mips64el") {
2449      common_optimize_on_ldflags += [
2450        # Warn in case of text relocations.
2451        "-Wl,--warn-shared-textrel",
2452      ]
2453    }
2454  }
2455
2456  if (is_apple) {
2457    common_optimize_on_ldflags += [ "-Wl,-dead_strip" ]
2458
2459    if (is_official_build) {
2460      common_optimize_on_ldflags += [
2461        "-Wl,-no_data_in_code_info",
2462        "-Wl,-no_function_starts",
2463      ]
2464    }
2465  } else if (current_os != "aix" && current_os != "zos") {
2466    # Non-Mac Posix flags.
2467    # Aix does not support these.
2468
2469    common_optimize_on_cflags += [
2470      # Put data and code in their own sections, so that unused symbols
2471      # can be removed at link time with --gc-sections.
2472      "-fdata-sections",
2473      "-ffunction-sections",
2474    ]
2475    if ((!is_nacl || is_nacl_saigo) && is_clang) {
2476      # We don't care about unique section names, this makes object files a bit
2477      # smaller.
2478      common_optimize_on_cflags += [ "-fno-unique-section-names" ]
2479    }
2480
2481    if (is_official_build) {
2482      common_optimize_on_ldflags += [
2483        # Specifically tell the linker to perform optimizations.
2484        # See http://lwn.net/Articles/192624/.
2485        # -O2 enables string tail merge optimization in lld.
2486        "-Wl,-O2",
2487      ]
2488    }
2489
2490    common_optimize_on_ldflags += [ "-Wl,--gc-sections" ]
2491  }
2492
2493  # We cannot rely on errno being set after math functions,
2494  # especially since glibc does not set it. Thus, use -fno-math-errno
2495  # so that the compiler knows it can inline math functions.
2496  # Note that this is different from -ffast-math (even though -ffast-math
2497  # implies -fno-math-errno), which also allows a number of unsafe
2498  # optimizations.
2499  common_optimize_on_cflags += [ "-fno-math-errno" ]
2500}
2501
2502config("default_stack_frames") {
2503  if (!is_win) {
2504    if (enable_frame_pointers) {
2505      cflags = [ "-fno-omit-frame-pointer" ]
2506
2507      # Omit frame pointers for leaf functions on x86, otherwise building libyuv
2508      # gives clang's register allocator issues, see llvm.org/PR15798 /
2509      # crbug.com/233709
2510      if (is_clang && current_cpu == "x86" && !is_apple) {
2511        cflags += [ "-momit-leaf-frame-pointer" ]
2512      }
2513    } else {
2514      cflags = [ "-fomit-frame-pointer" ]
2515    }
2516  }
2517  # On Windows, the flag to enable framepointers "/Oy-" must always come after
2518  # the optimization flag [e.g. "/O2"]. The optimization flag is set by one of
2519  # the "optimize" configs, see rest of this file. The ordering that cflags are
2520  # applied is well-defined by the GN spec, and there is no way to ensure that
2521  # cflags set by "default_stack_frames" is applied after those set by an
2522  # "optimize" config. Similarly, there is no way to propagate state from this
2523  # config into the "optimize" config. We always apply the "/Oy-" config in the
2524  # definition for common_optimize_on_cflags definition, even though this may
2525  # not be correct.
2526}
2527
2528# Default "optimization on" config.
2529#
2530# High-end Android: As of April 2024, `-O2` appears to be a good default,
2531# particularly since a selection of "hot" targets are already using `-O3`.
2532# Enabling `-O3` for all targets does not change performance much (according
2533# to Speedometer), but regresses binary size. Using `-O3` as the default:
2534#   - Decreases Speedometer 2.1 score by 0.2% [0].
2535#   - Increases Speedometer 3.0 score by 0.1% [1].
2536#   - Increases binary size by 1.47MB [2] (or 0.8%: the arm64 native code size
2537#     in M124 is 178MB).
2538# ... over `-O2`.
2539#
2540# [0]: https://pinpoint-dot-chromeperf.appspot.com/job/147634a8be0000
2541# [1]: https://pinpoint-dot-chromeperf.appspot.com/job/132bc772be0000
2542# [2]: https://crrev.com/c/5447532
2543config("optimize") {
2544  if (is_win) {
2545    # clang-cl's /O2 corresponds to clang's -O3, and really want -O2 for
2546    # consistency with the other platforms.
2547    cflags = [
2548               "/O2",
2549               "/clang:-O2",
2550             ] + common_optimize_on_cflags
2551
2552    # The `-O3` for clang turns on extra optimizations compared to the standard
2553    # `-O2`. But for rust, `-Copt-level=3` is the default and is thus reliable
2554    # to use.
2555    rustflags = [ "-Copt-level=3" ]
2556  } else if (optimize_for_size || is_chromeos) {
2557    # Favor size over speed.
2558    # -Os in clang is more of a size-conscious -O2 than "size at any cost"
2559    # (AKA -Oz).
2560
2561    if (is_fuchsia) {
2562      cflags = [ "-Oz" ] + common_optimize_on_cflags
2563    } else {
2564      cflags = [ "-Os" ] + common_optimize_on_cflags
2565    }
2566
2567    if (is_clang && use_ml_inliner && is_a_target_toolchain && !is_chromeos &&
2568        !is_high_end_android) {
2569      cflags += [
2570        "-mllvm",
2571        "-enable-ml-inliner=release",
2572        "-mllvm",
2573        "-ml-inliner-model-selector=arm32-size",
2574      ]
2575    }
2576
2577    # Similar to clang, we optimize with `-Copt-level=s` to keep loop
2578    # vectorization while otherwise optimizing for size.
2579    rustflags = [ "-Copt-level=s" ]
2580  } else {
2581    cflags = [ "-O2" ] + common_optimize_on_cflags
2582
2583    # The `-O3` for clang turns on extra optimizations compared to the standard
2584    # `-O2`. But for rust, `-Copt-level=3` is the default and is thus reliable
2585    # to use.
2586    rustflags = [ "-Copt-level=3" ]
2587  }
2588  ldflags = common_optimize_on_ldflags
2589}
2590
2591# Turn off optimizations.
2592config("no_optimize") {
2593  if (is_win) {
2594    cflags = [
2595      "/Od",  # Disable optimization.
2596      "/Ob0",  # Disable all inlining (on by default).
2597      "/GF",  # Enable string pooling (off by default).
2598    ]
2599
2600    if (target_cpu == "arm64") {
2601      # Disable omitting frame pointers for no_optimize build because stack
2602      # traces on Windows ARM64 rely on it.
2603      cflags += [ "/Oy-" ]
2604    }
2605  } else if (is_android && !android_full_debug) {
2606    # On Android we kind of optimize some things that don't affect debugging
2607    # much even when optimization is disabled to get the binary size down.
2608    if (is_clang) {
2609      cflags = [ "-Oz" ] + common_optimize_on_cflags
2610    } else {
2611      cflags = [ "-Os" ] + common_optimize_on_cflags
2612    }
2613
2614    if (!is_component_build) {
2615      # Required for library partitions. Without this all symbols just end up
2616      # in the base partition.
2617      ldflags = [ "-Wl,--gc-sections" ]
2618    }
2619  } else if (is_fuchsia) {
2620    # On Fuchsia, we optimize for size here to reduce the size of debug build
2621    # packages so they can be run in a KVM. See crbug.com/910243 for details.
2622    cflags = [ "-Og" ]
2623  } else {
2624    cflags = [ "-O0" ]
2625    ldflags = []
2626  }
2627}
2628
2629# Turns up the optimization level. Used to explicitly enable -O2 instead of
2630# -Os for select targets on platforms that use optimize_for_size. No-op
2631# elsewhere.
2632config("optimize_max") {
2633  if (is_nacl && is_nacl_irt) {
2634    # The NaCl IRT is a special case and always wants its own config.
2635    # Various components do:
2636    #   if (!is_debug) {
2637    #     configs -= [ "//build/config/compiler:default_optimization" ]
2638    #     configs += [ "//build/config/compiler:optimize_max" ]
2639    #   }
2640    # So this config has to have the selection logic just like
2641    # "default_optimization", below.
2642    configs = [ "//build/config/nacl:irt_optimize" ]
2643  } else {
2644    ldflags = common_optimize_on_ldflags
2645    if (is_win) {
2646      # Favor speed over size, /O2 must be before the common flags.
2647      # /O2 implies /Ot, /Oi, and /GF.
2648      cflags = [ "/O2" ] + common_optimize_on_cflags
2649    } else if (optimize_for_fuzzing) {
2650      cflags = [ "-O1" ] + common_optimize_on_cflags
2651    } else {
2652      cflags = [ "-O2" ] + common_optimize_on_cflags
2653    }
2654    rustflags = [ "-Copt-level=3" ]
2655  }
2656}
2657
2658# This config can be used to override the default settings for per-component
2659# and whole-program optimization, optimizing the particular target for speed
2660# instead of code size. This config is exactly the same as "optimize_max"
2661# except that we use -O3 instead of -O2 on non-IRT platforms.
2662#
2663# TODO(crbug.com/41259697) - rework how all of these configs are related
2664# so that we don't need this disclaimer.
2665config("optimize_speed") {
2666  if (is_nacl && is_nacl_irt) {
2667    # The NaCl IRT is a special case and always wants its own config.
2668    # Various components do:
2669    #   if (!is_debug) {
2670    #     configs -= [ "//build/config/compiler:default_optimization" ]
2671    #     configs += [ "//build/config/compiler:optimize_max" ]
2672    #   }
2673    # So this config has to have the selection logic just like
2674    # "default_optimization", below.
2675    configs = [ "//build/config/nacl:irt_optimize" ]
2676  } else {
2677    ldflags = common_optimize_on_ldflags
2678    if (is_win) {
2679      # Favor speed over size, /O2 must be before the common flags.
2680      # /O2 implies /Ot, /Oi, and /GF.
2681      cflags = [ "/O2" ] + common_optimize_on_cflags
2682      if (is_clang) {
2683        cflags += [ "/clang:-O3" ]
2684      }
2685    } else if (optimize_for_fuzzing) {
2686      cflags = [ "-O1" ] + common_optimize_on_cflags
2687    } else {
2688      cflags = [ "-O3" ] + common_optimize_on_cflags
2689    }
2690    rustflags = [ "-Copt-level=3" ]
2691  }
2692}
2693
2694config("optimize_fuzzing") {
2695  cflags = [ "-O1" ] + common_optimize_on_cflags
2696  rustflags = [ "-Copt-level=1" ]
2697  ldflags = common_optimize_on_ldflags
2698  visibility = [ ":default_optimization" ]
2699}
2700
2701# The default optimization applied to all targets. This will be equivalent to
2702# either "optimize" or "no_optimize", depending on the build flags.
2703config("default_optimization") {
2704  if (is_nacl && is_nacl_irt) {
2705    # The NaCl IRT is a special case and always wants its own config.
2706    # It gets optimized the same way regardless of the type of build.
2707    configs = [ "//build/config/nacl:irt_optimize" ]
2708  } else if (is_debug) {
2709    configs = [ ":no_optimize" ]
2710  } else if (optimize_for_fuzzing) {
2711    assert(!is_win, "Fuzzing optimize level not supported on Windows")
2712
2713    # Coverage build is quite slow. Using "optimize_for_fuzzing" makes it even
2714    # slower as it uses "-O1" instead of "-O3". Prevent that from happening.
2715    assert(!use_clang_coverage,
2716           "optimize_for_fuzzing=true should not be used with " +
2717               "use_clang_coverage=true.")
2718    configs = [ ":optimize_fuzzing" ]
2719  } else {
2720    configs = [ ":optimize" ]
2721  }
2722}
2723
2724_clang_sample_profile = ""
2725if (is_clang && is_a_target_toolchain) {
2726  if (clang_sample_profile_path != "") {
2727    _clang_sample_profile = clang_sample_profile_path
2728  } else if (clang_use_default_sample_profile) {
2729    assert(build_with_chromium,
2730           "Our default profiles currently only apply to Chromium")
2731    assert(is_android || is_chromeos || is_castos,
2732           "The current platform has no default profile")
2733    if (is_android || is_castos) {
2734      _clang_sample_profile = "//chrome/android/profiles/afdo.prof"
2735    } else {
2736      assert(chromeos_afdo_platform == "atom" ||
2737                 chromeos_afdo_platform == "bigcore" ||
2738                 chromeos_afdo_platform == "arm",
2739             "Only 'atom', 'bigcore', and 'arm' are valid ChromeOS profiles.")
2740      _clang_sample_profile =
2741          "//chromeos/profiles/${chromeos_afdo_platform}.afdo.prof"
2742    }
2743  }
2744}
2745
2746# Clang offers a way to assert that AFDO profiles are accurate, which causes it
2747# to optimize functions not represented in a profile more aggressively for size.
2748# This config can be toggled in cases where shaving off binary size hurts
2749# performance too much.
2750config("afdo_optimize_size") {
2751  if (_clang_sample_profile != "" && sample_profile_is_accurate) {
2752    cflags = [ "-fprofile-sample-accurate" ]
2753  }
2754}
2755
2756# GCC and clang support a form of profile-guided optimization called AFDO.
2757# There are some targeted places that AFDO regresses, so we provide a separate
2758# config to allow AFDO to be disabled per-target.
2759config("afdo") {
2760  if (is_clang) {
2761    cflags = []
2762    if (clang_emit_debug_info_for_profiling) {
2763      # Add the following flags to generate debug info for profiling.
2764      cflags += [ "-gline-tables-only" ]
2765      if (!is_nacl) {
2766        cflags += [ "-fdebug-info-for-profiling" ]
2767      }
2768    }
2769    if (_clang_sample_profile != "") {
2770      assert(chrome_pgo_phase == 0, "AFDO can't be used in PGO builds")
2771      rebased_clang_sample_profile =
2772          rebase_path(_clang_sample_profile, root_build_dir)
2773      cflags += [ "-fprofile-sample-use=${rebased_clang_sample_profile}" ]
2774      if (use_profi) {
2775        cflags += [ "-fsample-profile-use-profi" ]
2776      }
2777
2778      # crbug.com/1459429: ARM builds see failures due to -Wbackend-plugin.
2779      # These seem to be false positives - the complaints are about functions
2780      # marked with `__nodebug__` not having associated debuginfo. In the case
2781      # where this was observed, the `__nodebug__` function was also marked
2782      # `__always_inline__` and had no branches, so AFDO info is likely useless
2783      # there.
2784      cflags += [ "-Wno-backend-plugin" ]
2785      inputs = [ _clang_sample_profile ]
2786    }
2787  } else if (auto_profile_path != "" && is_a_target_toolchain) {
2788    cflags = [ "-fauto-profile=${auto_profile_path}" ]
2789    inputs = [ auto_profile_path ]
2790  }
2791}
2792
2793# Symbols ----------------------------------------------------------------------
2794
2795# The BUILDCONFIG file sets the "default_symbols" config on targets by
2796# default. It will be equivalent to one the three specific symbol levels.
2797#
2798# You can override the symbol level on a per-target basis by removing the
2799# default config and then adding the named one you want:
2800#
2801#   configs -= [ "//build/config/compiler:default_symbols" ]
2802#   configs += [ "//build/config/compiler:symbols" ]
2803
2804# A helper config that all configs passing /DEBUG to the linker should
2805# include as sub-config.
2806config("win_pdbaltpath") {
2807  visibility = [
2808    ":minimal_symbols",
2809    ":symbols",
2810  ]
2811
2812  # /DEBUG causes the linker to generate a pdb file, and to write the absolute
2813  # path to it in the executable file it generates.  This flag turns that
2814  # absolute path into just the basename of the pdb file, which helps with
2815  # build reproducibility. Debuggers look for pdb files next to executables,
2816  # so there's minimal downside to always using this. However, post-mortem
2817  # debugging of Chromium crash dumps and ETW tracing can be complicated by this
2818  # switch so an option to omit it is important.
2819  if (!use_full_pdb_paths) {
2820    ldflags = [ "/pdbaltpath:%_PDB%" ]
2821  }
2822}
2823
2824# Full symbols.
2825config("symbols") {
2826  rustflags = []
2827  configs = []
2828  if (is_win) {
2829    if (is_clang) {
2830      cflags = [
2831        # Debug information in the .obj files.
2832        "/Z7",
2833
2834        # Disable putting the compiler command line into the debug info to
2835        # prevent some types of non-determinism.
2836        "-gno-codeview-command-line",
2837      ]
2838    } else {
2839      cflags = [ "/Zi" ]  # Produce PDB file, no edit and continue.
2840    }
2841
2842    if (is_clang && use_lld && use_ghash) {
2843      cflags += [ "-gcodeview-ghash" ]
2844      ldflags = [ "/DEBUG:GHASH" ]
2845    } else {
2846      ldflags = [ "/DEBUG" ]
2847    }
2848
2849    # All configs using /DEBUG should include this:
2850    configs += [ ":win_pdbaltpath" ]
2851  } else {
2852    cflags = []
2853    if (is_mac && enable_dsyms) {
2854      # If generating dSYMs, specify -fno-standalone-debug. This was
2855      # originally specified for https://crbug.com/479841 because dsymutil
2856      # could not handle a 4GB dSYM file. But dsymutil from Xcodes prior to
2857      # version 7 also produces debug data that is incompatible with Breakpad
2858      # dump_syms, so this is still required (https://crbug.com/622406).
2859      cflags += [ "-fno-standalone-debug" ]
2860    }
2861
2862    # On aix -gdwarf causes linker failures due to thread_local variables.
2863    # On zos -gdwarf causes INSUFFICIENT ABOVE THE LINE STORAGE WAS AVAILABLE.
2864    if (!is_nacl && current_os != "aix" && current_os != "zos") {
2865      if (use_dwarf5) {
2866        cflags += [ "-gdwarf-5" ]
2867        rustflags += [ "-Zdwarf-version=5" ]
2868      } else {
2869        # Recent clang versions default to DWARF5 on Linux, and Android is about
2870        # to switch. TODO: Adopt that in controlled way. For now, keep DWARF4.
2871        # Apple platforms still default to 4 in clang, so they don't need the
2872        # cflags.
2873        if (!is_apple) {
2874          cflags += [ "-gdwarf-4" ]
2875        }
2876
2877        # On Apple, rustc defaults to DWARF2 so it needs to be told how to
2878        # match clang.
2879        rustflags += [ "-Zdwarf-version=4" ]
2880      }
2881    }
2882
2883    # The gcc-based nacl compilers don't support -fdebug-compilation-dir (see
2884    # elsewhere in this file), so they can't have build-dir-independent output.
2885    # Moreover pnacl does not support newer flags such as -fdebug-prefix-map
2886    # Disable symbols for nacl object files to get deterministic,
2887    # build-directory-independent output.
2888    # Keeping -g2 for saigo as it's the only toolchain whose artifacts that are
2889    # part of chromium release (other nacl toolchains are used only for tests).
2890    if ((!is_nacl || is_nacl_saigo) && current_os != "zos") {
2891      cflags += [ "-g2" ]
2892    }
2893
2894    if (!is_nacl && is_clang && !is_tsan && !is_asan) {
2895      # gcc generates dwarf-aranges by default on -g1 and -g2. On clang it has
2896      # to be manually enabled.
2897      #
2898      # It is skipped in tsan and asan because enabling it causes some
2899      # formatting changes in the output which would require fixing bunches
2900      # of expectation regexps.
2901      cflags += [ "-gdwarf-aranges" ]
2902    }
2903
2904    if (is_apple) {
2905      swiftflags = [ "-g" ]
2906    }
2907
2908    if (use_debug_fission) {
2909      cflags += [ "-gsplit-dwarf" ]
2910    }
2911    asmflags = cflags
2912    ldflags = []
2913
2914    # Split debug info with all thinlto builds except nacl and apple.
2915    # thinlto requires -gsplit-dwarf in ldflags.
2916    if (use_debug_fission && use_thin_lto && !is_nacl && !is_apple) {
2917      ldflags += [ "-gsplit-dwarf" ]
2918    }
2919
2920    # TODO(thakis): Figure out if there's a way to make this go for 32-bit,
2921    # currently we get "warning:
2922    # obj/native_client/src/trusted/service_runtime/sel_asm/nacl_switch_32.o:
2923    # DWARF info may be corrupt; offsets in a range list entry are in different
2924    # sections" there.  Maybe just a bug in nacl_switch_32.S.
2925    _enable_gdb_index =
2926        symbol_level == 2 && !is_apple && !is_nacl && current_cpu != "x86" &&
2927        current_os != "zos" && use_lld &&
2928        # Disable on non-fission 32-bit Android because it pushes
2929        # libcomponents_unittests over the 4gb size limit.
2930        !(is_android && !use_debug_fission && current_cpu != "x64" &&
2931          current_cpu != "arm64")
2932    if (_enable_gdb_index) {
2933      if (is_clang) {
2934        # This flag enables the GNU-format pubnames and pubtypes sections,
2935        # which lld needs in order to generate a correct GDB index.
2936        # TODO(pcc): Try to make lld understand non-GNU-format pubnames
2937        # sections (llvm.org/PR34820).
2938        cflags += [ "-ggnu-pubnames" ]
2939      }
2940      ldflags += [ "-Wl,--gdb-index" ]
2941    }
2942  }
2943
2944  # Compress debug on 32-bit ARM to stay under 4GB file size limit.
2945  # https://b/243982712, https://crbug.com/1354616, https://crbug.com/334073642
2946  if (symbol_level == 2 && !use_debug_fission && !is_nacl && !is_win &&
2947      (current_cpu == "arm" || current_cpu == "x86")) {
2948    configs += [ "//build/config:compress_debug_sections" ]
2949  }
2950
2951  if (is_clang && !is_nacl && is_win && !is_component_build) {
2952    # Remove unreferenced methods to reduce type info in symbols.
2953    # See: https://github.com/llvm/llvm-project/pull/87018.
2954    # The downside with this flag is precisely that: Unreferenced methods get
2955    # removed, so that methods only to be used from within a debugger become
2956    # unavailable. Therefore, only do this for Windows, which seems to be the
2957    # only platform that needs this, due to size limitations in PDF files.
2958    # Additionally, this limitation is only likely to be hit in non-component
2959    # builds, so only do it then.
2960    # See crbug.com/338094922
2961    cflags += [ "-gomit-unreferenced-methods" ]
2962  }
2963
2964  if (is_clang && (!is_nacl || is_nacl_saigo)) {
2965    if (is_apple) {
2966      # TODO(crbug.com/40117949): Investigate missing debug info on mac.
2967      # Make sure we don't use constructor homing on mac.
2968      cflags += [
2969        "-Xclang",
2970        "-debug-info-kind=limited",
2971      ]
2972    } else {
2973      # Use constructor homing for debug info. This option reduces debug info
2974      # by emitting class type info only when constructors are emitted.
2975      cflags += [
2976        "-Xclang",
2977        "-fuse-ctor-homing",
2978      ]
2979    }
2980  }
2981  rustflags += [ "-g" ]
2982}
2983
2984# Minimal symbols.
2985# This config guarantees to hold symbol for stack trace which are shown to user
2986# when crash happens in unittests running on buildbot.
2987config("minimal_symbols") {
2988  rustflags = []
2989  if (is_win) {
2990    # Functions, files, and line tables only.
2991    cflags = []
2992
2993    if (is_clang) {
2994      cflags += [
2995        # Disable putting the compiler command line into the debug info to
2996        # prevent some types of non-determinism.
2997        "-gno-codeview-command-line",
2998      ]
2999    }
3000    if (is_clang && use_lld && use_ghash) {
3001      cflags += [ "-gcodeview-ghash" ]
3002      ldflags = [ "/DEBUG:GHASH" ]
3003    } else {
3004      ldflags = [ "/DEBUG" ]
3005    }
3006
3007    # All configs using /DEBUG should include this:
3008    configs = [ ":win_pdbaltpath" ]
3009
3010    # Enable line tables for clang. MSVC doesn't have an equivalent option.
3011    if (is_clang) {
3012      # -gline-tables-only is the same as -g1, but clang-cl only exposes the
3013      # former.
3014      cflags += [ "-gline-tables-only" ]
3015    }
3016  } else {
3017    cflags = []
3018    if (is_mac && !use_dwarf5) {
3019      # clang defaults to DWARF2 on macOS unless mac_deployment_target is
3020      # at least 10.11.
3021      # TODO(thakis): Remove this once mac_deployment_target is 10.11.
3022      cflags += [ "-gdwarf-4" ]
3023      rustflags += [ "-Zdwarf-version=4" ]
3024    } else if (!use_dwarf5 && !is_nacl && current_os != "aix") {
3025      # On aix -gdwarf causes linker failures due to thread_local variables.
3026      # Recent clang versions default to DWARF5 on Linux, and Android is about
3027      # to switch. TODO: Adopt that in controlled way.
3028      cflags += [ "-gdwarf-4" ]
3029      rustflags += [ "-Zdwarf-version=4" ]
3030    }
3031
3032    if (use_dwarf5 && !is_nacl) {
3033      cflags += [ "-gdwarf-5" ]
3034      rustflags += [ "-Zdwarf-version=5" ]
3035    }
3036
3037    # The gcc-based nacl compilers don't support -fdebug-compilation-dir (see
3038    # elsewhere in this file), so they can't have build-dir-independent output.
3039    # Moreover pnacl does not support newer flags such as -fdebug-prefix-map
3040    # Disable symbols for nacl object files to get deterministic,
3041    # build-directory-independent output.
3042    # Keeping -g1 for saigo as it's the only toolchain whose artifacts that are
3043    # part of chromium release (other nacl toolchains are used only for tests).
3044    if (!is_nacl || is_nacl_saigo) {
3045      cflags += [ "-g1" ]
3046    }
3047
3048    if (!is_nacl && is_clang && !is_tsan && !is_asan && current_os != "zos") {
3049      # See comment for -gdwarf-aranges in config("symbols").
3050      cflags += [ "-gdwarf-aranges" ]
3051    }
3052
3053    ldflags = []
3054    if (is_android && is_clang) {
3055      # Android defaults to symbol_level=1 builds, but clang, unlike gcc,
3056      # doesn't emit DW_AT_linkage_name in -g1 builds.
3057      # -fdebug-info-for-profiling enables that (and a bunch of other things we
3058      # don't need), so that we get qualified names in stacks.
3059      # TODO(thakis): Consider making clang emit DW_AT_linkage_name in -g1 mode;
3060      #               failing that consider doing this on non-Android too.
3061      cflags += [ "-fdebug-info-for-profiling" ]
3062    }
3063
3064    asmflags = cflags
3065  }
3066  rustflags += [ "-Cdebuginfo=1" ]
3067}
3068
3069# This configuration contains function names only. That is, the compiler is
3070# told to not generate debug information and the linker then just puts function
3071# names in the final debug information.
3072config("no_symbols") {
3073  if (is_win) {
3074    ldflags = [ "/DEBUG" ]
3075
3076    # All configs using /DEBUG should include this:
3077    configs = [ ":win_pdbaltpath" ]
3078  } else {
3079    cflags = [ "-g0" ]
3080    asmflags = cflags
3081  }
3082}
3083
3084# Default symbols.
3085config("default_symbols") {
3086  if (symbol_level == 0) {
3087    configs = [ ":no_symbols" ]
3088  } else if (symbol_level == 1) {
3089    configs = [ ":minimal_symbols" ]
3090  } else if (symbol_level == 2) {
3091    configs = [ ":symbols" ]
3092  } else {
3093    assert(false)
3094  }
3095
3096  # This config is removed by base unittests apk.
3097  if (is_android && is_clang && strip_debug_info) {
3098    configs += [ ":strip_debug" ]
3099  }
3100}
3101
3102config("strip_debug") {
3103  if (!defined(ldflags)) {
3104    ldflags = []
3105  }
3106  ldflags += [ "-Wl,--strip-debug" ]
3107}
3108
3109if (is_apple) {
3110  # On macOS and iOS, this enables support for ARC (automatic reference
3111  # counting). See http://clang.llvm.org/docs/AutomaticReferenceCounting.html.
3112  #
3113  # -fobjc-arc enables ARC overall.
3114  #
3115  # ARC does not add exception handlers to pure Objective-C code, but does add
3116  # them to Objective-C++ code with the rationale that C++ pervasively adds them
3117  # in for exception safety. However, exceptions are banned in Chromium code for
3118  # C++ and exceptions in Objective-C code are intended to be fatal, so
3119  # -fno-objc-arc-exceptions is specified to disable these unwanted exception
3120  # handlers.
3121  config("enable_arc") {
3122    common_flags = [
3123      "-fobjc-arc",
3124      "-fno-objc-arc-exceptions",
3125    ]
3126    cflags_objc = common_flags
3127    cflags_objcc = common_flags
3128  }
3129}
3130
3131if (is_android) {
3132  # Use orderfile for linking Chrome on Android.
3133  # This config enables using an orderfile for linking in LLD.
3134  config("chrome_orderfile_config") {
3135    # Don't try to use an orderfile with call graph sorting, except on Android,
3136    # where we care about memory used by code, so we still want to mandate
3137    # ordering.
3138    if (chrome_orderfile_path != "") {
3139      assert(use_lld)
3140      _rebased_orderfile = rebase_path(chrome_orderfile_path, root_build_dir)
3141      ldflags = [
3142        "-Wl,--symbol-ordering-file",
3143        "-Wl,$_rebased_orderfile",
3144        "-Wl,--no-warn-symbol-ordering",
3145      ]
3146      inputs = [ chrome_orderfile_path ]
3147    }
3148  }
3149}
3150
3151# Initialize all variables on the stack if needed.
3152config("default_init_stack_vars") {
3153  cflags = []
3154  if (init_stack_vars && is_clang && !is_nacl && !using_sanitizer) {
3155    if (init_stack_vars_zero) {
3156      cflags += [ "-ftrivial-auto-var-init=zero" ]
3157    } else {
3158      cflags += [ "-ftrivial-auto-var-init=pattern" ]
3159    }
3160  }
3161}
3162
3163buildflag_header("compiler_buildflags") {
3164  header = "compiler_buildflags.h"
3165
3166  flags = [
3167    "CLANG_PGO=$chrome_pgo_phase",
3168    "SYMBOL_LEVEL=$symbol_level",
3169  ]
3170}
3171
3172config("cet_shadow_stack") {
3173  if (enable_cet_shadow_stack && is_win) {
3174    assert(target_cpu == "x64")
3175    ldflags = [ "/CETCOMPAT" ]
3176  }
3177}
3178