• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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