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 coverage information. 9 # After building with this, run tests and then run 10 # llvm/utils/prepare-code-coverage-artifact.py \ 11 # .../llvm-profdata .../llvm-cov out/gn/profiles/ report/ \ 12 # out/gn/bin/llvm-undname ...` 13 # to generate a HTML report for the binaries passed in the last line. 14 llvm_build_instrumented_coverage = false 15 16 # If set, puts relative paths in debug info. 17 # Makes the build output independent of the build directory, but makes 18 # most debuggers harder to use. See "Getting to local determinism" and 19 # "Getting debuggers to work well with locally deterministic builds" in 20 # http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html 21 # for more information. 22 use_relative_paths_in_debug_info = false 23 24 # The version of host gcc. Ignored if is_clang is true. 25 gcc_version = 9 26} 27 28assert(!llvm_build_instrumented_coverage || is_clang, 29 "llvm_build_instrumented_coverage requires clang as host compiler") 30 31config("compiler_defaults") { 32 defines = [] 33 34 if (!llvm_enable_assertions) { 35 defines += [ "NDEBUG" ] 36 } 37 38 if (llvm_enable_expensive_checks) { 39 defines += [ "EXPENSIVE_CHECKS" ] 40 } 41 42 asmflags = target_flags 43 cflags = target_flags 44 ldflags = target_flags + target_ldflags 45 46 # Mostly for compiler-rt, see compiler-rt/cmake/config-ix.cmake 47 if (current_os == "ios") { 48 asmflags += [ "-miphoneos-version-min=8.0" ] 49 cflags += [ "-miphoneos-version-min=8.0" ] 50 ldflags += [ "-miphoneos-version-min=8.0" ] 51 } 52 if (current_os == "mac") { 53 asmflags += [ "-mmacosx-version-min=10.10" ] 54 cflags += [ "-mmacosx-version-min=10.10" ] 55 ldflags += [ "-mmacosx-version-min=10.10" ] 56 } 57 58 assert(symbol_level == 0 || symbol_level == 1 || symbol_level == 2, 59 "Unexpected symbol_level") 60 if (host_os != "win") { 61 if (symbol_level == 2) { 62 cflags += [ "-g" ] 63 64 # For full debug-info -g builds, --gdb-index makes links ~15% slower, and 65 # gdb symbol reading time 1500% faster (lld links in 4.4 instead of 3.9s, 66 # and gdb loads and runs it in 2s instead of in 30s). It's likely that 67 # people doing symbol_level=2 want to run a debugger (since 68 # symbol_level=2 isn't the default). So this seems like the right 69 # tradeoff. 70 if (host_os != "mac" && use_lld) { 71 cflags += [ "-ggnu-pubnames" ] # PR34820 72 ldflags += [ "-Wl,--gdb-index" ] 73 } 74 } else if (symbol_level == 1) { 75 cflags += [ "-g1" ] 76 # For linetable-only -g1 builds, --gdb-index makes links ~8% slower, but 77 # links are 4x faster than -g builds so it's a fairly small absolute cost. 78 # On the other hand, gdb startup is well below 1s with and without the 79 # index, and people using -g1 likely don't use a debugger. So don't use 80 # the flag here. 81 } 82 if (is_optimized) { 83 cflags += [ "-O3" ] 84 } 85 cflags += [ "-fdiagnostics-color" ] 86 if (use_lld) { 87 ldflags += [ "-Wl,--color-diagnostics" ] 88 } 89 cflags_cc = [ 90 "-std=c++14", 91 "-fvisibility-inlines-hidden", 92 ] 93 } else { 94 if (symbol_level != 0) { 95 cflags += [ 96 "/Zi", 97 "/FS", 98 ] 99 if (symbol_level == 1 && is_clang) { 100 cflags += [ "-gline-tables-only" ] 101 } 102 ldflags += [ "/DEBUG" ] 103 104 # Speed up links with ghash on windows. 105 if (use_lld && is_clang) { 106 cflags += [ "-gcodeview-ghash" ] 107 ldflags += [ "/DEBUG:GHASH" ] 108 } 109 } 110 if (is_optimized) { 111 cflags += [ 112 "/O2", 113 "/Gw", 114 "/Zc:inline", 115 ] 116 ldflags += [ 117 "/OPT:REF", 118 "/OPT:ICF", 119 ] 120 } 121 defines += [ 122 "_CRT_SECURE_NO_DEPRECATE", 123 "_CRT_SECURE_NO_WARNINGS", 124 "_CRT_NONSTDC_NO_DEPRECATE", 125 "_CRT_NONSTDC_NO_WARNINGS", 126 "_SCL_SECURE_NO_DEPRECATE", 127 "_SCL_SECURE_NO_WARNINGS", 128 129 "_HAS_EXCEPTIONS=0", 130 "_UNICODE", 131 "UNICODE", 132 ] 133 cflags += [ "/EHs-c-" ] 134 135 # The MSVC default value (1 MB) is not enough for parsing recursive C++ 136 # templates in Clang. 137 ldflags += [ "/STACK:10000000" ] 138 } 139 140 # Warning setup. 141 if (host_os == "win" && !is_clang) { 142 cflags += [ 143 # Suppress ''modifier' : used more than once' (__forceinline and inline). 144 "-wd4141", 145 146 # Suppress 'conversion from 'type1' to 'type2', possible loss of data'. 147 "-wd4244", 148 149 # Suppress 'conversion from 'size_t' to 'type', possible loss of data'. 150 "-wd4267", 151 152 # Suppress 'no matching operator delete found'. 153 "-wd4291", 154 155 # Suppress 'noexcept used with no exception handling mode specified'. 156 "-wd4577", 157 158 # Suppress 'destructor was implicitly defined as deleted'. 159 "-wd4624", 160 161 # Suppress 'unsafe mix of type <type> and type <type> in operation'. 162 "-wd4805", 163 ] 164 } else { 165 if (host_os == "win") { 166 cflags += [ "/W4" ] 167 } else { 168 cflags += [ 169 "-Wall", 170 "-Wextra", 171 ] 172 } 173 cflags += [ "-Wno-unused-parameter" ] 174 if (is_clang) { 175 cflags += [ 176 "-Wdelete-non-virtual-dtor", 177 "-Wstring-conversion", 178 ] 179 } else { 180 cflags += [ 181 # GCC's -Wcomment complains about // comments ending with '\' if the 182 # next line is also a // comment. 183 "-Wno-comment", 184 185 # Disable gcc's potentially uninitialized use analysis as it presents 186 # lots of false positives. 187 "-Wno-maybe-uninitialized", 188 ] 189 cflags_cc += [ 190 # The LLVM libraries have no stable C++ API, so -Wnoexcept-type is not 191 # useful. 192 "-Wno-noexcept-type", 193 ] 194 if (gcc_version >= 8) { 195 cflags_cc += [ 196 # Disable -Wclass-memaccess, a C++-only warning from GCC 8 that fires 197 # on LLVM's ADT classes. 198 "-Wno-class-memaccess", 199 ] 200 } 201 if (gcc_version >= 9) { 202 cflags_cc += [ 203 # Disable -Wredundant-move on GCC>=9. GCC wants to remove std::move 204 # in code like "A foo(ConvertibleToA a) { return std::move(a); }", 205 # but this code does not compile (or uses the copy constructor 206 # instead) on clang<=3.8. Clang also has a -Wredundant-move, but it 207 # only fires when the types match exactly, so we can keep it here. 208 "-Wno-redundant-move", 209 ] 210 } 211 } 212 if (is_clang && use_goma) { 213 # goma converts all paths to lowercase on the server, breaking this 214 # warning. 215 cflags += [ "-Wno-nonportable-include-path" ] 216 } 217 } 218 219 # On Windows, the linker is not invoked through the compiler driver. 220 if (use_lld && host_os != "win") { 221 ldflags += [ "-fuse-ld=lld" ] 222 } 223 224 if (llvm_build_instrumented_coverage) { 225 cflags += [ 226 "-fcoverage-mapping", 227 228 # Using an absolute path here is lame, but it's used at test execution 229 # time to generate the profiles, and lit doesn't specify a fixed folder 230 # for test execution -- so this is the only way to get all profiles into 231 # a single folder like llvm/utils/prepare-code-coverage-artifact.py 232 # expects. 233 "-fprofile-instr-generate=" + 234 rebase_path("$root_build_dir/profiles/%4m.profraw"), 235 ] 236 if (host_os != "win") { 237 ldflags += [ "-fprofile-instr-generate" ] 238 } 239 } 240 241 # Deterministic build setup, see 242 # http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html 243 if (current_os == "win") { 244 ldflags += [ "/pdbaltpath:%_PDB%" ] 245 } 246 if (is_clang) { 247 cflags += [ 248 "-no-canonical-prefixes", 249 "-Werror=date-time", 250 ] 251 if (current_os == "win") { 252 cflags += [ "-fmsc-version=1916" ] 253 if (use_lld) { 254 cflags += [ "/Brepro" ] 255 ldflags += [ "/Brepro" ] 256 } 257 } 258 if (use_relative_paths_in_debug_info) { 259 cflags += [ 260 "-fdebug-compilation-dir", 261 ".", 262 ] 263 } 264 } 265 if (sysroot != "") { 266 if (current_os == "win") { 267 assert(is_clang, "sysroot only works with clang-cl as host compiler") 268 cflags += [ "/winsysroot" + rebase_path(sysroot, root_build_dir) ] 269 } else if (current_os != "ios" && current_os != "mac") { 270 cflags += [ "--sysroot=" + rebase_path(sysroot, root_build_dir) ] 271 } 272 } 273 if ((current_os == "ios" || current_os == "mac") && 274 (clang_base_path != "" || sysroot != "")) { 275 if (current_os == "ios" && current_cpu == "arm64") { 276 sdk_path = ios_sdk_path 277 } else if (current_os == "ios" && current_cpu == "x64") { 278 sdk_path = iossim_sdk_path 279 } else if (current_os == "mac") { 280 sdk_path = mac_sdk_path 281 } 282 cflags += [ 283 "-isysroot", 284 rebase_path(sdk_path, root_build_dir), 285 ] 286 ldflags += [ 287 "-isysroot", 288 rebase_path(sdk_path, root_build_dir), 289 ] 290 } 291 if (sysroot != "" && current_os != "win" && is_clang) { 292 cflags += [ "-Wpoison-system-directories" ] 293 } 294 assert( 295 !use_goma || sysroot != "", 296 "goma needs a sysroot: run `llvm/utils/sysroot.py make-fake --out-dir=sysroot` and add `sysroot = \"//sysroot\"` to your args.gn") 297 298 if (use_ubsan) { 299 assert(is_clang && current_os == "linux", 300 "ubsan only supported on Linux/Clang") 301 cflags += [ "-fsanitize=undefined" ] 302 ldflags += [ "-fsanitize=undefined" ] 303 } 304 305 if (use_asan) { 306 assert(is_clang && current_os == "linux", 307 "asan only supported on Linux/Clang") 308 cflags += [ "-fsanitize=address" ] 309 ldflags += [ "-fsanitize=address" ] 310 } 311 312 if (use_tsan) { 313 assert(is_clang && current_os == "linux", 314 "tsan only supported on Linux/Clang") 315 cflags += [ "-fsanitize=thread" ] 316 ldflags += [ "-fsanitize=thread" ] 317 } 318 319 if (use_thinlto) { 320 assert(is_clang, "ThinLTO only supported on Clang") 321 322 lto_opt_level = 2 323 324 cflags += [ "-flto=thin" ] 325 326 if (host_os == "win") { 327 ldflags += [ 328 "/opt:lldlto=" + lto_opt_level, 329 "/opt:lldltojobs=" + max_jobs_per_lto_link, 330 ] 331 } else { 332 ldflags += [ 333 "-flto=thin", 334 "-Wl,--thinlto-jobs=" + max_jobs_per_lto_link, 335 "-Wl,--lto-O" + lto_opt_level, 336 ] 337 } 338 } 339} 340 341config("no_exceptions") { 342 if (host_os != "win") { 343 cflags_cc = [ "-fno-exceptions" ] 344 } 345} 346 347config("no_rtti") { 348 if (current_os == "win") { 349 cflags_cc = [ "/GR-" ] 350 } else { 351 cflags_cc = [ "-fno-rtti" ] 352 } 353} 354 355# To make an archive that can be distributed, you need to remove this config and 356# set complete_static_lib. 357config("thin_archive") { 358 if (current_os != "ios" && current_os != "mac" && current_os != "win") { 359 arflags = [ "-T" ] 360 } 361} 362 363config("llvm_code") { 364 include_dirs = [ 365 "//llvm/include", 366 "$root_gen_dir/llvm/include", 367 ] 368} 369 370config("lld_code") { 371 include_dirs = [ 372 "//lld/include", 373 "$root_gen_dir/lld/include", 374 ] 375} 376 377config("clang_code") { 378 if (host_os != "win") { 379 cflags = [ "-fno-strict-aliasing" ] 380 } 381 include_dirs = [ 382 "//clang/include", 383 "$root_gen_dir/clang/include", 384 ] 385} 386 387config("crt_code") { 388 include_dirs = [ "//compiler-rt/lib" ] 389 cflags = [ 390 "-fPIC", 391 "-funwind-tables", 392 "-gline-tables-only", 393 "-fvisibility=hidden", 394 ] 395} 396 397config("warn_covered_switch_default") { 398 if (is_clang) { 399 cflags = [ "-Wcovered-switch-default" ] 400 } 401} 402