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