1 import("//llvm/utils/gn/build/buildflags.gni")
2 import("//llvm/utils/gn/build/mac_sdk.gni")
3 import("//llvm/utils/gn/build/sysroot.gni")
4 import("//llvm/utils/gn/build/toolchain/compiler.gni")
5 import("//llvm/utils/gn/build/toolchain/target_flags.gni")
8 # Whether to build everything with test coverage information.
9 # After building with this, run tests and then run
10 # llvm/utils/prepare-code-coverage-artifact.py \
11 # --compilation-dir=out/gn \
12 # .../llvm-profdata .../llvm-cov out/gn/profiles/ report/ \
13 # out/gn/bin/llvm-undname ...
14 # to generate a HTML report for the binaries passed in the last line.
15 llvm_build_instrumented_coverage = false
17 # Whether to build everything with instrumentation for PGO
18 # After building with this:
19 # 1. Remove old profile data with `rm *.profraw`
20 # 2. Run the built instrumented binaries.
21 # This will produce *.profraw files in the current working directory.
22 # 3. Run `llvm-profdata merge *.profraw -o llvm.profdata` to merge them.
23 # 4. Then build again, with this set to false, and with
24 # `llvm_pgo_use = "//llvm.profdata"` set to use the created profile.
25 llvm_pgo_instrument = false
27 # If non-empty, path to merged profiling data used for optimization
28 # See documentation for llvm_pgo_instrument for how to create profile data.
31 # If set, puts relative paths in debug info.
32 # Makes the build output independent of the build directory, but makes
33 # most debuggers harder to use. See "Getting to local determinism" and
34 # "Getting debuggers to work well with locally deterministic builds" in
35 # http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html
36 # for more information.
37 use_relative_paths_in_debug_info = false
39 # The version of host gcc. Ignored if is_clang is true.
43 assert(!llvm_build_instrumented_coverage || is_clang,
44 "llvm_build_instrumented_coverage requires clang as host compiler")
45 assert(!llvm_pgo_instrument || is_clang,
46 "llvm_pgo_instrument requires clang as host compiler")
47 assert(llvm_pgo_use == "" || is_clang,
48 "llvm_pgo_use requires clang as host compiler")
49 assert(!llvm_pgo_instrument || llvm_pgo_use == "",
50 "set at most one of llvm_pgo_instrument and llvm_pgo_use")
52 config("compiler_defaults") {
55 if (!llvm_enable_assertions) {
56 defines += [ "NDEBUG" ]
59 if (llvm_enable_expensive_checks) {
60 defines += [ "EXPENSIVE_CHECKS" ]
63 asmflags = target_flags
64 cflags = target_flags + target_cflags
66 ldflags = target_flags + target_ldflags
68 # Mostly for compiler-rt, see compiler-rt/cmake/config-ix.cmake
69 if (current_os == "ios") {
70 asmflags += [ "-miphoneos-version-min=8.0" ]
71 cflags += [ "-miphoneos-version-min=8.0" ]
72 ldflags += [ "-miphoneos-version-min=8.0" ]
74 if (current_os == "mac") {
75 asmflags += [ "-mmacos-version-min=$mac_deployment_target" ]
76 cflags += [ "-mmacos-version-min=$mac_deployment_target" ]
77 ldflags += [ "-mmacos-version-min=$mac_deployment_target" ]
80 assert(symbol_level == 0 || symbol_level == 1 || symbol_level == 2,
81 "Unexpected symbol_level")
82 if (current_os != "win") {
83 if (symbol_level == 2) {
86 # For full debug-info -g builds, --gdb-index makes links ~15% slower, and
87 # gdb symbol reading time 1500% faster (lld links in 4.4 instead of 3.9s,
88 # and gdb loads and runs it in 2s instead of in 30s). It's likely that
89 # people doing symbol_level=2 want to run a debugger (since
90 # symbol_level=2 isn't the default). So this seems like the right
92 if (current_os != "mac" && use_lld) {
93 cflags += [ "-ggnu-pubnames" ] # PR34820
94 ldflags += [ "-Wl,--gdb-index" ]
96 # Use debug fission. In this mode, detailed debug information is
97 # written to a .dwo file next to each .o file instead of into the .o
98 # file directly. The linker then only links the .o files, which contain
99 # a pointer to each .dwo file. The debugger then reads debug info out
100 # of all the .dwo files instead of from the binary.
102 # (The dwp tool can link all the debug info together into a single
103 # "debug info binary", but that's not done as part of the build.)
105 # This requires `-Wl,--gdb-index` (above) to work well.
107 # With lld, this reduces link time:
108 # - in release + symbol_level=2 builds: From 2.3s to 1.3s
109 # - in debug builds: From 5.2s to 4.6s
111 # Time needed for gdb startup and setting a breakpoint is comparable,
112 # the time from from `r` to hititng a breakpoint on main goes from 4s
115 # (macOS's linker always keeps debug info out of its output executables
116 # and debuggers there also know to load debug info from the .o files.
117 # macOS also has a debug info linker like dwp, it's called dsymutil.
118 # This happens by default, so there's no need to pass a flag there.)
119 cflags += [ "-gsplit-dwarf" ]
120 ldflags += [ "-gsplit-dwarf" ] # Needed for ThinLTO builds.
122 } else if (symbol_level == 1) {
124 # For linetable-only -g1 builds, --gdb-index makes links ~8% slower, but
125 # links are 4x faster than -g builds so it's a fairly small absolute cost.
126 # On the other hand, gdb startup is well below 1s with and without the
127 # index, and people using -g1 likely don't use a debugger. So don't use
129 # Linetables always go in the .o file, even with -gsplit-dwarf, so there's
130 # no point in passing -gsplit-dwarf here.
135 cflags += [ "-fdiagnostics-color" ]
137 ldflags += [ "-Wl,--color-diagnostics" ]
141 "-fvisibility-inlines-hidden",
144 if (symbol_level != 0) {
149 if (symbol_level == 1 && is_clang) {
150 cflags += [ "-gline-tables-only" ]
152 ldflags += [ "/DEBUG" ]
154 # Speed up links with ghash on windows.
155 if (use_lld && is_clang) {
156 cflags += [ "-gcodeview-ghash" ]
157 ldflags += [ "/DEBUG:GHASH" ]
172 "_CRT_SECURE_NO_DEPRECATE",
173 "_CRT_SECURE_NO_WARNINGS",
174 "_CRT_NONSTDC_NO_DEPRECATE",
175 "_CRT_NONSTDC_NO_WARNINGS",
176 "_SCL_SECURE_NO_DEPRECATE",
177 "_SCL_SECURE_NO_WARNINGS",
183 cflags += [ "/EHs-c-" ]
184 cflags_cc += [ "/std:c++17" ]
187 # expand __VA_ARGS__ in "OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__)"
188 cflags += [ "/Zc:preprocessor" ]
190 # cl.exe doesn't set __cplusplus correctly by default.
191 # clang-cl gets it right by default, so don't needlessly add the flag there.
192 cflags_cc += [ "/Zc:__cplusplus" ]
195 # The MSVC default value (1 MB) is not enough for parsing recursive C++
196 # templates in Clang.
197 ldflags += [ "/STACK:10000000" ]
201 if (current_os == "win" && !is_clang) {
203 # Suppress ''modifier' : used more than once' (__forceinline and inline).
206 # Suppress 'conversion from 'type1' to 'type2', possible loss of data'.
209 # Suppress 'conversion from 'size_t' to 'type', possible loss of data'.
212 # Suppress 'no matching operator delete found'.
215 # Suppress 'noexcept used with no exception handling mode specified'.
218 # Suppress 'destructor was implicitly defined as deleted'.
221 # Suppress 'unsafe mix of type <type> and type <type> in operation'.
225 if (current_os == "win") {
233 cflags += [ "-Wno-unused-parameter" ]
236 "-Wdelete-non-virtual-dtor",
237 "-Wstring-conversion",
241 # GCC's -Wcomment complains about // comments ending with '\' if the
242 # next line is also a // comment.
245 # Disable gcc's potentially uninitialized use analysis as it presents
246 # lots of false positives.
247 "-Wno-maybe-uninitialized",
250 # The LLVM libraries have no stable C++ API, so -Wnoexcept-type is not
252 "-Wno-noexcept-type",
254 if (gcc_version >= 8) {
256 # Disable -Wclass-memaccess, a C++-only warning from GCC 8 that fires
257 # on LLVM's ADT classes.
258 "-Wno-class-memaccess",
261 if (gcc_version >= 9) {
263 # Disable -Wredundant-move on GCC>=9. GCC wants to remove std::move
264 # in code like "A foo(ConvertibleToA a) { return std::move(a); }",
265 # but this code does not compile (or uses the copy constructor
266 # instead) on clang<=3.8. Clang also has a -Wredundant-move, but it
267 # only fires when the types match exactly, so we can keep it here.
268 "-Wno-redundant-move",
274 # On Windows, the linker is not invoked through the compiler driver.
275 if (use_lld && current_os != "win") {
276 ldflags += [ "-fuse-ld=lld" ]
279 if (llvm_build_instrumented_coverage) {
281 "-fcoverage-mapping",
283 # For build determinism. Using this requires passing --compilation-dir to
284 # llvm/utils/prepare-code-coverage-artifact.py.
285 "-fcoverage-compilation-dir=.",
287 # Using an absolute path here is lame, but it's used at test execution
288 # time to generate the profiles, and lit doesn't specify a fixed folder
289 # for test execution -- so this is the only way to get all profiles into
290 # a single folder like llvm/utils/prepare-code-coverage-artifact.py
292 "-fprofile-instr-generate=" +
293 rebase_path("$root_build_dir/profiles/%4m.profraw"),
295 if (current_os != "win") {
296 ldflags += [ "-fprofile-instr-generate" ]
299 if (llvm_pgo_instrument) {
300 cflags += [ "-fprofile-generate" ]
301 if (current_os != "win") {
302 ldflags += [ "-fprofile-generate" ]
305 if (llvm_pgo_use != "") {
307 "-fprofile-use=" + rebase_path(llvm_pgo_use, root_build_dir),
309 # There are always quite a few diags like
310 # warning: foo.cpp: Function control flow change detected
311 # (hash mismatch) [-Wbackend-plugin]
312 # in a PGO build. Since they're not unexpected, silence them.
313 "-Wno-backend-plugin",
317 # Deterministic build setup, see
318 # http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html
319 if (current_os == "win") {
320 ldflags += [ "/pdbaltpath:%_PDB%" ]
324 "-no-canonical-prefixes",
327 if (current_os == "win") {
328 cflags += [ "-fmsc-version=1926" ]
330 cflags += [ "/Brepro" ]
331 ldflags += [ "/Brepro" ]
334 if (use_relative_paths_in_debug_info) {
335 cflags += [ "-fdebug-compilation-dir=." ]
339 if (current_os == "win") {
340 assert(is_clang, "sysroot only works with clang-cl as host compiler")
341 cflags += [ "/winsysroot" + rebase_path(sysroot, root_build_dir) ]
343 ldflags += [ "/winsysroot:" + rebase_path(sysroot, root_build_dir) ]
345 # FIXME: Remove once PR54409 is fixed.
346 if (current_cpu == "x64") {
347 ldflags += [ "/machine:x64" ]
348 } else if (current_cpu == "x86") {
349 ldflags += [ "/machine:x86" ]
352 } else if (current_os != "ios" && current_os != "mac" &&
353 current_os != "android") {
354 cflags += [ "--sysroot=" + rebase_path(sysroot, root_build_dir) ]
357 if ((current_os == "ios" || current_os == "mac") &&
358 (clang_base_path != "" || sysroot != "")) {
359 if (current_os == "ios" && current_cpu == "arm64") {
360 sdk_path = ios_sdk_path
361 } else if (current_os == "ios" && current_cpu == "x64") {
362 sdk_path = iossim_sdk_path
363 } else if (current_os == "mac") {
364 sdk_path = mac_sdk_path
368 rebase_path(sdk_path, root_build_dir),
372 rebase_path(sdk_path, root_build_dir),
375 if (sysroot != "" && current_os != "win" && is_clang) {
376 cflags += [ "-Wpoison-system-directories" ]
380 assert(is_clang && (current_os == "ios" || current_os == "linux" ||
381 current_os == "mac"),
382 "ubsan only supported on iOS/Clang, Linux/Clang, or macOS/Clang")
384 "-fsanitize=undefined",
385 "-fno-sanitize=vptr,function",
386 "-fno-sanitize-recover=all",
388 ldflags += [ "-fsanitize=undefined" ]
392 assert(is_clang && (current_os == "ios" || current_os == "linux" ||
393 current_os == "mac"),
394 "asan only supported on iOS/Clang, Linux/Clang, or macOS/Clang")
395 cflags += [ "-fsanitize=address" ]
396 ldflags += [ "-fsanitize=address" ]
400 assert(is_clang && current_os == "linux",
401 "tsan only supported on Linux/Clang")
402 cflags += [ "-fsanitize=thread" ]
403 ldflags += [ "-fsanitize=thread" ]
407 assert(is_clang, "ThinLTO only supported on Clang")
411 cflags += [ "-flto=thin" ]
413 if (current_os == "win") {
415 "/opt:lldlto=" + lto_opt_level,
416 "/opt:lldltojobs=" + max_jobs_per_lto_link,
421 "-Wl,--thinlto-jobs=" + max_jobs_per_lto_link,
422 "-Wl,--lto-O" + lto_opt_level,
427 cflags_objcc = cflags_cc
430 config("no_exceptions") {
432 if (current_os != "win") {
433 cflags_cc += [ "-fno-exceptions" ]
435 cflags_objcc = cflags_cc
439 if (current_os == "win") {
440 cflags_cc = [ "/GR-" ]
442 cflags_cc = [ "-fno-rtti" ]
444 cflags_objcc = cflags_cc
448 # -Wl,-z,defs doesn't work with sanitizers.
449 # https://clang.llvm.org/docs/AddressSanitizer.html
450 if (current_os != "ios" && current_os != "mac" && current_os != "win" &&
451 !(use_asan || use_tsan || use_ubsan)) {
452 ldflags = [ "-Wl,-z,defs" ]
456 # To make an archive that can be distributed, you need to remove this config and
457 # set complete_static_lib.
458 config("thin_archive") {
459 if (current_os != "ios" && current_os != "mac" && current_os != "win") {
464 config("llvm_code") {
467 "$root_gen_dir/llvm/include",
469 if (current_os != "win") {
477 "$root_gen_dir/lld/include",
481 config("clang_code") {
482 if (current_os != "win") {
483 cflags = [ "-fno-strict-aliasing" ]
487 "$root_gen_dir/clang/include",
491 config("bolt_code") {
494 "$root_gen_dir/bolt/include",
499 include_dirs = [ "//compiler-rt/lib" ]
502 "-gline-tables-only",
504 if (current_os != "win") {
508 "-fvisibility=hidden",
512 # Disable thread safe initialization for static locals. ASan shouldn't need it.
513 # Thread safe initialization assumes that the CRT has already been initialized, but ASan initializes before the CRT.
514 "/Zc:threadSafeInit-",
519 "-Werror=thread-safety",
520 "-Werror=thread-safety-reference",
521 "-Werror=thread-safety-beta",
526 config("lldb_code") {
527 if (current_os != "win") {
528 cflags = [ "-fno-strict-aliasing" ]
532 "$root_gen_dir/lldb/include",
536 config("warn_covered_switch_default") {
538 cflags = [ "-Wcovered-switch-default" ]