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