1if (is_wasm) { 2 import("wasm.gni") 3} 4if (is_fuchsia) { 5 import("//build/fuchsia/sdk.gni") 6} 7 8declare_args() { 9 host_ar = ar 10 host_cc = cc 11 host_cxx = cxx 12 13 if (is_android) { 14 _prefix = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin" 15 if (host_os == "win") { 16 target_ar = "$_prefix/llvm-ar.exe" 17 target_cc = "$_prefix/clang.exe --target=$ndk_target$ndk_api -fno-addrsig" 18 target_cxx = 19 "$_prefix/clang++.exe --target=$ndk_target$ndk_api -fno-addrsig" 20 } else { 21 target_ar = "$_prefix/llvm-ar" 22 target_cc = "$_prefix/$ndk_target$ndk_api-clang" 23 target_cxx = "$_prefix/$ndk_target$ndk_api-clang++" 24 } 25 } else if (is_fuchsia && using_fuchsia_sdk) { 26 target_ar = rebase_path("$fuchsia_toolchain_path/bin/llvm-ar") 27 target_cc = rebase_path("$fuchsia_toolchain_path/bin/clang") 28 target_cxx = rebase_path("$fuchsia_toolchain_path/bin/clang++") 29 cflags = "--sysroot=" + 30 rebase_path("$fuchsia_toolchain_path/$target_cpu/sysroot") 31 link = rebase_path("$fuchsia_toolchain_path/bin/ld.lld") 32 } else { 33 target_ar = ar 34 target_cc = cc 35 target_cxx = cxx 36 } 37 38 cc_wrapper = "" 39 40 # dsymutil seems to kill the machine when too many processes are run in 41 # parallel, so we need to use a pool to limit the concurrency when passing 42 # large -j to Ninja (e.g. Goma build). Unfortunately this is also one of the 43 # slowest steps in a build, so we don't want to limit too much. Use the number 44 # of CPUs as a default. 45 dlsymutil_pool_depth = exec_script("num_cpus.py", [], "value") 46 47 # Too many linkers running at once causes issues for some builders. Allow 48 # such builders to limit the number of concurrent link steps. 49 # link_pool_depth < 0 means no pool, 0 means cpu count, > 0 sets pool size. 50 link_pool_depth = -1 51} 52 53declare_args() { 54 host_link = host_cxx 55 target_link = target_cxx 56} 57 58# For 'shell' see https://ninja-build.org/manual.html#ref_rule_command 59if (host_os == "win") { 60 shell = "cmd.exe /c " 61 stamp = "$shell echo >" 62} else { 63 shell = "" 64 stamp = "touch" 65} 66 67if (current_toolchain == default_toolchain) { 68 pool("dsymutil_pool") { 69 depth = dlsymutil_pool_depth 70 } 71 if (0 <= link_pool_depth) { 72 pool("link_pool") { 73 if (link_pool_depth == 0) { 74 depth = exec_script("num_cpus.py", [], "value") 75 } else { 76 depth = link_pool_depth 77 } 78 } 79 } 80} 81 82template("msvc_toolchain") { 83 toolchain(target_name) { 84 toolchain_target_cpu = invoker.cpu 85 lib_switch = "" 86 lib_dir_switch = "/LIBPATH:" 87 88 bin = "$win_vc/Tools/MSVC/$win_toolchain_version/bin/HostX64/$toolchain_target_cpu" 89 90 env_setup = "" 91 if (toolchain_target_cpu == "x86") { 92 # Toolchain asset includes a script that configures for x86 building. 93 # We don't support x86 builds with local MSVC installations. 94 env_setup = "$shell $win_sdk/bin/SetEnv.cmd /x86 && " 95 } else if (toolchain_target_cpu == "arm64") { 96 # ARM64 compiler is incomplete - it relies on DLLs located in the host toolchain directory. 97 env_setup = "$shell set \"PATH=%PATH%;$win_vc\\Tools\\MSVC\\$win_toolchain_version\\bin\\HostX64\\x64\" && " 98 } 99 100 cl_m32_flag = "" 101 102 if (clang_win != "") { 103 if (toolchain_target_cpu == "x86") { 104 # cl.exe knows implicitly by the choice of executable that it's targeting 105 # x86, but clang-cl.exe needs to be told when targeting non-host 106 # platforms. (All our builders are x86-64, so x86 is always non-host.) 107 cl_m32_flag = "-m32" 108 } 109 if (host_os == "win") { 110 cl = "\"$clang_win/bin/clang-cl.exe\"" 111 lib = "\"$clang_win/bin/lld-link.exe\" /lib" 112 link = "\"$clang_win/bin/lld-link.exe\"" 113 } else { 114 cl = "\"$clang_win/bin/clang-cl\"" 115 lib = "\"$clang_win/bin/lld-link\" /lib" 116 link = "\"$clang_win/bin/lld-link\"" 117 } 118 } else { 119 cl = "\"$bin/cl.exe\"" 120 lib = "\"$bin/lib.exe\"" 121 link = "\"$bin/link.exe\"" 122 } 123 124 tool("asm") { 125 _ml = "ml" 126 if (toolchain_target_cpu == "x64") { 127 _ml += "64" 128 } 129 command = "$env_setup \"$bin/$_ml.exe\" {{asmflags}} /nologo /c /Fo {{output}} {{source}}" 130 outputs = [ 131 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", 132 ] 133 description = "assemble {{source}}" 134 } 135 136 tool("cc") { 137 precompiled_header_type = "msvc" 138 pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" 139 140 # Label names may have spaces so pdbname must be quoted. 141 command = "$env_setup $cc_wrapper $cl /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} $cl_m32_flag {{cflags_c}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\"" 142 depsformat = "msvc" 143 outputs = [ 144 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", 145 ] 146 description = "compile {{source}}" 147 } 148 149 tool("cxx") { 150 precompiled_header_type = "msvc" 151 pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" 152 153 # Label names may have spaces so pdbname must be quoted. 154 command = "$env_setup $cc_wrapper $cl /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} $cl_m32_flag {{cflags_cc}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\"" 155 depsformat = "msvc" 156 outputs = [ 157 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", 158 ] 159 description = "compile {{source}}" 160 } 161 162 tool("alink") { 163 rspfile = "{{output}}.rsp" 164 165 command = "$env_setup $lib /nologo /ignore:4221 {{arflags}} /OUT:{{output}} @$rspfile" 166 outputs = [ 167 # Ignore {{output_extension}} and always use .lib, there's no reason to 168 # allow targets to override this extension on Windows. 169 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}", 170 ] 171 default_output_extension = ".lib" 172 default_output_dir = "{{target_out_dir}}" 173 174 # inputs_newline works around a fixed per-line buffer size in the linker. 175 rspfile_content = "{{inputs_newline}}" 176 description = "link {{output}}" 177 if (0 <= link_pool_depth) { 178 pool = ":link_pool($default_toolchain)" 179 } 180 } 181 182 tool("solink") { 183 dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 184 libname = "${dllname}.lib" 185 pdbname = "${dllname}.pdb" 186 rspfile = "${dllname}.rsp" 187 188 command = "$env_setup $link /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:$pdbname @$rspfile" 189 outputs = [ 190 dllname, 191 libname, 192 pdbname, 193 ] 194 default_output_extension = ".dll" 195 default_output_dir = "{{root_out_dir}}" 196 197 link_output = libname 198 depend_output = libname 199 runtime_outputs = [ 200 dllname, 201 pdbname, 202 ] 203 204 # I don't quite understand this. Aping Chrome's toolchain/win/BUILD.gn. 205 restat = true 206 207 # inputs_newline works around a fixed per-line buffer size in the linker. 208 rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}" 209 description = "link {{output}}" 210 if (0 <= link_pool_depth) { 211 pool = ":link_pool($default_toolchain)" 212 } 213 } 214 215 tool("link") { 216 exename = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" 217 pdbname = "$exename.pdb" 218 rspfile = "$exename.rsp" 219 220 command = "$env_setup $link /nologo /OUT:$exename /PDB:$pdbname @$rspfile" 221 default_output_extension = ".exe" 222 default_output_dir = "{{root_out_dir}}" 223 outputs = [ exename ] 224 225 # inputs_newline works around a fixed per-line buffer size in the linker. 226 rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}" 227 description = "link {{output}}" 228 if (0 <= link_pool_depth) { 229 pool = ":link_pool($default_toolchain)" 230 } 231 } 232 233 tool("stamp") { 234 command = "$stamp {{output}}" 235 description = "stamp {{output}}" 236 } 237 238 tool("copy") { 239 cp_py = rebase_path("../cp.py") 240 command = "$shell python3 \"$cp_py\" {{source}} {{output}}" 241 description = "copy {{source}} {{output}}" 242 } 243 244 toolchain_args = { 245 current_cpu = invoker.cpu 246 current_os = invoker.os 247 } 248 } 249} 250 251msvc_toolchain("msvc") { 252 cpu = current_cpu 253 os = current_os 254} 255 256msvc_toolchain("msvc_host") { 257 cpu = host_cpu 258 os = host_os 259} 260 261template("gcc_like_toolchain") { 262 toolchain(target_name) { 263 ar = invoker.ar 264 cc = invoker.cc 265 cxx = invoker.cxx 266 link = invoker.link 267 lib_switch = "-l" 268 lib_dir_switch = "-L" 269 270 tool("cc") { 271 depfile = "{{output}}.d" 272 command = "$cc_wrapper $cc -MD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" 273 depsformat = "gcc" 274 outputs = 275 [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] 276 description = "compile {{source}}" 277 } 278 279 tool("cxx") { 280 depfile = "{{output}}.d" 281 command = "$cc_wrapper $cxx -MD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}" 282 depsformat = "gcc" 283 outputs = 284 [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] 285 description = "compile {{source}}" 286 } 287 288 tool("objc") { 289 depfile = "{{output}}.d" 290 command = "$cc_wrapper $cc -MD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}" 291 depsformat = "gcc" 292 outputs = 293 [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] 294 description = "compile {{source}}" 295 } 296 297 tool("objcxx") { 298 depfile = "{{output}}.d" 299 command = "$cc_wrapper $cxx -MD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_objcc}} -c {{source}} -o {{output}}" 300 depsformat = "gcc" 301 outputs = 302 [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] 303 description = "compile {{source}}" 304 } 305 306 tool("asm") { 307 depfile = "{{output}}.d" 308 command = "$cc_wrapper $cc -MD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}" 309 depsformat = "gcc" 310 outputs = 311 [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] 312 description = "assemble {{source}}" 313 } 314 315 if (is_mac || is_ios) { 316 not_needed([ "ar" ]) # We use libtool instead. 317 } 318 319 tool("alink") { 320 if (is_mac || is_ios) { 321 command = "libtool -static -o {{output}} -no_warning_for_no_symbols {{inputs}}" 322 } else { 323 rspfile = "{{output}}.rsp" 324 rspfile_content = "{{inputs}}" 325 rm_py = rebase_path("../rm.py") 326 command = "$shell python3 \"$rm_py\" \"{{output}}\" && $ar rcs {{output}} @$rspfile" 327 } 328 329 outputs = 330 [ "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" ] 331 default_output_extension = ".a" 332 output_prefix = "lib" 333 description = "link {{output}}" 334 if (0 <= link_pool_depth) { 335 pool = ":link_pool($default_toolchain)" 336 } 337 } 338 339 tool("solink") { 340 soname = "{{target_output_name}}{{output_extension}}" 341 342 rpath = "-Wl,-soname,$soname" 343 if (is_mac || is_ios) { 344 rpath = "-Wl,-install_name,@rpath/$soname" 345 } 346 347 rspfile = "{{output}}.rsp" 348 rspfile_content = "{{inputs}}" 349 350 # --start-group/--end-group let us link multiple .a {{inputs}} 351 # without worrying about their relative order on the link line. 352 # 353 # This is mostly important for traditional linkers like GNU ld and Gold. 354 # The Mac/iOS linker neither needs nor accepts these flags. 355 # LLD doesn't need these flags, but accepts and ignores them. 356 _start_group = "-Wl,--start-group" 357 _end_group = "-Wl,--end-group" 358 if (is_mac || is_ios || is_fuchsia) { 359 _start_group = "" 360 _end_group = "" 361 } 362 363 command = "$link -shared {{ldflags}} $_start_group @$rspfile {{frameworks}} {{solibs}} $_end_group {{libs}} $rpath -o {{output}}" 364 outputs = [ "{{root_out_dir}}/$soname" ] 365 output_prefix = "lib" 366 if (is_mac || is_ios) { 367 default_output_extension = ".dylib" 368 } else { 369 default_output_extension = ".so" 370 } 371 description = "link {{output}}" 372 if (0 <= link_pool_depth) { 373 pool = ":link_pool($default_toolchain)" 374 } 375 } 376 377 tool("link") { 378 exe_name = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" 379 rspfile = "$exe_name.rsp" 380 rspfile_content = "{{inputs}}" 381 382 # --start-group/--end-group let us link multiple .a {{inputs}} 383 # without worrying about their relative order on the link line. 384 # 385 # This is mostly important for traditional linkers like GNU ld and Gold. 386 # The Mac/iOS linker neither needs nor accepts these flags. 387 # LLD doesn't need these flags, but accepts and ignores them. 388 _start_group = "-Wl,--start-group" 389 _end_group = "-Wl,--end-group" 390 if (is_mac || is_ios || is_fuchsia) { 391 _start_group = "" 392 _end_group = "" 393 } 394 command = "$link {{ldflags}} $_start_group @$rspfile {{frameworks}} {{solibs}} $_end_group {{libs}} -o $exe_name" 395 396 outputs = [ "$exe_name" ] 397 description = "link {{output}}" 398 if (0 <= link_pool_depth) { 399 pool = ":link_pool($default_toolchain)" 400 } 401 } 402 403 tool("stamp") { 404 command = "$stamp {{output}}" 405 description = "stamp {{output}}" 406 } 407 408 tool("copy") { 409 cp_py = rebase_path("../cp.py") 410 command = "python3 \"$cp_py\" {{source}} {{output}}" 411 description = "copy {{source}} {{output}}" 412 } 413 414 tool("copy_bundle_data") { 415 cp_py = rebase_path("../cp.py") 416 command = "python3 \"$cp_py\" {{source}} {{output}}" 417 description = "copy_bundle_data {{source}} {{output}}" 418 } 419 420 # We don't currently have any xcasset files so make this a NOP 421 tool("compile_xcassets") { 422 command = "true" 423 description = "compile_xcassets {{output}}" 424 } 425 426 toolchain_args = { 427 current_cpu = invoker.cpu 428 current_os = invoker.os 429 } 430 } 431} 432 433gcc_like_toolchain("gcc_like") { 434 cpu = current_cpu 435 os = current_os 436 ar = target_ar 437 cc = target_cc 438 cxx = target_cxx 439 link = target_link 440} 441 442gcc_like_toolchain("gcc_like_host") { 443 cpu = host_cpu 444 os = host_os 445 ar = host_ar 446 cc = host_cc 447 cxx = host_cxx 448 link = host_link 449} 450 451# Only define this toolchain if actually building for wasm. 452if (is_wasm) { 453 gcc_like_toolchain("wasm") { 454 cpu = "wasm" 455 os = "wasm" 456 if (host_os == "win") { 457 ar = "$skia_emsdk_dir/upstream/emscripten/emar.bat" 458 cc = "$skia_emsdk_dir/upstream/emscripten/emcc.bat" 459 cxx = "$skia_emsdk_dir/upstream/emscripten/em++.bat" 460 } else { 461 ar = "$skia_emsdk_dir/upstream/emscripten/emar" 462 cc = "$skia_emsdk_dir/upstream/emscripten/emcc" 463 cxx = "$skia_emsdk_dir/upstream/emscripten/em++" 464 } 465 link = cxx 466 } 467} 468