[M120 Migration][Gamepad]Add gamepad event latency Test code
[platform/framework/web/chromium-efl.git] / build / toolchain / gcc_toolchain.gni
1 # Copyright 2013 The Chromium Authors
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import("//build/config/clang/clang.gni")
6 import("//build/config/compiler/compiler.gni")
7 import("//build/config/coverage/coverage.gni")
8 import("//build/config/rust.gni")
9 import("//build/config/sanitizers/sanitizers.gni")
10 import("//build/config/v8_target_cpu.gni")
11 import("//build/toolchain/cc_wrapper.gni")
12 import("//build/toolchain/goma.gni")
13 import("//build/toolchain/rbe.gni")
14 import("//build/toolchain/toolchain.gni")
15
16 if (is_nacl) {
17   # To keep NaCl variables out of builds that don't include NaCl, all
18   # variables defined in nacl/config.gni referenced here should be protected by
19   # is_nacl conditions.
20   import("//build/config/nacl/config.gni")
21 }
22
23 declare_args() {
24   # Enables allowlist generation for IDR_ grit defines seen by the compiler.
25   # Currently works only on some platforms and enabled by default for official
26   # builds. Requires debug info.
27   enable_resource_allowlist_generation =
28       is_official_build &&
29       # Don't enable for Android-on-Chrome OS.
30       (target_os == "android" || target_os == "win")
31
32   # Use -MD instead of -MMD for compiler commands. This is useful for tracking
33   # the comprehensive set of dependencies.
34   system_headers_in_deps = false
35 }
36
37 # When the arg is set via args.gn, it applies to all toolchains. In order to not
38 # hit the assert in grit_rule.gni, explicitly disable for host toolchains.
39 if ((is_linux || is_chromeos) && target_os == "android") {
40   enable_resource_allowlist_generation = false
41 }
42
43 # Ensure enable_resource_allowlist_generation is enabled only when it will work.
44 if (enable_resource_allowlist_generation) {
45   assert(
46       !strip_debug_info,
47       "enable_resource_allowlist_generation=true requires strip_debug_info=false")
48   assert(
49       !is_component_build,
50       "enable_resource_allowlist_generation=true requires is_component_build=false")
51   assert(
52       target_os == "android" || target_os == "win",
53       "enable_resource_allowlist_generation=true does not work for target_os=$target_os")
54 }
55
56 # This template defines a toolchain for something that works like gcc
57 # (including clang).
58 #
59 # It requires the following variables specifying the executables to run:
60 #  - ar
61 #  - cc
62 #  - cxx
63 #  - ld
64 #
65 # Optional parameters that control the tools:
66 #
67 #  - extra_cflags
68 #      Extra flags to be appended when compiling C files (but not C++ files).
69 #  - extra_cppflags
70 #      Extra flags to be appended when compiling both C and C++ files. "CPP"
71 #      stands for "C PreProcessor" in this context, although it can be
72 #      used for non-preprocessor flags as well. Not to be confused with
73 #      "CXX" (which follows).
74 #  - extra_cxxflags
75 #      Extra flags to be appended when compiling C++ files (but not C files).
76 #  - extra_asmflags
77 #      Extra flags to be appended when compiling assembly.
78 #  - extra_ldflags
79 #      Extra flags to be appended when linking
80 #
81 #  - link_outputs
82 #      The content of this array, if specified, will be added to the list of
83 #      outputs from the link command. This can be useful in conjunction with
84 #      the post_link parameter.
85 #  - use_unstripped_as_runtime_outputs
86 #      When |strip| is set, mark unstripped executables as runtime deps rather
87 #      than stripped ones.
88 #  - post_link
89 #      The content of this string, if specified, will be run as a separate
90 #      command following the the link command.
91 #  - deps
92 #      Just forwarded to the toolchain definition.
93 #  - executable_extension
94 #      If this string is specified it will be used for the file extension
95 #      for an executable, rather than using no extension; targets will
96 #      still be able to override the extension using the output_extension
97 #      variable.
98 #  - rebuild_define
99 #      The contents of this string, if specified, will be passed as a #define
100 #      to the toolchain. It can be used to force recompiles whenever a
101 #      toolchain is updated.
102 #  - shlib_extension
103 #      If this string is specified it will be used for the file extension
104 #      for a shared library, rather than default value specified in
105 #      toolchain.gni
106 #  - strip
107 #      Location of the strip executable. When specified, strip will be run on
108 #      all shared libraries and executables as they are built. The pre-stripped
109 #      artifacts will be put in lib.unstripped/ and exe.unstripped/.
110 #
111 # Callers will normally want to invoke "gcc_toolchain" instead, which makes an
112 # additional toolchain for Rust targets that are build-time artificts such as
113 # proc macros.
114 template("single_gcc_toolchain") {
115   toolchain(target_name) {
116     assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ar\" value")
117     assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value")
118     assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value")
119     assert(defined(invoker.ld), "gcc_toolchain() must specify a \"ld\" value")
120
121     # This define changes when the toolchain changes, forcing a rebuild.
122     # Nothing should ever use this define.
123     if (defined(invoker.rebuild_define)) {
124       rebuild_string = "-D" + invoker.rebuild_define + " "
125     } else {
126       rebuild_string = ""
127     }
128
129     # GN's syntax can't handle more than one scope dereference at once, like
130     # "invoker.toolchain_args.foo", so make a temporary to hold the toolchain
131     # args so we can do "invoker_toolchain_args.foo".
132     assert(defined(invoker.toolchain_args),
133            "Toolchains must specify toolchain_args")
134     invoker_toolchain_args = invoker.toolchain_args
135     assert(defined(invoker_toolchain_args.current_cpu),
136            "toolchain_args must specify a current_cpu")
137     assert(defined(invoker_toolchain_args.current_os),
138            "toolchain_args must specify a current_os")
139
140     # When invoking this toolchain not as the default one, these args will be
141     # passed to the build. They are ignored when this is the default toolchain.
142     toolchain_args = {
143       # Populate toolchain args from the invoker.
144       forward_variables_from(invoker_toolchain_args, "*")
145
146       # The host toolchain value computed by the default toolchain's setup
147       # needs to be passed through unchanged to all secondary toolchains to
148       # ensure that it's always the same, regardless of the values that may be
149       # set on those toolchains.
150       host_toolchain = host_toolchain
151
152       if (!defined(invoker_toolchain_args.v8_current_cpu)) {
153         v8_current_cpu = invoker_toolchain_args.current_cpu
154       }
155     }
156
157     # When the invoker has explicitly overridden use_remoteexec, use_goma or
158     # cc_wrapper in the toolchain args, use those values, otherwise default
159     # to the global one.  This works because the only reasonable override
160     # that toolchains might supply for these values are to force-disable them.
161     if (defined(toolchain_args.use_remoteexec)) {
162       toolchain_uses_remoteexec = toolchain_args.use_remoteexec
163     } else {
164       toolchain_uses_remoteexec = use_remoteexec
165     }
166     if (defined(toolchain_args.use_remoteexec_links)) {
167       toolchain_uses_remoteexec_links = toolchain_args.use_remoteexec_links
168     } else {
169       toolchain_uses_remoteexec_links = use_remoteexec_links
170     }
171     if (defined(toolchain_args.use_goma)) {
172       toolchain_uses_goma = toolchain_args.use_goma
173     } else {
174       toolchain_uses_goma = use_goma
175     }
176
177     # x86_64-nacl-* is ELF-32 and Goma/RBE won't support ELF-32.
178     if (toolchain_uses_goma &&
179         get_path_info(invoker.cc, "name") == "x86_64-nacl-gcc") {
180       # it will also disable x86_64-nacl-g++ since these are in
181       # the same toolchain.
182       toolchain_uses_goma = false
183     }
184     if (defined(toolchain_args.cc_wrapper)) {
185       toolchain_cc_wrapper = toolchain_args.cc_wrapper
186     } else {
187       toolchain_cc_wrapper = cc_wrapper
188     }
189     assert(!(toolchain_uses_remoteexec && toolchain_uses_goma),
190            "Goma and re-client can't be used together.")
191     assert(!(toolchain_cc_wrapper != "" && toolchain_uses_remoteexec),
192            "re-client and cc_wrapper can't be used together.")
193     assert(!(toolchain_cc_wrapper != "" && toolchain_uses_goma),
194            "Goma and cc_wrapper can't be used together.")
195
196     # When the invoker has explicitly overridden use_goma or cc_wrapper in the
197     # toolchain args, use those values, otherwise default to the global one.
198     # This works because the only reasonable override that toolchains might
199     # supply for these values are to force-disable them.
200     # But if needs_gomacc_path_arg is set in a Chrome OS build, the toolchain
201     # wrapper will have picked up gomacc via cmd-line arg. So need to prepend
202     # gomacc in that case.
203     goma_path = "$goma_dir/gomacc"
204     if (toolchain_uses_remoteexec && (!defined(invoker.needs_gomacc_path_arg) ||
205                                       !invoker.needs_gomacc_path_arg)) {
206       if (defined(toolchain_args.rbe_cc_cfg_file)) {
207         toolchain_rbe_cc_cfg_file = toolchain_args.rbe_cc_cfg_file
208       } else {
209         toolchain_rbe_cc_cfg_file = rbe_cc_cfg_file
210       }
211
212       # C/C++ (clang) rewrapper prefix to use when use_remoteexec is true.
213       compiler_prefix = "${rbe_bin_dir}/rewrapper -cfg=${toolchain_rbe_cc_cfg_file} -exec_root=${rbe_exec_root} "
214     } else if (toolchain_uses_goma &&
215                (!defined(invoker.needs_gomacc_path_arg) ||
216                 !invoker.needs_gomacc_path_arg)) {
217       compiler_prefix = "${goma_path} "
218       if (use_goma_rust) {
219         rust_compiler_prefix = compiler_prefix
220       }
221     } else {
222       compiler_prefix = "${toolchain_cc_wrapper} "
223
224       # Prevent warning about unused variable since it is not read in the code
225       # paths when goma is not needed.
226       not_needed(invoker, [ "needs_gomacc_path_arg" ])
227     }
228
229     if (toolchain_uses_remoteexec_links) {
230       if (defined(toolchain_args.rbe_link_cfg_file)) {
231         toolchain_rbe_link_cfg_file = toolchain_args.rbe_link_cfg_file
232       } else {
233         toolchain_rbe_link_cfg_file = rbe_link_cfg_file
234       }
235       link_prefix = "${rbe_bin_dir}/rewrapper -cfg=${toolchain_rbe_link_cfg_file} -exec_root=${rbe_exec_root} "
236       not_needed([ "goma_path" ])
237     } else if (use_goma_thin_lto && toolchain_uses_goma && use_thin_lto) {
238       # remote_ld.py uses autoninja in an attempt to set a reasonable
239       # number of jobs, but this results in too low a value on
240       # Chrome OS builders. So we pass in an explicit value.
241       link_prefix =
242           "\"$python_path\" " +
243           rebase_path("//tools/clang/scripts/remote_ld.py", root_build_dir) +
244           " --wrapper ${goma_path} --jobs 200 --ar-path ${invoker.ar} -- "
245     } else {
246       link_prefix = ""
247       not_needed([ "goma_path" ])
248     }
249
250     # A specific toolchain may wish to avoid coverage instrumentation, so we
251     # allow the global "use_clang_coverage" arg to be overridden.
252     if (defined(toolchain_args.use_clang_coverage)) {
253       toolchain_use_clang_coverage = toolchain_args.use_clang_coverage
254     } else {
255       toolchain_use_clang_coverage = use_clang_coverage
256     }
257
258     # For a coverage build, we use the wrapper script globally so that it can
259     # remove coverage cflags from files that should not have them.
260     if (toolchain_use_clang_coverage) {
261       # "coverage_instrumentation_input_file" is set in args.gn, but it can be
262       # overridden by a toolchain config.
263       if (defined(toolchain_args.coverage_instrumentation_input_file)) {
264         toolchain_coverage_instrumentation_input_file =
265             toolchain_args.coverage_instrumentation_input_file
266       } else {
267         toolchain_coverage_instrumentation_input_file =
268             coverage_instrumentation_input_file
269       }
270
271       _coverage_wrapper =
272           rebase_path("//build/toolchain/clang_code_coverage_wrapper.py",
273                       root_build_dir)
274
275       # The wrapper needs to know what OS we target because it uses that to
276       # select a list of files that should not be instrumented.
277       _coverage_wrapper = _coverage_wrapper + " --target-os=" +
278                           invoker_toolchain_args.current_os
279
280       # We want to instrument everything if there is no input file set.
281       # If there is a file we need to give it to the wrapper script so it can
282       # instrument only those files.
283       if (toolchain_coverage_instrumentation_input_file != "") {
284         _coverage_wrapper =
285             _coverage_wrapper + " --files-to-instrument=" +
286             rebase_path(toolchain_coverage_instrumentation_input_file,
287                         root_build_dir)
288       }
289       compiler_prefix =
290           "\"$python_path\" ${_coverage_wrapper} " + compiler_prefix
291     }
292
293     cc = compiler_prefix + invoker.cc
294     cxx = compiler_prefix + invoker.cxx
295
296     # "asm" doesn't support any of toolchain_cc_wrapper, toolchain_uses_goma and
297     # toolchain_uses_remoteexec. The coverage flags are also nonsensical on
298     # assembler runs.
299     asm = invoker.cc
300     ar = invoker.ar
301     ld = link_prefix + invoker.ld
302     if (defined(invoker.readelf)) {
303       readelf = invoker.readelf
304     } else {
305       readelf = "readelf"
306     }
307     if (defined(invoker.nm)) {
308       nm = invoker.nm
309     } else {
310       nm = "nm"
311     }
312     if (defined(invoker.dwp)) {
313       dwp_switch = " --dwp=\"${invoker.dwp}\""
314     } else {
315       dwp_switch = ""
316     }
317
318     if (defined(invoker.shlib_extension)) {
319       default_shlib_extension = invoker.shlib_extension
320     } else {
321       default_shlib_extension = shlib_extension
322     }
323
324     if (defined(invoker.default_shlib_subdir)) {
325       default_shlib_subdir = invoker.default_shlib_subdir
326     } else {
327       default_shlib_subdir = ""
328     }
329
330     if (defined(invoker.executable_extension)) {
331       default_executable_extension = invoker.executable_extension
332     } else {
333       default_executable_extension = ""
334     }
335
336     # Bring these into our scope for string interpolation with default values.
337     if (defined(invoker.extra_cflags) && invoker.extra_cflags != "") {
338       extra_cflags = " " + invoker.extra_cflags
339     } else {
340       extra_cflags = ""
341     }
342
343     if (defined(invoker.extra_cppflags) && invoker.extra_cppflags != "") {
344       extra_cppflags = " " + invoker.extra_cppflags
345     } else {
346       extra_cppflags = ""
347     }
348
349     if (defined(invoker.extra_cxxflags) && invoker.extra_cxxflags != "") {
350       extra_cxxflags = " " + invoker.extra_cxxflags
351     } else {
352       extra_cxxflags = ""
353     }
354
355     if (defined(invoker.extra_asmflags) && invoker.extra_asmflags != "") {
356       extra_asmflags = " " + invoker.extra_asmflags
357     } else {
358       extra_asmflags = ""
359     }
360
361     if (defined(invoker.extra_ldflags) && invoker.extra_ldflags != "") {
362       extra_ldflags = " " + invoker.extra_ldflags
363     } else {
364       extra_ldflags = ""
365     }
366
367     if (system_headers_in_deps) {
368       md = "-MD"
369     } else {
370       md = "-MMD"
371     }
372
373     enable_linker_map = defined(invoker.enable_linker_map) &&
374                         invoker.enable_linker_map && generate_linker_map
375
376     # These library switches can apply to all tools below.
377     lib_switch = "-l"
378     lib_dir_switch = "-L"
379
380     # Object files go in this directory.
381     object_subdir = "{{target_out_dir}}/{{label_name}}"
382
383     tool("cc") {
384       depfile = "{{output}}.d"
385       precompiled_header_type = "gcc"
386       command = "$cc $md -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}${extra_cppflags}${extra_cflags} -c {{source}} -o {{output}}"
387       depsformat = "gcc"
388       description = "CC {{output}}"
389       outputs = [ "$object_subdir/{{source_name_part}}.o" ]
390     }
391
392     tool("cxx") {
393       depfile = "{{output}}.d"
394       precompiled_header_type = "gcc"
395       command = "$cxx $md -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}${extra_cppflags}${extra_cxxflags} -c {{source}} -o {{output}}"
396       depsformat = "gcc"
397       description = "CXX {{output}}"
398       outputs = [ "$object_subdir/{{source_name_part}}.o" ]
399     }
400
401     tool("asm") {
402       # For GCC we can just use the C compiler to compile assembly.
403       depfile = "{{output}}.d"
404       command = "$asm $md -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{asmflags}}${extra_asmflags} -c {{source}} -o {{output}}"
405       depsformat = "gcc"
406       description = "ASM {{output}}"
407       outputs = [ "$object_subdir/{{source_name_part}}.o" ]
408     }
409
410     tool("alink") {
411       if (current_os == "aix") {
412         # AIX does not support either -D (deterministic output) or response
413         # files.
414         command = "$ar -X64 {{arflags}} -r -c -s {{output}} {{inputs}}"
415       } else {
416         rspfile = "{{output}}.rsp"
417         rspfile_content = "{{inputs}}"
418         command = "\"$ar\" {{arflags}} -r -c -s -D {{output}} @\"$rspfile\""
419       }
420
421       # Remove the output file first so that ar doesn't try to modify the
422       # existing file.
423       if (host_os == "win") {
424         tool_wrapper_path =
425             rebase_path("//build/toolchain/win/tool_wrapper.py", root_build_dir)
426         command = "cmd /s /c \"\"$python_path\" $tool_wrapper_path delete-file {{output}} && $command\""
427       } else {
428         command = "rm -f {{output}} && $command"
429       }
430
431       # Almost all targets build with //build/config/compiler:thin_archive which
432       # adds -T to arflags.
433       description = "AR {{output}}"
434       outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
435
436       # Shared libraries go in the target out directory by default so we can
437       # generate different targets with the same name and not have them collide.
438       default_output_dir = "{{target_out_dir}}"
439       default_output_extension = ".a"
440       output_prefix = "lib"
441     }
442
443     tool("solink") {
444       soname = "{{target_output_name}}{{output_extension}}"  # e.g. "libfoo.so".
445       sofile = "{{output_dir}}/$soname"  # Possibly including toolchain dir.
446       rspfile = sofile + ".rsp"
447
448       pool = "//build/toolchain:link_pool($default_toolchain)"
449
450       if (defined(invoker.strip)) {
451         unstripped_sofile = "{{root_out_dir}}/lib.unstripped/$soname"
452       } else {
453         unstripped_sofile = sofile
454       }
455
456       # These variables are not built into GN but are helpers that
457       # implement (1) linking to produce a .so, (2) extracting the symbols
458       # from that file (3) if the extracted list differs from the existing
459       # .TOC file, overwrite it, otherwise, don't change it.
460       tocfile = sofile + ".TOC"
461
462       soname_flag = ""
463       if (current_os != "aix") {
464         # -soname flag is not available on aix ld
465         soname_flag = "-Wl,-soname=\"$soname\""
466       }
467       link_command = "$ld -shared $soname_flag {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" @\"$rspfile\" {{rlibs}}"
468
469       # Generate a map file to be used for binary size analysis.
470       # Map file adds ~10% to the link time on a z620.
471       # With target_os="android", libchrome.so.map.gz is ~20MB.
472       map_switch = ""
473       if (enable_linker_map) {
474         map_file = "$unstripped_sofile.map.gz"
475         map_switch = " --map-file \"$map_file\""
476       }
477
478       assert(defined(readelf), "to solink you must have a readelf")
479       assert(defined(nm), "to solink you must have an nm")
480       strip_switch = ""
481       if (defined(invoker.strip)) {
482         strip_switch = "--strip=${invoker.strip} "
483       }
484
485       # This needs a Python script to avoid using a complex shell command
486       # requiring sh control structures, pipelines, and POSIX utilities.
487       # The host might not have a POSIX shell and utilities (e.g. Windows).
488       solink_wrapper =
489           rebase_path("//build/toolchain/gcc_solink_wrapper.py", root_build_dir)
490       solink_extra_flags = ""
491       if (current_os == "aix") {
492         # to be intercepted by solink_wrapper, so that we exit immediately
493         # after linking the shared object, without generating the TOC file
494         # (skipped on Aix)
495         solink_extra_flags = "--partitioned-library"
496       }
497       command = "\"$python_path\" \"$solink_wrapper\" --readelf=\"$readelf\" --nm=\"$nm\" $strip_switch$dwp_switch --sofile=\"$unstripped_sofile\" --tocfile=\"$tocfile\"$map_switch --output=\"$sofile\" -- $link_command $solink_extra_flags"
498
499       if (target_cpu == "mipsel" && is_component_build && is_android) {
500         rspfile_content = "-Wl,--start-group -Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}} -Wl,--end-group"
501       } else if (current_os == "aix") {
502         # --whole-archive, --no-whole-archive flags are not available on the aix
503         # ld.
504         rspfile_content = "{{inputs}} {{solibs}} {{libs}}"
505       } else {
506         rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
507       }
508
509       description = "SOLINK $sofile"
510
511       # Use this for {{output_extension}} expansions unless a target manually
512       # overrides it (in which case {{output_extension}} will be what the target
513       # specifies).
514       default_output_extension = default_shlib_extension
515
516       default_output_dir = "{{root_out_dir}}${default_shlib_subdir}"
517
518       output_prefix = "lib"
519
520       # Since the above commands only updates the .TOC file when it changes, ask
521       # Ninja to check if the timestamp actually changed to know if downstream
522       # dependencies should be recompiled.
523       restat = true
524
525       # Tell GN about the output files. It will link to the sofile but use the
526       # tocfile for dependency management.
527       outputs = [
528         sofile,
529         tocfile,
530       ]
531       if (sofile != unstripped_sofile) {
532         outputs += [ unstripped_sofile ]
533         if (defined(invoker.use_unstripped_as_runtime_outputs) &&
534             invoker.use_unstripped_as_runtime_outputs) {
535           runtime_outputs = [ unstripped_sofile ]
536         }
537       }
538
539       # Clank build will generate DWP files when Fission is used.
540       # Other builds generate DWP files outside of the gn link targets, if at
541       # all.
542       if (defined(invoker.dwp)) {
543         outputs += [ unstripped_sofile + ".dwp" ]
544         if (defined(invoker.use_unstripped_as_runtime_outputs) &&
545             invoker.use_unstripped_as_runtime_outputs) {
546           runtime_outputs += [ unstripped_sofile + ".dwp" ]
547         }
548       }
549       if (defined(map_file)) {
550         outputs += [ map_file ]
551       }
552       link_output = sofile
553       depend_output = tocfile
554     }
555
556     tool("solink_module") {
557       soname = "{{target_output_name}}{{output_extension}}"  # e.g. "libfoo.so".
558       sofile = "{{output_dir}}/$soname"
559       rspfile = sofile + ".rsp"
560
561       pool = "//build/toolchain:link_pool($default_toolchain)"
562
563       if (defined(invoker.strip)) {
564         unstripped_sofile = "{{root_out_dir}}/lib.unstripped/$soname"
565       } else {
566         unstripped_sofile = sofile
567       }
568
569       soname_flag = ""
570       whole_archive_flag = ""
571       no_whole_archive_flag = ""
572       if (current_os != "aix") {
573         # -soname, --whole-archive, --no-whole-archive flags are not available
574         # on aix ld
575         soname_flag = "-Wl,-soname=\"$soname\""
576         whole_archive_flag = "-Wl,--whole-archive"
577         no_whole_archive_flag = "-Wl,--no-whole-archive"
578       }
579       command = "$ld -shared {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" $soname_flag @\"$rspfile\""
580
581       if (defined(invoker.strip)) {
582         strip_command = "${invoker.strip} -o \"$sofile\" \"$unstripped_sofile\""
583         command += " && " + strip_command
584       }
585       rspfile_content = "$whole_archive_flag {{inputs}} {{solibs}} $no_whole_archive_flag {{libs}} {{rlibs}}"
586
587       description = "SOLINK_MODULE $sofile"
588
589       # Use this for {{output_extension}} expansions unless a target manually
590       # overrides it (in which case {{output_extension}} will be what the target
591       # specifies).
592       if (defined(invoker.loadable_module_extension)) {
593         default_output_extension = invoker.loadable_module_extension
594       } else {
595         default_output_extension = default_shlib_extension
596       }
597
598       default_output_dir = "{{root_out_dir}}${default_shlib_subdir}"
599
600       output_prefix = "lib"
601
602       outputs = [ sofile ]
603       if (sofile != unstripped_sofile) {
604         outputs += [ unstripped_sofile ]
605         if (defined(invoker.use_unstripped_as_runtime_outputs) &&
606             invoker.use_unstripped_as_runtime_outputs) {
607           runtime_outputs = [ unstripped_sofile ]
608         }
609       }
610     }
611
612     tool("link") {
613       exename = "{{target_output_name}}{{output_extension}}"
614       outfile = "{{output_dir}}/$exename"
615       rspfile = "$outfile.rsp"
616       unstripped_outfile = outfile
617
618       pool = "//build/toolchain:link_pool($default_toolchain)"
619
620       # Use this for {{output_extension}} expansions unless a target manually
621       # overrides it (in which case {{output_extension}} will be what the target
622       # specifies).
623       default_output_extension = default_executable_extension
624
625       default_output_dir = "{{root_out_dir}}"
626
627       if (defined(invoker.strip)) {
628         unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$exename"
629       }
630
631       start_group_flag = ""
632       end_group_flag = ""
633       if (current_os != "aix") {
634         # the "--start-group .. --end-group" feature isn't available on the aix
635         # ld.
636         start_group_flag = "-Wl,--start-group"
637         end_group_flag = "-Wl,--end-group "
638       }
639       link_command = "$ld {{ldflags}}${extra_ldflags} -o \"$unstripped_outfile\" $start_group_flag @\"$rspfile\" {{solibs}} $end_group_flag {{libs}} {{rlibs}}"
640
641       # Generate a map file to be used for binary size analysis.
642       # Map file adds ~10% to the link time on a z620.
643       # With target_os="android", libchrome.so.map.gz is ~20MB.
644       map_switch = ""
645       if (enable_linker_map) {
646         map_file = "$unstripped_outfile.map.gz"
647         map_switch = " --map-file \"$map_file\""
648       }
649
650       strip_switch = ""
651       if (defined(invoker.strip)) {
652         strip_switch = " --strip=\"${invoker.strip}\" --unstripped-file=\"$unstripped_outfile\""
653       }
654
655       link_wrapper =
656           rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir)
657       command = "\"$python_path\" \"$link_wrapper\" --output=\"$outfile\"$strip_switch$map_switch$dwp_switch -- $link_command"
658
659       description = "LINK $outfile"
660
661       rspfile_content = "{{inputs}}"
662       outputs = [ outfile ]
663       if (outfile != unstripped_outfile) {
664         outputs += [ unstripped_outfile ]
665         if (defined(invoker.use_unstripped_as_runtime_outputs) &&
666             invoker.use_unstripped_as_runtime_outputs) {
667           runtime_outputs = [ unstripped_outfile ]
668         }
669       }
670
671       # Clank build will generate DWP files when Fission is used.
672       # Other builds generate DWP files outside of the gn link targets, if at
673       # all.
674       if (defined(invoker.dwp)) {
675         outputs += [ unstripped_outfile + ".dwp" ]
676         if (defined(invoker.use_unstripped_as_runtime_outputs) &&
677             invoker.use_unstripped_as_runtime_outputs) {
678           runtime_outputs += [ unstripped_outfile + ".dwp" ]
679         }
680       }
681       if (defined(invoker.link_outputs)) {
682         outputs += invoker.link_outputs
683       }
684       if (defined(map_file)) {
685         outputs += [ map_file ]
686       }
687     }
688
689     # These two are really entirely generic, but have to be repeated in
690     # each toolchain because GN doesn't allow a template to be used here.
691     # See //build/toolchain/toolchain.gni for details.
692     tool("stamp") {
693       command = stamp_command
694       description = stamp_description
695     }
696     tool("copy") {
697       command = copy_command
698       description = copy_description
699     }
700
701     tool("action") {
702       pool = "//build/toolchain:action_pool($default_toolchain)"
703     }
704
705     if (toolchain_has_rust) {
706       if (!defined(rust_compiler_prefix)) {
707         rust_compiler_prefix = ""
708       }
709       rust_sysroot_relative = rebase_path(rust_sysroot, root_build_dir)
710       rustc_bin = "$rust_sysroot_relative/bin/rustc"
711       rustc = "$rust_compiler_prefix${rustc_bin}"
712       rustc_wrapper =
713           rebase_path("//build/rust/rustc_wrapper.py", root_build_dir)
714
715       # RSP manipulation due to https://bugs.chromium.org/p/gn/issues/detail?id=249
716       tool("rust_staticlib") {
717         libname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
718         rspfile = "$libname.rsp"
719         depfile = "$libname.d"
720
721         default_output_extension = ".a"
722         output_prefix = "lib"
723         default_output_dir = "{{root_out_dir}}"
724         description = "RUST(STATICLIB) {{output}}"
725         outputs = [ libname ]
726
727         rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}"
728         command = "\"$python_path\" \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- -Clinker=\"${invoker.cxx}\" $rustc_common_args --emit=dep-info=$depfile,link -o $libname LDFLAGS RUSTENV {{rustenv}}"
729         rust_sysroot = rust_sysroot_relative
730       }
731
732       tool("rust_rlib") {
733         # We must always prefix with `lib` even if the library already starts
734         # with that prefix or else our stdlib is unable to find libc.rlib (or
735         # actually liblibc.rlib).
736         rlibname =
737             "{{output_dir}}/lib{{target_output_name}}{{output_extension}}"
738         rspfile = "$rlibname.rsp"
739         depfile = "$rlibname.d"
740
741         default_output_extension = ".rlib"
742
743         # This is prefixed unconditionally in `rlibname`.
744         # output_prefix = "lib"
745         default_output_dir = "{{root_out_dir}}"
746         description = "RUST {{output}}"
747         outputs = [ rlibname ]
748
749         rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}"
750         command = "\"$python_path\" \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- -Clinker=\"${invoker.cxx}\" $rustc_common_args --emit=dep-info=$depfile,link -o $rlibname LDFLAGS RUSTENV {{rustenv}}"
751         rust_sysroot = rust_sysroot_relative
752       }
753
754       tool("rust_bin") {
755         exename = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
756         depfile = "$exename.d"
757         rspfile = "$exename.rsp"
758         pool = "//build/toolchain:link_pool($default_toolchain)"
759
760         default_output_extension = default_executable_extension
761         default_output_dir = "{{root_out_dir}}"
762         description = "RUST(BIN) {{output}}"
763         outputs = [ exename ]
764
765         rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}"
766         command = "\"$python_path\" \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- -Clinker=\"${invoker.cxx}\" $rustc_common_args --emit=dep-info=$depfile,link -o $exename LDFLAGS {{ldflags}} ${extra_ldflags} RUSTENV {{rustenv}}"
767         rust_sysroot = rust_sysroot_relative
768       }
769
770       tool("rust_cdylib") {
771         dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
772         depfile = "$dllname.d"
773         rspfile = "$dllname.rsp"
774         pool = "//build/toolchain:link_pool($default_toolchain)"
775
776         default_output_extension = default_shlib_extension
777         output_prefix = "lib"
778         default_output_dir = "{{root_out_dir}}${default_shlib_subdir}"
779         description = "RUST(CDYLIB) {{output}}"
780         outputs = [ dllname ]
781
782         rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}"
783         command = "\"$python_path\" \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- -Clinker=\"${invoker.cxx}\" $rustc_common_args --emit=dep-info=$depfile,link -o $dllname LDFLAGS {{ldflags}} ${extra_ldflags} RUSTENV {{rustenv}}"
784         rust_sysroot = rust_sysroot_relative
785       }
786
787       tool("rust_macro") {
788         dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
789         depfile = "$dllname.d"
790         rspfile = "$dllname.rsp"
791         pool = "//build/toolchain:link_pool($default_toolchain)"
792
793         default_output_extension = default_shlib_extension
794         output_prefix = "lib"
795         default_output_dir = "{{root_out_dir}}${default_shlib_subdir}"
796         description = "RUST(MACRO) {{output}}"
797         outputs = [ dllname ]
798
799         rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}"
800         command = "\"$python_path\" \"$rustc_wrapper\" --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- -Clinker=\"${invoker.cxx}\" $rustc_common_args --emit=dep-info=$depfile,link -o $dllname LDFLAGS {{ldflags}} ${extra_ldflags} RUSTENV {{rustenv}}"
801         rust_sysroot = rust_sysroot_relative
802       }
803     }
804
805     forward_variables_from(invoker,
806                            [
807                              "deps",
808                              "propagates_configs",
809                            ])
810   }
811 }
812
813 # Makes a GCC toolchain for the target, and an equivalent toolchain with the
814 # prebuilt Rust stdlib for building proc macros (and other for-build-use
815 # artifacts).
816 template("gcc_toolchain") {
817   single_gcc_toolchain(target_name) {
818     assert(defined(invoker.toolchain_args),
819            "Toolchains must declare toolchain_args")
820     forward_variables_from(invoker,
821                            "*",
822                            [
823                              "visibility",
824                              "test_only",
825                            ])
826
827     # No need to forward visibility and test_only as they apply to targets not
828     # toolchains, but presubmit checks require that we explicitly exclude them
829   }
830
831   if (enable_rust && current_toolchain == default_toolchain) {
832     # Make an additional toolchain which is used for making tools that are run
833     # on the host machine as part of the build process (such as proc macros
834     # and Cargo build scripts). This toolchain uses the prebuilt stdlib that
835     # comes with the compiler, so it doesn't have to wait for the stdlib to be
836     # built before building other stuff. And this ensures its proc macro
837     # outputs have the right ABI to be loaded by the compiler, and it can be
838     # used to compile build scripts that are part of the stdlib that is built
839     # for the default toolchain.
840     single_gcc_toolchain("${target_name}_for_rust_host_build_tools") {
841       assert(defined(invoker.toolchain_args),
842              "Toolchains must declare toolchain_args")
843       forward_variables_from(invoker,
844                              "*",
845                              [
846                                "toolchain_args",
847                                "visibility",
848                                "test_only",
849                              ])
850       toolchain_args = {
851         # Populate toolchain args from the invoker.
852         forward_variables_from(invoker.toolchain_args, "*")
853         toolchain_for_rust_host_build_tools = true
854
855         # The host build tools are static release builds to make the Chromium
856         # build faster.
857         is_debug = false
858         is_component_build = false
859         is_official_build = false
860         use_clang_coverage = false
861         use_sanitizer_coverage = false
862         generate_linker_map = false
863       }
864
865       # When cross-compiling we don't want to use the target platform's file
866       # extensions.
867       shlib_extension = host_shlib_extension
868     }
869   }
870 }
871
872 # This is a shorthand for gcc_toolchain instances based on the Chromium-built
873 # version of Clang. Only the toolchain_cpu and toolchain_os variables need to
874 # be specified by the invoker, and optionally toolprefix if it's a
875 # cross-compile case. Note that for a cross-compile case this toolchain
876 # requires a config to pass the appropriate -target option, or else it will
877 # actually just be doing a native compile. The invoker can optionally override
878 # use_gold too.
879 template("clang_toolchain") {
880   gcc_toolchain(target_name) {
881     _path = "$clang_base_path/bin"
882     _is_path_absolute = get_path_info(_path, "abspath") == _path
883
884     # Preserve absolute paths for tools like distcc.
885     if (_is_path_absolute && filter_include([ _path ], [ "//*" ]) == []) {
886       prefix = _path
887     } else {
888       prefix = rebase_path(_path, root_build_dir)
889     }
890
891     cc = "${prefix}/clang"
892     cxx = "${prefix}/clang++"
893     ld = cxx
894     readelf = "${prefix}/llvm-readelf"
895     ar = "${prefix}/llvm-ar"
896     nm = "${prefix}/llvm-nm"
897
898     forward_variables_from(invoker, "*", [ "toolchain_args" ])
899
900     toolchain_args = {
901       if (defined(invoker.toolchain_args)) {
902         forward_variables_from(invoker.toolchain_args, "*")
903       }
904       is_clang = true
905     }
906   }
907 }