542 lines · plain
1import("//llvm/utils/gn/build/buildflags.gni")2import("//llvm/utils/gn/build/mac_sdk.gni")3import("//llvm/utils/gn/build/sysroot.gni")4import("//llvm/utils/gn/build/toolchain/compiler.gni")5import("//llvm/utils/gn/build/toolchain/target_flags.gni")6 7declare_args() {8 # Whether to build everything with test coverage information.9 # After building with this, run tests and then run10 # 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 = false16 17 # Whether to build everything with instrumentation for PGO18 # 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 with24 # `llvm_pgo_use = "//llvm.profdata"` set to use the created profile.25 llvm_pgo_instrument = false26 27 # If non-empty, path to merged profiling data used for optimization28 # See documentation for llvm_pgo_instrument for how to create profile data.29 llvm_pgo_use = ""30 31 # If set, puts relative paths in debug info.32 # Makes the build output independent of the build directory, but makes33 # most debuggers harder to use. See "Getting to local determinism" and34 # "Getting debuggers to work well with locally deterministic builds" in35 # http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html36 # for more information.37 use_relative_paths_in_debug_info = false38 39 # The version of host gcc. Ignored if is_clang is true.40 gcc_version = 941}42 43assert(!llvm_build_instrumented_coverage || is_clang,44 "llvm_build_instrumented_coverage requires clang as host compiler")45assert(!llvm_pgo_instrument || is_clang,46 "llvm_pgo_instrument requires clang as host compiler")47assert(llvm_pgo_use == "" || is_clang,48 "llvm_pgo_use requires clang as host compiler")49assert(!llvm_pgo_instrument || llvm_pgo_use == "",50 "set at most one of llvm_pgo_instrument and llvm_pgo_use")51 52config("compiler_defaults") {53 defines = []54 55 if (!llvm_enable_assertions) {56 defines += [ "NDEBUG" ]57 }58 59 if (llvm_enable_expensive_checks) {60 defines += [ "EXPENSIVE_CHECKS" ]61 }62 63 asmflags = target_flags64 cflags = target_flags + target_cflags65 cflags_cc = []66 ldflags = target_flags + target_ldflags67 68 # Mostly for compiler-rt, see compiler-rt/cmake/config-ix.cmake69 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" ]73 }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" ]78 }79 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) {84 cflags += [ "-g" ]85 86 # For full debug-info -g builds, --gdb-index makes links ~15% slower, and87 # 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 that89 # people doing symbol_level=2 want to run a debugger (since90 # symbol_level=2 isn't the default). So this seems like the right91 # tradeoff.92 if (current_os != "mac" && use_lld) {93 cflags += [ "-ggnu-pubnames" ] # PR3482094 ldflags += [ "-Wl,--gdb-index" ]95 96 # Use debug fission. In this mode, detailed debug information is97 # written to a .dwo file next to each .o file instead of into the .o98 # file directly. The linker then only links the .o files, which contain99 # a pointer to each .dwo file. The debugger then reads debug info out100 # of all the .dwo files instead of from the binary.101 #102 # (The dwp tool can link all the debug info together into a single103 # "debug info binary", but that's not done as part of the build.)104 #105 # This requires `-Wl,--gdb-index` (above) to work well.106 #107 # With lld, this reduces link time:108 # - in release + symbol_level=2 builds: From 2.3s to 1.3s109 # - in debug builds: From 5.2s to 4.6s110 #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 4s113 # to 2s.114 #115 # (macOS's linker always keeps debug info out of its output executables116 # 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.121 }122 } else if (symbol_level == 1) {123 cflags += [ "-g1" ]124 # For linetable-only -g1 builds, --gdb-index makes links ~8% slower, but125 # 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 the127 # index, and people using -g1 likely don't use a debugger. So don't use128 # the flag here.129 # Linetables always go in the .o file, even with -gsplit-dwarf, so there's130 # no point in passing -gsplit-dwarf here.131 }132 if (is_optimized) {133 cflags += [ "-O3" ]134 }135 cflags += [ "-fdiagnostics-color" ]136 if (use_lld) {137 ldflags += [ "-Wl,--color-diagnostics" ]138 }139 cflags_cc += [140 "-std=c++17",141 "-fvisibility-inlines-hidden",142 ]143 } else {144 if (symbol_level != 0) {145 cflags += [146 "/Zi",147 "/FS",148 ]149 if (symbol_level == 1 && is_clang) {150 cflags += [ "-gline-tables-only" ]151 }152 ldflags += [ "/DEBUG" ]153 154 # Speed up links with ghash on windows.155 if (use_lld && is_clang) {156 cflags += [ "-gcodeview-ghash" ]157 ldflags += [ "/DEBUG:GHASH" ]158 }159 }160 if (is_optimized) {161 cflags += [162 "/O2",163 "/Gw",164 "/Zc:inline",165 ]166 ldflags += [167 "/OPT:REF",168 "/OPT:ICF",169 ]170 }171 defines += [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",178 179 "_HAS_EXCEPTIONS=0",180 "_UNICODE",181 "UNICODE",182 "CLANG_BUILD_STATIC",183 ]184 cflags += [ "/EHs-c-" ]185 cflags_cc += [ "/std:c++17" ]186 187 if (!is_clang) {188 # expand __VA_ARGS__ in "OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__)"189 cflags += [ "/Zc:preprocessor" ]190 191 # cl.exe doesn't set __cplusplus correctly by default.192 # clang-cl gets it right by default, so don't needlessly add the flag there.193 cflags_cc += [ "/Zc:__cplusplus" ]194 }195 196 # The MSVC default value (1 MB) is not enough for parsing recursive C++197 # templates in Clang.198 ldflags += [ "/STACK:10000000" ]199 }200 201 # Warning setup.202 if (current_os == "win" && !is_clang) {203 cflags += [204 # Suppress ''modifier' : used more than once' (__forceinline and inline).205 "-wd4141",206 207 # Suppress 'conversion from 'type1' to 'type2', possible loss of data'.208 "-wd4244",209 210 # Suppress 'conversion from 'size_t' to 'type', possible loss of data'.211 "-wd4267",212 213 # Suppress 'no matching operator delete found'.214 "-wd4291",215 216 # Suppress 'noexcept used with no exception handling mode specified'.217 "-wd4577",218 219 # Suppress 'destructor was implicitly defined as deleted'.220 "-wd4624",221 222 # Suppress 'unsafe mix of type <type> and type <type> in operation'.223 "-wd4805",224 ]225 } else {226 if (current_os == "win") {227 cflags += [ "/W4" ]228 } else {229 cflags += [230 "-Wall",231 "-Wextra",232 ]233 }234 cflags += [ "-Wno-unused-parameter" ]235 if (is_clang) {236 cflags += [237 "-Wdelete-non-virtual-dtor",238 "-Wstring-conversion",239 ]240 } else {241 cflags += [242 # GCC's -Wcomment complains about // comments ending with '\' if the243 # next line is also a // comment.244 "-Wno-comment",245 246 # Disable gcc's potentially uninitialized use analysis as it presents247 # lots of false positives.248 "-Wno-maybe-uninitialized",249 ]250 cflags_cc += [251 # The LLVM libraries have no stable C++ API, so -Wnoexcept-type is not252 # useful.253 "-Wno-noexcept-type",254 ]255 if (gcc_version >= 8) {256 cflags_cc += [257 # Disable -Wclass-memaccess, a C++-only warning from GCC 8 that fires258 # on LLVM's ADT classes.259 "-Wno-class-memaccess",260 ]261 }262 if (gcc_version >= 9) {263 cflags_cc += [264 # Disable -Wredundant-move on GCC>=9. GCC wants to remove std::move265 # in code like "A foo(ConvertibleToA a) { return std::move(a); }",266 # but this code does not compile (or uses the copy constructor267 # instead) on clang<=3.8. Clang also has a -Wredundant-move, but it268 # only fires when the types match exactly, so we can keep it here.269 "-Wno-redundant-move",270 ]271 }272 }273 }274 275 # On Windows, the linker is not invoked through the compiler driver.276 if (use_lld && current_os != "win") {277 ldflags += [ "-fuse-ld=lld" ]278 }279 280 if (llvm_build_instrumented_coverage) {281 cflags += [282 "-fcoverage-mapping",283 284 # For build determinism. Using this requires passing --compilation-dir to285 # llvm/utils/prepare-code-coverage-artifact.py.286 "-fcoverage-compilation-dir=.",287 288 # Using an absolute path here is lame, but it's used at test execution289 # time to generate the profiles, and lit doesn't specify a fixed folder290 # for test execution -- so this is the only way to get all profiles into291 # a single folder like llvm/utils/prepare-code-coverage-artifact.py292 # expects.293 "-fprofile-instr-generate=" +294 rebase_path("$root_build_dir/profiles/%4m.profraw"),295 ]296 if (current_os != "win") {297 ldflags += [ "-fprofile-instr-generate" ]298 }299 }300 if (llvm_pgo_instrument) {301 cflags += [ "-fprofile-generate" ]302 if (current_os != "win") {303 ldflags += [ "-fprofile-generate" ]304 }305 }306 if (llvm_pgo_use != "") {307 cflags += [308 "-fprofile-use=" + rebase_path(llvm_pgo_use, root_build_dir),309 310 # There are always quite a few diags like311 # warning: foo.cpp: Function control flow change detected312 # (hash mismatch) [-Wbackend-plugin]313 # in a PGO build. Since they're not unexpected, silence them.314 "-Wno-backend-plugin",315 ]316 }317 318 # Deterministic build setup, see319 # http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html320 if (current_os == "win") {321 ldflags += [ "/pdbaltpath:%_PDB%" ]322 }323 if (is_clang) {324 cflags += [325 "-no-canonical-prefixes",326 "-Werror=date-time",327 ]328 if (current_os == "win") {329 cflags += [ "-fmsc-version=1926" ]330 if (use_lld) {331 cflags += [ "/Brepro" ]332 ldflags += [ "/Brepro" ]333 }334 }335 if (use_relative_paths_in_debug_info) {336 cflags += [ "-fdebug-compilation-dir=." ]337 }338 }339 if (sysroot != "") {340 if (current_os == "win") {341 assert(is_clang, "sysroot only works with clang-cl as host compiler")342 cflags += [ "/winsysroot" + rebase_path(sysroot, root_build_dir) ]343 if (use_lld) {344 ldflags += [ "/winsysroot:" + rebase_path(sysroot, root_build_dir) ]345 346 # FIXME: Remove once PR54409 is fixed.347 if (current_cpu == "x64") {348 ldflags += [ "/machine:x64" ]349 } else if (current_cpu == "x86") {350 ldflags += [ "/machine:x86" ]351 }352 }353 } else if (current_os != "ios" && current_os != "mac" &&354 current_os != "android") {355 cflags += [ "--sysroot=" + rebase_path(sysroot, root_build_dir) ]356 }357 }358 if ((current_os == "ios" || current_os == "mac") &&359 (clang_base_path != "" || sysroot != "")) {360 if (current_os == "ios" && current_cpu == "arm64") {361 sdk_path = ios_sdk_path362 } else if (current_os == "ios" && current_cpu == "x64") {363 sdk_path = iossim_sdk_path364 } else if (current_os == "mac") {365 sdk_path = mac_sdk_path366 }367 cflags += [368 "-isysroot",369 rebase_path(sdk_path, root_build_dir),370 ]371 ldflags += [372 "-isysroot",373 rebase_path(sdk_path, root_build_dir),374 ]375 }376 if (sysroot != "" && current_os != "win" && is_clang) {377 cflags += [ "-Wpoison-system-directories" ]378 }379 380 if (use_ubsan) {381 assert(is_clang && (current_os == "ios" || current_os == "linux" ||382 current_os == "mac"),383 "ubsan only supported on iOS/Clang, Linux/Clang, or macOS/Clang")384 cflags += [385 "-fsanitize=undefined",386 "-fno-sanitize=vptr,function",387 "-fno-sanitize-recover=all",388 ]389 ldflags += [ "-fsanitize=undefined" ]390 }391 392 if (use_asan) {393 assert(is_clang && (current_os == "ios" || current_os == "linux" ||394 current_os == "mac"),395 "asan only supported on iOS/Clang, Linux/Clang, or macOS/Clang")396 cflags += [ "-fsanitize=address" ]397 ldflags += [ "-fsanitize=address" ]398 }399 400 if (use_tsan) {401 assert(is_clang && current_os == "linux",402 "tsan only supported on Linux/Clang")403 cflags += [ "-fsanitize=thread" ]404 ldflags += [ "-fsanitize=thread" ]405 }406 407 if (use_thinlto) {408 assert(is_clang, "ThinLTO only supported on Clang")409 410 lto_opt_level = 2411 412 cflags += [ "-flto=thin" ]413 414 if (current_os == "win") {415 ldflags += [416 "/opt:lldlto=" + lto_opt_level,417 "/opt:lldltojobs=" + max_jobs_per_lto_link,418 ]419 } else {420 ldflags += [421 "-flto=thin",422 "-Wl,--thinlto-jobs=" + max_jobs_per_lto_link,423 "-Wl,--lto-O" + lto_opt_level,424 ]425 }426 }427 428 cflags_objcc = cflags_cc429}430 431config("no_exceptions") {432 cflags_cc = []433 if (current_os != "win") {434 cflags_cc += [ "-fno-exceptions" ]435 }436 cflags_objcc = cflags_cc437}438 439config("no_rtti") {440 if (current_os == "win") {441 cflags_cc = [ "/GR-" ]442 } else {443 cflags_cc = [ "-fno-rtti" ]444 }445 cflags_objcc = cflags_cc446}447 448config("zdefs") {449 # -Wl,-z,defs doesn't work with sanitizers.450 # https://clang.llvm.org/docs/AddressSanitizer.html451 if (current_os != "ios" && current_os != "mac" && current_os != "win" &&452 !(use_asan || use_tsan || use_ubsan)) {453 ldflags = [ "-Wl,-z,defs" ]454 }455}456 457# To make an archive that can be distributed, you need to remove this config and458# set complete_static_lib.459config("thin_archive") {460 if (current_os != "ios" && current_os != "mac" && current_os != "win") {461 arflags = [ "-T" ]462 }463}464 465config("llvm_code") {466 include_dirs = [467 "//llvm/include",468 "$root_gen_dir/llvm/include",469 ]470 if (current_os != "win") {471 cflags = [ "-fPIC" ]472 }473}474 475config("lld_code") {476 include_dirs = [477 "//lld/include",478 "$root_gen_dir/lld/include",479 ]480}481 482config("clang_code") {483 if (current_os != "win") {484 cflags = [ "-fno-strict-aliasing" ]485 }486 include_dirs = [487 "//clang/include",488 "$root_gen_dir/clang/include",489 ]490}491 492config("bolt_code") {493 include_dirs = [494 "//bolt/include",495 "$root_gen_dir/bolt/include",496 ]497}498 499config("crt_code") {500 include_dirs = [ "//compiler-rt/lib" ]501 cflags = [502 "-fno-builtin",503 "-gline-tables-only",504 ]505 if (current_os != "win") {506 cflags += [507 "-fPIC",508 "-funwind-tables",509 "-fvisibility=hidden",510 ]511 } else {512 cflags += [513 # Disable thread safe initialization for static locals. ASan shouldn't need it.514 # Thread safe initialization assumes that the CRT has already been initialized, but ASan initializes before the CRT.515 "/Zc:threadSafeInit-",516 ]517 }518 if (is_clang) {519 cflags += [520 "-Werror=thread-safety",521 "-Werror=thread-safety-reference",522 "-Werror=thread-safety-beta",523 ]524 }525}526 527config("lldb_code") {528 if (current_os != "win") {529 cflags = [ "-fno-strict-aliasing" ]530 }531 include_dirs = [532 "//lldb/include",533 "$root_gen_dir/lldb/include",534 ]535}536 537config("warn_covered_switch_default") {538 if (is_clang) {539 cflags = [ "-Wcovered-switch-default" ]540 }541}542