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