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