OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import("//build/config/nacl/config.gni") |
| 6 import("//build/config/sanitizers/sanitizers.gni") |
| 7 import("//build/toolchain/cc_wrapper.gni") |
| 8 import("//build/toolchain/goma.gni") |
| 9 import("//build/toolchain/toolchain.gni") |
| 10 |
| 11 # "concurrent_links" is a toolchain variable. By computing it here rather than |
| 12 # inside the toolchain, the exec_script will only get run once rather than |
| 13 # each time the toolchain template is invoked. |
| 14 if (allow_posix_link_time_opt || is_cfi) { |
| 15 concurrent_links_ = |
| 16 exec_script("get_concurrent_links.py", [ "--lto" ], "value") |
| 17 } else { |
| 18 concurrent_links_ = exec_script("get_concurrent_links.py", [], "value") |
| 19 } |
| 20 |
| 21 # This template defines a toolchain for something that works like gcc |
| 22 # (including clang). |
| 23 # |
| 24 # It requires the following variables specifying the executables to run: |
| 25 # - ar |
| 26 # - cc |
| 27 # - cxx |
| 28 # - ld |
| 29 # and the following which is used in the toolchain_args |
| 30 # - toolchain_cpu (What "current_cpu" should be set to when invoking a |
| 31 # build using this toolchain.) |
| 32 # - toolchain_os (What "current_os" should be set to when invoking a |
| 33 # build using this toolchain.) |
| 34 # |
| 35 # Optional parameters that control the tools: |
| 36 # |
| 37 # - extra_cflags |
| 38 # Extra flags to be appended when compiling C files (but not C++ files). |
| 39 # - extra_cppflags |
| 40 # Extra flags to be appended when compiling both C and C++ files. "CPP" |
| 41 # stands for "C PreProcessor" in this context, although it can be |
| 42 # used for non-preprocessor flags as well. Not to be confused with |
| 43 # "CXX" (which follows). |
| 44 # - extra_cxxflags |
| 45 # Extra flags to be appended when compiling C++ files (but not C files). |
| 46 # - extra_ldflags |
| 47 # Extra flags to be appended when linking |
| 48 # |
| 49 # - libs_section_prefix |
| 50 # - libs_section_postfix |
| 51 # The contents of these strings, if specified, will be placed around |
| 52 # the libs section of the linker line. It allows one to inject libraries |
| 53 # at the beginning and end for all targets in a toolchain. |
| 54 # - solink_libs_section_prefix |
| 55 # - solink_libs_section_postfix |
| 56 # Same as libs_section_{pre,post}fix except used for solink instead of link
. |
| 57 # - link_outputs |
| 58 # The content of this array, if specified, will be added to the list of |
| 59 # outputs from the link command. This can be useful in conjunction with |
| 60 # the post_link parameter. |
| 61 # - post_link |
| 62 # The content of this string, if specified, will be run as a separate |
| 63 # command following the the link command. |
| 64 # - deps |
| 65 # Just forwarded to the toolchain definition. |
| 66 # - executable_extension |
| 67 # If this string is specified it will be used for the file extension |
| 68 # for an executable, rather than using no extension; targets will |
| 69 # still be able to override the extension using the output_extension |
| 70 # variable. |
| 71 # - rebuild_define |
| 72 # The contents of this string, if specified, will be passed as a #define |
| 73 # to the toolchain. It can be used to force recompiles whenever a |
| 74 # toolchain is updated. |
| 75 # - shlib_extension |
| 76 # If this string is specified it will be used for the file extension |
| 77 # for a shared library, rather than default value specified in |
| 78 # toolchain.gni |
| 79 # - strip |
| 80 # Location of the strip executable. When specified, strip will be run on |
| 81 # all shared libraries and executables as they are built. The pre-stripped |
| 82 # artifacts will be put in lib.unstripped/ and exe.unstripped/. |
| 83 # |
| 84 # Optional build argument contols. |
| 85 # |
| 86 # - clear_sanitizers |
| 87 # When set to true, is_asan, is_msan, etc.will all be set to false. Often |
| 88 # secondary toolchains do not want to run with sanitizers. |
| 89 # - is_clang |
| 90 # Whether to use clang instead of gcc. |
| 91 # - is_component_build |
| 92 # Whether to forcibly enable or disable component builds for this |
| 93 # toolchain; if not specified, the toolchain will inherit the |
| 94 # default setting. |
| 95 # - is_nacl_glibc |
| 96 # Whether NaCl code is built using Glibc instead of Newlib. |
| 97 # - cc_wrapper |
| 98 # Override the global cc_wrapper setting. e.g. "ccache" or "icecc". |
| 99 # useful to opt-out of cc_wrapper in a particular toolchain by setting |
| 100 # cc_wrapper = "" in it. |
| 101 # - use_debug_fission |
| 102 # Override the global use_debug_fission setting, useful if the particular |
| 103 # toolchain should not be generating split-dwarf code. |
| 104 # - use_goma |
| 105 # Override the global use_goma setting, useful to opt-out of goma in a |
| 106 # particular toolchain by setting use_gome = false in it. |
| 107 # - use_gold |
| 108 # Override the global use_gold setting, useful if the particular |
| 109 # toolchain has a custom link step that is not actually using Gold. |
| 110 template("gcc_toolchain") { |
| 111 toolchain(target_name) { |
| 112 assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ar\" value") |
| 113 assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value") |
| 114 assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value") |
| 115 assert(defined(invoker.ld), "gcc_toolchain() must specify a \"ld\" value") |
| 116 assert(defined(invoker.toolchain_cpu), |
| 117 "gcc_toolchain() must specify a \"toolchain_cpu\"") |
| 118 assert(defined(invoker.toolchain_os), |
| 119 "gcc_toolchain() must specify a \"toolchain_os\"") |
| 120 |
| 121 concurrent_links = concurrent_links_ |
| 122 |
| 123 if (defined(invoker.cc_wrapper)) { |
| 124 cc_wrapper = invoker.cc_wrapper |
| 125 } |
| 126 if (defined(invoker.use_goma)) { |
| 127 use_goma = invoker.use_goma |
| 128 } |
| 129 if (use_goma) { |
| 130 assert(cc_wrapper == "", "Goma and cc_wrapper can't be used together.") |
| 131 compiler_prefix = "$goma_dir/gomacc " |
| 132 } else if (cc_wrapper != "") { |
| 133 compiler_prefix = cc_wrapper + " " |
| 134 } else { |
| 135 compiler_prefix = "" |
| 136 } |
| 137 |
| 138 # This define changes when the toolchain changes, forcing a rebuild. |
| 139 # Nothing should ever use this define. |
| 140 if (defined(invoker.rebuild_define)) { |
| 141 rebuild_string = "-D" + invoker.rebuild_define + " " |
| 142 } else { |
| 143 rebuild_string = "" |
| 144 } |
| 145 |
| 146 cc = compiler_prefix + invoker.cc |
| 147 cxx = compiler_prefix + invoker.cxx |
| 148 ar = invoker.ar |
| 149 ld = invoker.ld |
| 150 if (defined(invoker.readelf)) { |
| 151 readelf = invoker.readelf |
| 152 } else { |
| 153 readelf = "readelf" |
| 154 } |
| 155 if (defined(invoker.nm)) { |
| 156 nm = invoker.nm |
| 157 } else { |
| 158 nm = "nm" |
| 159 } |
| 160 |
| 161 if (defined(invoker.shlib_extension)) { |
| 162 default_shlib_extension = invoker.shlib_extension |
| 163 } else { |
| 164 default_shlib_extension = shlib_extension |
| 165 } |
| 166 |
| 167 if (defined(invoker.executable_extension)) { |
| 168 default_executable_extension = invoker.executable_extension |
| 169 } else { |
| 170 default_executable_extension = "" |
| 171 } |
| 172 |
| 173 # Bring these into our scope for string interpolation with default values. |
| 174 if (defined(invoker.libs_section_prefix)) { |
| 175 libs_section_prefix = invoker.libs_section_prefix |
| 176 } else { |
| 177 libs_section_prefix = "" |
| 178 } |
| 179 |
| 180 if (defined(invoker.libs_section_postfix)) { |
| 181 libs_section_postfix = invoker.libs_section_postfix |
| 182 } else { |
| 183 libs_section_postfix = "" |
| 184 } |
| 185 |
| 186 if (defined(invoker.solink_libs_section_prefix)) { |
| 187 solink_libs_section_prefix = invoker.solink_libs_section_prefix |
| 188 } else { |
| 189 solink_libs_section_prefix = "" |
| 190 } |
| 191 |
| 192 if (defined(invoker.solink_libs_section_postfix)) { |
| 193 solink_libs_section_postfix = invoker.solink_libs_section_postfix |
| 194 } else { |
| 195 solink_libs_section_postfix = "" |
| 196 } |
| 197 |
| 198 if (defined(invoker.extra_cflags) && invoker.extra_cflags != "") { |
| 199 extra_cflags = " " + invoker.extra_cflags |
| 200 } else { |
| 201 extra_cflags = "" |
| 202 } |
| 203 |
| 204 if (defined(invoker.extra_cppflags) && invoker.extra_cppflags != "") { |
| 205 extra_cppflags = " " + invoker.extra_cppflags |
| 206 } else { |
| 207 extra_cppflags = "" |
| 208 } |
| 209 |
| 210 if (defined(invoker.extra_cxxflags) && invoker.extra_cxxflags != "") { |
| 211 extra_cxxflags = " " + invoker.extra_cxxflags |
| 212 } else { |
| 213 extra_cxxflags = "" |
| 214 } |
| 215 |
| 216 if (defined(invoker.extra_ldflags) && invoker.extra_ldflags != "") { |
| 217 extra_ldflags = " " + invoker.extra_ldflags |
| 218 } else { |
| 219 extra_ldflags = "" |
| 220 } |
| 221 |
| 222 # These library switches can apply to all tools below. |
| 223 lib_switch = "-l" |
| 224 lib_dir_switch = "-L" |
| 225 |
| 226 # Object files go in this directory. |
| 227 object_subdir = "{{target_out_dir}}/{{label_name}}" |
| 228 |
| 229 tool("cc") { |
| 230 depfile = "{{output}}.d" |
| 231 command = "$cc -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_di
rs}} {{cflags}} {{cflags_c}}${extra_cppflags}${extra_cflags} -c {{source}} -o {{
output}}" |
| 232 depsformat = "gcc" |
| 233 description = "CC {{output}}" |
| 234 outputs = [ |
| 235 "$object_subdir/{{source_name_part}}.o", |
| 236 ] |
| 237 } |
| 238 |
| 239 tool("cxx") { |
| 240 depfile = "{{output}}.d" |
| 241 command = "$cxx -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_d
irs}} {{cflags}} {{cflags_cc}}${extra_cppflags}${extra_cxxflags} -c {{source}} -
o {{output}}" |
| 242 depsformat = "gcc" |
| 243 description = "CXX {{output}}" |
| 244 outputs = [ |
| 245 "$object_subdir/{{source_name_part}}.o", |
| 246 ] |
| 247 } |
| 248 |
| 249 tool("asm") { |
| 250 # For GCC we can just use the C compiler to compile assembly. |
| 251 depfile = "{{output}}.d" |
| 252 command = "$cc -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_di
rs}} {{asmflags}} -c {{source}} -o {{output}}" |
| 253 depsformat = "gcc" |
| 254 description = "ASM {{output}}" |
| 255 outputs = [ |
| 256 "$object_subdir/{{source_name_part}}.o", |
| 257 ] |
| 258 } |
| 259 |
| 260 tool("alink") { |
| 261 rspfile = "{{output}}.rsp" |
| 262 |
| 263 # This needs a Python script to avoid using simple sh features in this |
| 264 # command, in case the host does not use a POSIX shell (e.g. compiling |
| 265 # POSIX-like toolchains such as NaCl on Windows). |
| 266 ar_wrapper = |
| 267 rebase_path("//build/toolchain/gcc_ar_wrapper.py", root_build_dir) |
| 268 command = "$python_path \"$ar_wrapper\" --output={{output}} --ar=\"$ar\" {
{arflags}} rcsD @\"$rspfile\"" |
| 269 description = "AR {{output}}" |
| 270 rspfile_content = "{{inputs}}" |
| 271 outputs = [ |
| 272 "{{output_dir}}/{{target_output_name}}{{output_extension}}", |
| 273 ] |
| 274 |
| 275 # Shared libraries go in the target out directory by default so we can |
| 276 # generate different targets with the same name and not have them collide. |
| 277 default_output_dir = "{{target_out_dir}}" |
| 278 default_output_extension = ".a" |
| 279 output_prefix = "lib" |
| 280 } |
| 281 |
| 282 tool("solink") { |
| 283 soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so". |
| 284 sofile = "{{output_dir}}/$soname" # Possibly including toolchain dir. |
| 285 rspfile = sofile + ".rsp" |
| 286 |
| 287 if (defined(invoker.strip)) { |
| 288 unstripped_sofile = "{{root_out_dir}}/lib.unstripped/$soname" |
| 289 } else { |
| 290 unstripped_sofile = sofile |
| 291 } |
| 292 |
| 293 # These variables are not built into GN but are helpers that |
| 294 # implement (1) linking to produce a .so, (2) extracting the symbols |
| 295 # from that file (3) if the extracted list differs from the existing |
| 296 # .TOC file, overwrite it, otherwise, don't change it. |
| 297 tocfile = sofile + ".TOC" |
| 298 |
| 299 link_command = "$ld -shared {{ldflags}}${extra_ldflags} -o \"$unstripped_s
ofile\" -Wl,-soname=\"$soname\" @\"$rspfile\"" |
| 300 |
| 301 assert(defined(readelf), "to solink you must have a readelf") |
| 302 assert(defined(nm), "to solink you must have an nm") |
| 303 strip_switch = "" |
| 304 if (defined(invoker.strip)) { |
| 305 strip_switch = "--strip=${invoker.strip}" |
| 306 } |
| 307 |
| 308 # This needs a Python script to avoid using a complex shell command |
| 309 # requiring sh control structures, pipelines, and POSIX utilities. |
| 310 # The host might not have a POSIX shell and utilities (e.g. Windows). |
| 311 solink_wrapper = rebase_path("//build/toolchain/gcc_solink_wrapper.py") |
| 312 command = "$python_path \"$solink_wrapper\" --readelf=\"$readelf\" --nm=\"
$nm\" $strip_switch --sofile=\"$unstripped_sofile\" --tocfile=\"$tocfile\" --out
put=\"$sofile\" -- $link_command" |
| 313 |
| 314 rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whol
e-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix" |
| 315 |
| 316 description = "SOLINK $sofile" |
| 317 |
| 318 # Use this for {{output_extension}} expansions unless a target manually |
| 319 # overrides it (in which case {{output_extension}} will be what the target |
| 320 # specifies). |
| 321 default_output_extension = default_shlib_extension |
| 322 |
| 323 default_output_dir = "{{root_out_dir}}" |
| 324 if (shlib_subdir != ".") { |
| 325 default_output_dir += "/$shlib_subdir" |
| 326 } |
| 327 |
| 328 output_prefix = "lib" |
| 329 |
| 330 # Since the above commands only updates the .TOC file when it changes, ask |
| 331 # Ninja to check if the timestamp actually changed to know if downstream |
| 332 # dependencies should be recompiled. |
| 333 restat = true |
| 334 |
| 335 # Tell GN about the output files. It will link to the sofile but use the |
| 336 # tocfile for dependency management. |
| 337 outputs = [ |
| 338 sofile, |
| 339 tocfile, |
| 340 ] |
| 341 if (sofile != unstripped_sofile) { |
| 342 outputs += [ unstripped_sofile ] |
| 343 } |
| 344 link_output = sofile |
| 345 depend_output = tocfile |
| 346 } |
| 347 |
| 348 tool("solink_module") { |
| 349 soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so". |
| 350 sofile = "{{output_dir}}/$soname" |
| 351 rspfile = sofile + ".rsp" |
| 352 |
| 353 if (defined(invoker.strip)) { |
| 354 unstripped_sofile = "{{root_out_dir}}/lib.unstripped/$soname" |
| 355 } else { |
| 356 unstripped_sofile = sofile |
| 357 } |
| 358 |
| 359 command = "$ld -shared {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile
\" -Wl,-soname=\"$soname\" @\"$rspfile\"" |
| 360 |
| 361 if (defined(invoker.strip)) { |
| 362 strip_command = "${invoker.strip} --strip-unneeded -o \"$sofile\" \"$uns
tripped_sofile\"" |
| 363 command += " && " + strip_command |
| 364 } |
| 365 rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whol
e-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix" |
| 366 |
| 367 description = "SOLINK_MODULE $sofile" |
| 368 |
| 369 # Use this for {{output_extension}} expansions unless a target manually |
| 370 # overrides it (in which case {{output_extension}} will be what the target |
| 371 # specifies). |
| 372 if (defined(invoker.loadable_module_extension)) { |
| 373 default_output_extension = invoker.loadable_module_extension |
| 374 } else { |
| 375 default_output_extension = default_shlib_extension |
| 376 } |
| 377 |
| 378 default_output_dir = "{{root_out_dir}}" |
| 379 if (shlib_subdir != ".") { |
| 380 default_output_dir += "/$shlib_subdir" |
| 381 } |
| 382 |
| 383 output_prefix = "lib" |
| 384 |
| 385 outputs = [ |
| 386 sofile, |
| 387 ] |
| 388 if (sofile != unstripped_sofile) { |
| 389 outputs += [ unstripped_sofile ] |
| 390 } |
| 391 } |
| 392 |
| 393 tool("link") { |
| 394 exename = "{{target_output_name}}{{output_extension}}" |
| 395 outfile = "{{output_dir}}/$exename" |
| 396 rspfile = "$outfile.rsp" |
| 397 unstripped_outfile = outfile |
| 398 |
| 399 # Use this for {{output_extension}} expansions unless a target manually |
| 400 # overrides it (in which case {{output_extension}} will be what the target |
| 401 # specifies). |
| 402 default_output_extension = default_executable_extension |
| 403 |
| 404 default_output_dir = "{{root_out_dir}}" |
| 405 |
| 406 if (defined(invoker.strip)) { |
| 407 unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$exename" |
| 408 } |
| 409 |
| 410 command = "$ld {{ldflags}}${extra_ldflags} -o \"$unstripped_outfile\" -Wl,
--start-group @\"$rspfile\" {{solibs}} -Wl,--end-group $libs_section_prefix {{li
bs}} $libs_section_postfix" |
| 411 if (defined(invoker.strip)) { |
| 412 link_wrapper = |
| 413 rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir) |
| 414 command = "$python_path \"$link_wrapper\" --strip=\"${invoker.strip}\" -
-unstripped-file=\"$unstripped_outfile\" --output=\"$outfile\" -- $command" |
| 415 } |
| 416 description = "LINK $outfile" |
| 417 rspfile_content = "{{inputs}}" |
| 418 outputs = [ |
| 419 outfile, |
| 420 ] |
| 421 if (outfile != unstripped_outfile) { |
| 422 outputs += [ unstripped_outfile ] |
| 423 } |
| 424 if (defined(invoker.link_outputs)) { |
| 425 outputs += invoker.link_outputs |
| 426 } |
| 427 } |
| 428 |
| 429 # These two are really entirely generic, but have to be repeated in |
| 430 # each toolchain because GN doesn't allow a template to be used here. |
| 431 # See //build/toolchain/toolchain.gni for details. |
| 432 tool("stamp") { |
| 433 command = stamp_command |
| 434 description = stamp_description |
| 435 } |
| 436 tool("copy") { |
| 437 command = copy_command |
| 438 description = copy_description |
| 439 } |
| 440 |
| 441 # When invoking this toolchain not as the default one, these args will be |
| 442 # passed to the build. They are ignored when this is the default toolchain. |
| 443 toolchain_args() { |
| 444 current_cpu = invoker.toolchain_cpu |
| 445 current_os = invoker.toolchain_os |
| 446 |
| 447 # These values need to be passed through unchanged. |
| 448 host_toolchain = host_toolchain |
| 449 target_os = target_os |
| 450 target_cpu = target_cpu |
| 451 |
| 452 if (defined(invoker.is_clang)) { |
| 453 is_clang = invoker.is_clang |
| 454 } |
| 455 if (defined(invoker.is_component_build)) { |
| 456 is_component_build = invoker.is_component_build |
| 457 } |
| 458 if (defined(invoker.is_nacl_glibc)) { |
| 459 is_nacl_glibc = invoker.is_nacl_glibc |
| 460 } |
| 461 if (defined(invoker.symbol_level)) { |
| 462 symbol_level = invoker.symbol_level |
| 463 } |
| 464 if (defined(invoker.use_allocator)) { |
| 465 use_allocator = invoker.use_allocator |
| 466 } |
| 467 if (defined(invoker.use_debug_fission)) { |
| 468 use_debug_fission = invoker.use_debug_fission |
| 469 } |
| 470 if (defined(invoker.use_gold)) { |
| 471 use_gold = invoker.use_gold |
| 472 } |
| 473 if (defined(invoker.use_sysroot)) { |
| 474 use_sysroot = invoker.use_sysroot |
| 475 } |
| 476 |
| 477 # Disable sanitizers for non-default toolchains. |
| 478 is_asan = false |
| 479 is_cfi = false |
| 480 is_lsan = false |
| 481 is_msan = false |
| 482 is_syzyasan = false |
| 483 is_tsan = false |
| 484 is_ubsan = false |
| 485 is_ubsan_vptr = false |
| 486 } |
| 487 |
| 488 forward_variables_from(invoker, [ "deps" ]) |
| 489 } |
| 490 } |
| 491 |
| 492 # This is a shorthand for gcc_toolchain instances based on the |
| 493 # Chromium-built version of Clang. Only the toolchain_cpu and |
| 494 # toolchain_os variables need to be specified by the invoker, and |
| 495 # optionally toolprefix if it's a cross-compile case. Note that for |
| 496 # a cross-compile case this toolchain requires a config to pass the |
| 497 # appropriate -target option, or else it will actually just be doing |
| 498 # a native compile. The invoker can optionally override use_gold too. |
| 499 template("clang_toolchain") { |
| 500 assert(defined(invoker.toolchain_cpu), |
| 501 "clang_toolchain() must specify a \"toolchain_cpu\"") |
| 502 assert(defined(invoker.toolchain_os), |
| 503 "clang_toolchain() must specify a \"toolchain_os\"") |
| 504 if (defined(invoker.toolprefix)) { |
| 505 toolprefix = invoker.toolprefix |
| 506 } else { |
| 507 toolprefix = "" |
| 508 } |
| 509 |
| 510 gcc_toolchain(target_name) { |
| 511 prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", |
| 512 root_build_dir) |
| 513 cc = "$prefix/clang" |
| 514 cxx = "$prefix/clang++" |
| 515 ld = cxx |
| 516 is_clang = true |
| 517 |
| 518 readelf = "${toolprefix}readelf" |
| 519 ar = "${toolprefix}ar" |
| 520 nm = "${toolprefix}nm" |
| 521 |
| 522 forward_variables_from(invoker, |
| 523 [ |
| 524 "toolchain_cpu", |
| 525 "toolchain_os", |
| 526 "use_gold", |
| 527 "strip", |
| 528 ]) |
| 529 |
| 530 if (defined(invoker.use_debug_fission)) { |
| 531 use_debug_fission = invoker.use_debug_fission |
| 532 } |
| 533 } |
| 534 } |
OLD | NEW |