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