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