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