toolchain.gni 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. # Copyright 2022 The Chromium Authors. All rights reserved.
  2. # Use of this source code is governed by a BSD-style license that can be
  3. # found in the LICENSE file.
  4. import("//build/config/clang/clang.gni")
  5. import("//build/config/compiler/compiler.gni")
  6. import("//build/config/rust.gni")
  7. import("//build/config/sanitizers/sanitizers.gni")
  8. import("//build/config/win/visual_studio_version.gni")
  9. import("//build/toolchain/cc_wrapper.gni")
  10. import("//build/toolchain/goma.gni")
  11. import("//build/toolchain/rbe.gni")
  12. import("//build/toolchain/toolchain.gni")
  13. assert(is_win, "Should only be running on Windows")
  14. # This tool will is used as a wrapper for various commands below.
  15. _tool_wrapper_path =
  16. rebase_path("//build/toolchain/win/tool_wrapper.py", root_build_dir)
  17. if (host_os == "win") {
  18. _exe = ".exe"
  19. } else {
  20. _exe = ""
  21. }
  22. _clang_bin_path = rebase_path("$clang_base_path/bin", root_build_dir)
  23. # Parameters:
  24. # environment: File name of environment file.
  25. #
  26. # You would also define a toolchain_args variable with at least these set:
  27. # current_cpu: current_cpu to pass as a build arg
  28. # current_os: current_os to pass as a build arg
  29. template("msvc_toolchain") {
  30. toolchain(target_name) {
  31. # When invoking this toolchain not as the default one, these args will be
  32. # passed to the build. They are ignored when this is the default toolchain.
  33. assert(defined(invoker.toolchain_args))
  34. toolchain_args = {
  35. forward_variables_from(invoker.toolchain_args, "*")
  36. # This value needs to be passed through unchanged.
  37. host_toolchain = host_toolchain
  38. # Respect the global setting for whether rustc can make binaries.
  39. rustc_can_link = rustc_can_link
  40. }
  41. if (defined(toolchain_args.is_clang)) {
  42. toolchain_is_clang = toolchain_args.is_clang
  43. } else {
  44. toolchain_is_clang = is_clang
  45. }
  46. # When the invoker has explicitly overridden use_goma or cc_wrapper in the
  47. # toolchain args, use those values, otherwise default to the global one.
  48. # This works because the only reasonable override that toolchains might
  49. # supply for these values are to force-disable them.
  50. if (defined(toolchain_args.use_remoteexec)) {
  51. toolchain_uses_remoteexec = toolchain_args.use_remoteexec
  52. } else {
  53. toolchain_uses_remoteexec = use_remoteexec
  54. }
  55. if (defined(toolchain_args.use_goma)) {
  56. toolchain_uses_goma = toolchain_args.use_goma
  57. } else {
  58. toolchain_uses_goma = use_goma
  59. }
  60. if (defined(toolchain_args.cc_wrapper)) {
  61. toolchain_cc_wrapper = toolchain_args.cc_wrapper
  62. } else {
  63. toolchain_cc_wrapper = cc_wrapper
  64. }
  65. assert(!(toolchain_uses_remoteexec && toolchain_uses_goma),
  66. "Goma and re-client can't be used together.")
  67. assert(!(toolchain_cc_wrapper != "" && toolchain_uses_remoteexec),
  68. "re-client and cc_wrapper can't be used together.")
  69. assert(!(toolchain_cc_wrapper != "" && toolchain_uses_goma),
  70. "Goma and cc_wrapper can't be used together.")
  71. if (toolchain_uses_remoteexec) {
  72. if (toolchain_is_clang) {
  73. cl_prefix = "${rbe_bin_dir}/rewrapper -cfg=${rbe_cc_cfg_file} -exec_root=${rbe_exec_root} "
  74. } else {
  75. cl_prefix = ""
  76. }
  77. } else if (toolchain_uses_goma) {
  78. cl_prefix = "${goma_dir}/gomacc${_exe} "
  79. } else if (toolchain_cc_wrapper != "" && toolchain_is_clang) {
  80. cl_prefix = toolchain_cc_wrapper + " "
  81. } else {
  82. cl_prefix = ""
  83. }
  84. cl = "${cl_prefix}${invoker.cl}"
  85. if (host_os == "win") {
  86. # Flip the slashes so that copy/paste of the command works.
  87. cl = string_replace(cl, "/", "\\")
  88. }
  89. # Make these apply to all tools below.
  90. lib_switch = ""
  91. lib_dir_switch = "/LIBPATH:"
  92. # Object files go in this directory.
  93. object_subdir = "{{target_out_dir}}/{{label_name}}"
  94. env = invoker.environment
  95. if (use_lld) {
  96. # lld-link includes a replacement for lib.exe that can produce thin
  97. # archives and understands bitcode (for lto builds).
  98. link = "${_clang_bin_path}/lld-link${_exe}"
  99. if (host_os == "win") {
  100. # Flip the slashes so that copy/paste of the commands works.
  101. link = string_replace(link, "/", "\\")
  102. }
  103. lib = "$link /lib"
  104. if (host_os != "win") {
  105. # See comment adding --rsp-quoting to $cl above for more information.
  106. link = "$link --rsp-quoting=posix"
  107. }
  108. } else {
  109. lib = "lib.exe"
  110. link = "link.exe"
  111. }
  112. # If possible, pass system includes as flags to the compiler. When that's
  113. # not possible, load a full environment file (containing %INCLUDE% and
  114. # %PATH%) -- e.g. 32-bit MSVS builds require %PATH% to be set and just
  115. # passing in a list of include directories isn't enough.
  116. if (defined(invoker.sys_include_flags)) {
  117. env_wrapper = ""
  118. sys_include_flags =
  119. "${invoker.sys_include_flags} " # Note trailing space.
  120. } else {
  121. # clang-cl doesn't need this env hoop, so omit it there.
  122. assert(!toolchain_is_clang)
  123. env_wrapper = "ninja -t msvc -e $env -- " # Note trailing space.
  124. sys_include_flags = ""
  125. }
  126. if (host_os != "win" || (use_lld && defined(invoker.sys_lib_flags))) {
  127. linker_wrapper = ""
  128. sys_lib_flags = "${invoker.sys_lib_flags} " # Note trailing space.
  129. } else {
  130. # link.exe must be run under a wrapper to set up the environment
  131. # (it needs %LIB% set to find libraries), and to work around its bugs.
  132. # Note trailing space:
  133. linker_wrapper =
  134. "$python_path $_tool_wrapper_path link-wrapper $env False "
  135. sys_lib_flags = ""
  136. }
  137. if (defined(toolchain_args.use_clang_coverage)) {
  138. toolchain_use_clang_coverage = toolchain_args.use_clang_coverage
  139. } else {
  140. toolchain_use_clang_coverage = use_clang_coverage
  141. }
  142. if (toolchain_use_clang_coverage) {
  143. assert(toolchain_is_clang,
  144. "use_clang_coverage should only be used with Clang")
  145. if (defined(toolchain_args.coverage_instrumentation_input_file)) {
  146. toolchain_coverage_instrumentation_input_file =
  147. toolchain_args.coverage_instrumentation_input_file
  148. } else {
  149. toolchain_coverage_instrumentation_input_file =
  150. coverage_instrumentation_input_file
  151. }
  152. coverage_wrapper =
  153. rebase_path("//build/toolchain/clang_code_coverage_wrapper.py",
  154. root_build_dir)
  155. coverage_wrapper = coverage_wrapper + " --target-os=" + target_os
  156. if (toolchain_coverage_instrumentation_input_file != "") {
  157. coverage_wrapper =
  158. coverage_wrapper + " --files-to-instrument=" +
  159. rebase_path(toolchain_coverage_instrumentation_input_file,
  160. root_build_dir)
  161. }
  162. coverage_wrapper = "$python_path " + coverage_wrapper + " "
  163. } else {
  164. coverage_wrapper = ""
  165. }
  166. # Disabled with cc_wrapper because of
  167. # https://github.com/mozilla/sccache/issues/1013
  168. if (toolchain_is_clang && toolchain_cc_wrapper == "") {
  169. # This flag omits system includes from /showIncludes output, to reduce
  170. # the amount of data to parse and store in .ninja_deps. We do this on
  171. # non-Windows too, and already make sure rebuilds after winsdk/libc++/
  172. # clang header updates happen via changing command line flags.
  173. show_includes = "/showIncludes:user"
  174. } else {
  175. show_includes = "/showIncludes"
  176. }
  177. tool("cc") {
  178. precompiled_header_type = "msvc"
  179. pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
  180. # Label names may have spaces in them so the pdbname must be quoted. The
  181. # source and output don't need to be quoted because GN knows they're a
  182. # full file name and will quote automatically when necessary.
  183. depsformat = "msvc"
  184. description = "CC {{output}}"
  185. outputs = [ "$object_subdir/{{source_name_part}}.obj" ]
  186. # Note that the code coverage wrapper scripts assumes that {{source}}
  187. # comes immediately after /c.
  188. command = "$coverage_wrapper$env_wrapper$cl /c {{source}} /nologo $show_includes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} /Fo{{output}} /Fd\"$pdbname\""
  189. }
  190. tool("cxx") {
  191. precompiled_header_type = "msvc"
  192. # The PDB name needs to be different between C and C++ compiled files.
  193. pdbname = "{{target_out_dir}}/{{label_name}}_cc.pdb"
  194. # See comment in CC tool about quoting.
  195. depsformat = "msvc"
  196. description = "CXX {{output}}"
  197. outputs = [ "$object_subdir/{{source_name_part}}.obj" ]
  198. # Note that the code coverage wrapper scripts assumes that {{source}}
  199. # comes immediately after /c.
  200. command = "$coverage_wrapper$env_wrapper$cl /c {{source}} /Fo{{output}} /nologo $show_includes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} /Fd\"$pdbname\""
  201. }
  202. tool("rc") {
  203. command = "$python_path $_tool_wrapper_path rc-wrapper $env rc.exe /nologo $sys_include_flags{{defines}} {{include_dirs}} /fo{{output}} {{source}}"
  204. depsformat = "msvc"
  205. outputs = [ "$object_subdir/{{source_name_part}}.res" ]
  206. description = "RC {{output}}"
  207. }
  208. tool("asm") {
  209. is_msvc_assembler = true
  210. if (toolchain_args.current_cpu == "arm64") {
  211. if (toolchain_is_clang) {
  212. ml = "${cl_prefix}${_clang_bin_path}/clang-cl${_exe} --target=arm64-windows"
  213. if (host_os == "win") {
  214. # Flip the slashes so that copy/paste of the command works.
  215. ml = string_replace(ml, "/", "\\")
  216. }
  217. ml += " -c -o{{output}}"
  218. is_msvc_assembler = false
  219. } else {
  220. # Only affects Arm builds with is_clang = false, implemented for
  221. # building V8 for Windows on Arm systems with the MSVC toolchain.
  222. ml = "armasm64.exe"
  223. }
  224. } else {
  225. if (toolchain_is_clang) {
  226. prefix = rebase_path("$clang_base_path/bin", root_build_dir)
  227. ml = "$prefix/llvm-ml${_exe}"
  228. if (toolchain_args.current_cpu == "x64") {
  229. ml += " -m64"
  230. } else {
  231. ml += " -m32"
  232. }
  233. } else {
  234. if (toolchain_args.current_cpu == "x64") {
  235. ml = "ml64.exe"
  236. } else {
  237. ml = "ml.exe"
  238. }
  239. }
  240. }
  241. if (is_msvc_assembler) {
  242. ml += " /nologo /Fo{{output}}"
  243. # Suppress final-stage linking on x64/x86 builds. (Armasm64 does not
  244. # require /c because it doesn't support linking.)
  245. if (toolchain_args.current_cpu != "arm64") {
  246. ml += " /c"
  247. }
  248. if (use_lld && !toolchain_is_clang) {
  249. # Wrap ml(64).exe with a script that makes its output deterministic.
  250. # It's lld only because the script zaps obj Timestamp which
  251. # link.exe /incremental looks at.
  252. ml_py = rebase_path("//build/toolchain/win/ml.py", root_build_dir)
  253. ml = "$python_path $ml_py $ml"
  254. }
  255. }
  256. if (toolchain_args.current_cpu != "arm64" || toolchain_is_clang) {
  257. # TODO(thakis): Stop using asm-wrapper when using clang.
  258. command = "$python_path $_tool_wrapper_path asm-wrapper $env $ml {{defines}} {{include_dirs}} {{asmflags}} {{source}}"
  259. } else {
  260. # armasm64.exe does not support definitions passed via the command
  261. # line. (Fortunately, they're not needed for compiling the V8
  262. # snapshot, which is the only time this assembler is required.)
  263. command = "$python_path $_tool_wrapper_path asm-wrapper $env $ml {{include_dirs}} {{asmflags}} {{source}}"
  264. }
  265. description = "ASM {{output}}"
  266. outputs = [ "$object_subdir/{{source_name_part}}.obj" ]
  267. }
  268. if (toolchain_has_rust) {
  269. rustc_wrapper = rebase_path("//build/rust/rustc_wrapper.py")
  270. # TODO(https://crbug.com/1271215)
  271. # Other toolchains (Linux, Mac) pass {{ldflags}} to rustc.
  272. # This is necessary for some types of build such as
  273. # LTO and sanitizers. However, such ldflags are not yet fully
  274. # compatible with the arguments passed from rustc to the linker,
  275. # so we'll do this at a later stage.
  276. rustc = rebase_path("${rust_sysroot}/bin/rustc", root_build_dir)
  277. rust_sysroot_relative_to_out = rebase_path(rust_sysroot, root_out_dir)
  278. tool("rust_staticlib") {
  279. rust_outfile = "{{output_dir}}/{{target_output_name}}.lib"
  280. depfile = "{{output}}.d"
  281. rspfile = "$rust_outfile.rsp"
  282. rspfile_content = "{{rustdeps}} {{externs}}"
  283. command = "$python_path \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_common_args --emit=dep-info=$depfile,link -o $rust_outfile LDFLAGS RUSTENV {{rustenv}}"
  284. description = "RUST $rust_outfile"
  285. rust_sysroot = rust_sysroot_relative_to_out
  286. outputs = [ rust_outfile ]
  287. }
  288. tool("rust_rlib") {
  289. rust_outfile = "{{output_dir}}/lib{{target_output_name}}.rlib"
  290. depfile = "{{output}}.d"
  291. # Do not use rsp files in this (common) case because they occupy the
  292. # ninja main thread, and {{rlibs}} have shorter command lines than
  293. # fully linked targets.
  294. command = "$python_path \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile -- $rustc_common_args --emit=dep-info=$depfile,link -o $rust_outfile {{rustdeps}} {{externs}} LDFLAGS RUSTENV {{rustenv}}"
  295. description = "RUST $rust_outfile"
  296. rust_sysroot = rust_sysroot_relative_to_out
  297. outputs = [ rust_outfile ]
  298. }
  299. if (toolchain_args.rustc_can_link) {
  300. tool("rust_bin") {
  301. rust_outfile = "{{root_out_dir}}/{{target_output_name}}.exe"
  302. depfile = "{{output}}.d"
  303. rspfile = "$rust_outfile.rsp"
  304. rspfile_content = "{{rustdeps}} {{externs}}"
  305. command = "$python_path \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_common_args --emit=dep-info=$depfile,link -o $rust_outfile LDFLAGS RUSTENV {{rustenv}}"
  306. description = "RUST $rust_outfile"
  307. rust_sysroot = rust_sysroot_relative_to_out
  308. outputs = [ rust_outfile ]
  309. }
  310. tool("rust_cdylib") {
  311. rust_outfile = "{{output_dir}}/lib{{target_output_name}}.dll"
  312. depfile = "{{output}}.d"
  313. rspfile = "$rust_outfile.rsp"
  314. rspfile_content = "{{rustdeps}} {{externs}}"
  315. command = "$python_path \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_common_args --emit=dep-info=$depfile,link -o $rust_outfile LDFLAGS RUSTENV {{rustenv}}"
  316. description = "RUST $rust_outfile"
  317. rust_sysroot = rust_sysroot_relative_to_out
  318. outputs = [ rust_outfile ]
  319. }
  320. tool("rust_macro") {
  321. rust_outfile = "{{output_dir}}/{{target_output_name}}.dll"
  322. depfile = "{{output}}.d"
  323. rspfile = "$rust_outfile.rsp"
  324. rspfile_content = "{{rustdeps}} {{externs}}"
  325. command = "$python_path \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_common_args --emit=dep-info=$depfile,link -o $rust_outfile LDFLAGS RUSTENV {{rustenv}}"
  326. description = "RUST $rust_outfile"
  327. rust_sysroot = rust_sysroot_relative_to_out
  328. outputs = [ rust_outfile ]
  329. }
  330. }
  331. }
  332. tool("alink") {
  333. rspfile = "{{output}}.rsp"
  334. command =
  335. "$linker_wrapper$lib /OUT:{{output}} /nologo {{arflags}} @$rspfile"
  336. description = "LIB {{output}}"
  337. outputs = [
  338. # Ignore {{output_extension}} and always use .lib, there's no reason to
  339. # allow targets to override this extension on Windows.
  340. "{{output_dir}}/{{target_output_name}}.lib",
  341. ]
  342. default_output_extension = ".lib"
  343. default_output_dir = "{{target_out_dir}}"
  344. # The use of inputs_newline is to work around a fixed per-line buffer
  345. # size in the linker.
  346. rspfile_content = "{{inputs_newline}}"
  347. }
  348. tool("solink") {
  349. # E.g. "foo.dll":
  350. dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
  351. libname = "${dllname}.lib" # e.g. foo.dll.lib
  352. pdbname = "${dllname}.pdb"
  353. rspfile = "${dllname}.rsp"
  354. pool = "//build/toolchain:link_pool($default_toolchain)"
  355. command = "$linker_wrapper$link /OUT:$dllname /nologo ${sys_lib_flags}/IMPLIB:$libname /DLL /PDB:$pdbname @$rspfile"
  356. default_output_extension = ".dll"
  357. default_output_dir = "{{root_out_dir}}"
  358. description = "LINK(DLL) {{output}}"
  359. outputs = [
  360. dllname,
  361. libname,
  362. pdbname,
  363. ]
  364. link_output = libname
  365. depend_output = libname
  366. runtime_outputs = [
  367. dllname,
  368. pdbname,
  369. ]
  370. # Since the above commands only updates the .lib file when it changes,
  371. # ask Ninja to check if the timestamp actually changed to know if
  372. # downstream dependencies should be recompiled.
  373. restat = true
  374. # The use of inputs_newline is to work around a fixed per-line buffer
  375. # size in the linker.
  376. rspfile_content =
  377. "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}} {{rlibs}}"
  378. }
  379. tool("solink_module") {
  380. # E.g. "foo.dll":
  381. dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
  382. pdbname = "${dllname}.pdb"
  383. rspfile = "${dllname}.rsp"
  384. pool = "//build/toolchain:link_pool($default_toolchain)"
  385. command = "$linker_wrapper$link /OUT:$dllname /nologo ${sys_lib_flags}/DLL /PDB:$pdbname @$rspfile"
  386. default_output_extension = ".dll"
  387. default_output_dir = "{{root_out_dir}}"
  388. description = "LINK_MODULE(DLL) {{output}}"
  389. outputs = [
  390. dllname,
  391. pdbname,
  392. ]
  393. runtime_outputs = outputs
  394. # The use of inputs_newline is to work around a fixed per-line buffer
  395. # size in the linker.
  396. rspfile_content =
  397. "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}} {{rlibs}}"
  398. }
  399. tool("link") {
  400. exename = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
  401. pdbname = "$exename.pdb"
  402. rspfile = "$exename.rsp"
  403. pool = "//build/toolchain:link_pool($default_toolchain)"
  404. command = "$linker_wrapper$link /OUT:$exename /nologo ${sys_lib_flags} /PDB:$pdbname @$rspfile"
  405. default_output_extension = ".exe"
  406. default_output_dir = "{{root_out_dir}}"
  407. description = "LINK {{output}}"
  408. outputs = [
  409. exename,
  410. pdbname,
  411. ]
  412. runtime_outputs = outputs
  413. # The use of inputs_newline is to work around a fixed per-line buffer
  414. # size in the linker.
  415. rspfile_content =
  416. "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}} {{rlibs}}"
  417. }
  418. # These two are really entirely generic, but have to be repeated in
  419. # each toolchain because GN doesn't allow a template to be used here.
  420. # See //build/toolchain/toolchain.gni for details.
  421. tool("stamp") {
  422. command = stamp_command
  423. description = stamp_description
  424. pool = "//build/toolchain:action_pool($default_toolchain)"
  425. }
  426. tool("copy") {
  427. command = copy_command
  428. description = copy_description
  429. pool = "//build/toolchain:action_pool($default_toolchain)"
  430. }
  431. tool("action") {
  432. pool = "//build/toolchain:action_pool($default_toolchain)"
  433. }
  434. }
  435. }
  436. template("win_toolchains") {
  437. assert(defined(invoker.toolchain_arch))
  438. toolchain_arch = invoker.toolchain_arch
  439. win_toolchain_data = exec_script("//build/toolchain/win/setup_toolchain.py",
  440. [
  441. visual_studio_path,
  442. windows_sdk_path,
  443. visual_studio_runtime_dirs,
  444. "win",
  445. toolchain_arch,
  446. "environment." + toolchain_arch,
  447. ],
  448. "scope")
  449. # The toolchain using MSVC only makes sense when not doing cross builds.
  450. # Chromium exclusively uses the win_clang_ toolchain below, but V8 and
  451. # WebRTC still use this MSVC toolchain in some cases.
  452. if (host_os == "win") {
  453. if (defined(invoker.cl_toolchain_prefix)) {
  454. cl_toolchain_prefix = invoker.cl_toolchain_prefix
  455. } else {
  456. cl_toolchain_prefix = ""
  457. }
  458. msvc_toolchain(cl_toolchain_prefix + target_name) {
  459. environment = "environment." + toolchain_arch
  460. cl = "\"${win_toolchain_data.vc_bin_dir}/cl.exe\""
  461. toolchain_args = {
  462. if (defined(invoker.toolchain_args)) {
  463. forward_variables_from(invoker.toolchain_args, "*")
  464. }
  465. is_clang = false
  466. use_clang_coverage = false
  467. current_os = "win"
  468. current_cpu = toolchain_arch
  469. }
  470. }
  471. }
  472. if (defined(invoker.clang_toolchain_prefix)) {
  473. clang_toolchain_prefix = invoker.clang_toolchain_prefix
  474. } else {
  475. clang_toolchain_prefix = "win_clang_"
  476. }
  477. msvc_toolchain(clang_toolchain_prefix + target_name) {
  478. environment = "environment." + toolchain_arch
  479. cl = "${_clang_bin_path}/clang-cl${_exe}"
  480. _clang_lib_dir =
  481. rebase_path("$clang_base_path/lib/clang/$clang_version/lib/windows",
  482. root_build_dir)
  483. if (host_os == "win") {
  484. # And to match the other -libpath flags.
  485. _clang_lib_dir = string_replace(_clang_lib_dir, "/", "\\")
  486. }
  487. sys_include_flags = "${win_toolchain_data.include_flags_imsvc}"
  488. if (use_lld) {
  489. sys_lib_flags =
  490. "-libpath:$_clang_lib_dir ${win_toolchain_data.libpath_lldlink_flags}"
  491. # TODO(thakis): Remove once crbug.com/1300005 is fixed
  492. assert(toolchain_arch == "x64" || toolchain_arch == "x86" ||
  493. toolchain_arch == "arm" || toolchain_arch == "arm64",
  494. "Only supports x64, x86, arm and arm64 CPUs")
  495. if (toolchain_arch == "x64") {
  496. sys_lib_flags += " /MACHINE:X64"
  497. } else if (toolchain_arch == "x86") {
  498. sys_lib_flags += " /MACHINE:X86"
  499. } else if (toolchain_arch == "arm") {
  500. sys_lib_flags += " /MACHINE:ARM"
  501. } else if (toolchain_arch == "arm64") {
  502. sys_lib_flags += " /MACHINE:ARM64"
  503. }
  504. }
  505. toolchain_args = {
  506. if (defined(invoker.toolchain_args)) {
  507. forward_variables_from(invoker.toolchain_args, "*")
  508. }
  509. is_clang = true
  510. current_os = "win"
  511. current_cpu = toolchain_arch
  512. }
  513. }
  514. }