xref: /aosp_15_r20/external/pigweed/pw_toolchain/static_analysis_toolchain.gni (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker# Copyright 2022 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker#
3*61c4878aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker# the License at
6*61c4878aSAndroid Build Coastguard Worker#
7*61c4878aSAndroid Build Coastguard Worker#     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker#
9*61c4878aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker# the License.
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Workerimport("//build_overrides/pigweed.gni")
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_compilation_testing/negative_compilation_test.gni")
18*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_third_party/boringssl/boringssl.gni")
19*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_third_party/chre/chre.gni")
20*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_third_party/googletest/googletest.gni")
21*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_third_party/mbedtls/mbedtls.gni")
22*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_toolchain/universal_tools.gni")
23*61c4878aSAndroid Build Coastguard Worker
24*61c4878aSAndroid Build Coastguard Workerdeclare_args() {
25*61c4878aSAndroid Build Coastguard Worker  # Regular expressions matching the paths of the source files to be excluded
26*61c4878aSAndroid Build Coastguard Worker  # from the analysis. clang-tidy provides no alternative option.
27*61c4878aSAndroid Build Coastguard Worker  #
28*61c4878aSAndroid Build Coastguard Worker  # For example, the following disables clang-tidy on all source files in the
29*61c4878aSAndroid Build Coastguard Worker  # third_party directory:
30*61c4878aSAndroid Build Coastguard Worker  #
31*61c4878aSAndroid Build Coastguard Worker  #   pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES = ["third_party/.*"]
32*61c4878aSAndroid Build Coastguard Worker  #
33*61c4878aSAndroid Build Coastguard Worker  pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES = []
34*61c4878aSAndroid Build Coastguard Worker
35*61c4878aSAndroid Build Coastguard Worker  # Disable clang-tidy for specific include paths. In the clang-tidy command,
36*61c4878aSAndroid Build Coastguard Worker  # include paths that end with one of these, or match as a regular expression,
37*61c4878aSAndroid Build Coastguard Worker  # are switched from -I to -isystem, which causes clang-tidy to ignore them.
38*61c4878aSAndroid Build Coastguard Worker  # Unfortunately, clang-tidy provides no other way to filter header files.
39*61c4878aSAndroid Build Coastguard Worker  #
40*61c4878aSAndroid Build Coastguard Worker  # For example, the following ignores header files in "repo/include":
41*61c4878aSAndroid Build Coastguard Worker  #
42*61c4878aSAndroid Build Coastguard Worker  #   pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS = ["repo/include"]
43*61c4878aSAndroid Build Coastguard Worker  #
44*61c4878aSAndroid Build Coastguard Worker  # While the following ignores all third-party header files:
45*61c4878aSAndroid Build Coastguard Worker  #
46*61c4878aSAndroid Build Coastguard Worker  #   pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS = [".*/third_party/.*"]
47*61c4878aSAndroid Build Coastguard Worker  #
48*61c4878aSAndroid Build Coastguard Worker  pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS = []
49*61c4878aSAndroid Build Coastguard Worker}
50*61c4878aSAndroid Build Coastguard Worker
51*61c4878aSAndroid Build Coastguard Worker# Third-party software with Pigweed-supported build files that do not pass all
52*61c4878aSAndroid Build Coastguard Worker# clang-tidy checks.
53*61c4878aSAndroid Build Coastguard Worker_excluded_third_party_dirs = [
54*61c4878aSAndroid Build Coastguard Worker  dir_pw_third_party_mbedtls,
55*61c4878aSAndroid Build Coastguard Worker  dir_pw_third_party_boringssl,
56*61c4878aSAndroid Build Coastguard Worker  dir_pw_third_party_googletest,
57*61c4878aSAndroid Build Coastguard Worker  dir_pw_third_party_chre,
58*61c4878aSAndroid Build Coastguard Worker]
59*61c4878aSAndroid Build Coastguard Worker
60*61c4878aSAndroid Build Coastguard Worker# Creates a toolchain target for static analysis.
61*61c4878aSAndroid Build Coastguard Worker#
62*61c4878aSAndroid Build Coastguard Worker# The generated toolchain runs clang-tidy on all source files that are not
63*61c4878aSAndroid Build Coastguard Worker# excluded by pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES or
64*61c4878aSAndroid Build Coastguard Worker# pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS.
65*61c4878aSAndroid Build Coastguard Worker#
66*61c4878aSAndroid Build Coastguard Worker# Args:
67*61c4878aSAndroid Build Coastguard Worker#   cc: (required) String indicating the C compiler to use.
68*61c4878aSAndroid Build Coastguard Worker#   cxx: (required) String indicating the C++ compiler to use.
69*61c4878aSAndroid Build Coastguard Worker#   static_analysis: (required) A scope defining args to apply to the
70*61c4878aSAndroid Build Coastguard Worker#     static_analysis toolchain.
71*61c4878aSAndroid Build Coastguard Worker#   static_analysis.enabled: (required) Bool used to indicate whether
72*61c4878aSAndroid Build Coastguard Worker#       static_analysis should be enabled for the toolchain where scope is
73*61c4878aSAndroid Build Coastguard Worker#       applied to. Note that static_analysis.enabled must be set in order to
74*61c4878aSAndroid Build Coastguard Worker#       use this toolchain.
75*61c4878aSAndroid Build Coastguard Worker#   static_analysis.clang_tidy_path: (optional) String indicating clang-tidy bin
76*61c4878aSAndroid Build Coastguard Worker#       to use.
77*61c4878aSAndroid Build Coastguard Worker#   static_analysis.cc_post: (optional) String defining additional commands to
78*61c4878aSAndroid Build Coastguard Worker#       append to cc tool's command list (i.e command(s) to run after cc command
79*61c4878aSAndroid Build Coastguard Worker#       chain).
80*61c4878aSAndroid Build Coastguard Worker#   static_analysis.cxx_post: (optional) String defining additional commands to
81*61c4878aSAndroid Build Coastguard Worker#       append to cxx tool's command list (i.e command(s) to run after cxx
82*61c4878aSAndroid Build Coastguard Worker#       command chain).
83*61c4878aSAndroid Build Coastguard Workertemplate("pw_static_analysis_toolchain") {
84*61c4878aSAndroid Build Coastguard Worker  invoker_toolchain_args = invoker.defaults
85*61c4878aSAndroid Build Coastguard Worker  assert(defined(invoker.static_analysis), "static_analysis scope missing.")
86*61c4878aSAndroid Build Coastguard Worker  _static_analysis_args = invoker.static_analysis
87*61c4878aSAndroid Build Coastguard Worker  assert(defined(_static_analysis_args.enabled),
88*61c4878aSAndroid Build Coastguard Worker         "static_analysis.enabled is missing")
89*61c4878aSAndroid Build Coastguard Worker  assert(_static_analysis_args.enabled,
90*61c4878aSAndroid Build Coastguard Worker         "static_analysis.enabled must be true to use this toolchain.")
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard Worker  _skipped_regexps = []
93*61c4878aSAndroid Build Coastguard Worker  _skipped_include_paths = []
94*61c4878aSAndroid Build Coastguard Worker  foreach(third_party_dir, _excluded_third_party_dirs) {
95*61c4878aSAndroid Build Coastguard Worker    if (third_party_dir != "") {
96*61c4878aSAndroid Build Coastguard Worker      _skipped_include_paths += [
97*61c4878aSAndroid Build Coastguard Worker        third_party_dir + "/include",
98*61c4878aSAndroid Build Coastguard Worker        third_party_dir,
99*61c4878aSAndroid Build Coastguard Worker      ]
100*61c4878aSAndroid Build Coastguard Worker    }
101*61c4878aSAndroid Build Coastguard Worker  }
102*61c4878aSAndroid Build Coastguard Worker
103*61c4878aSAndroid Build Coastguard Worker  _skipped_regexps += pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES
104*61c4878aSAndroid Build Coastguard Worker  _skipped_include_paths += pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS
105*61c4878aSAndroid Build Coastguard Worker
106*61c4878aSAndroid Build Coastguard Worker  # Clang tidy is invoked by a wrapper script which implements the missing
107*61c4878aSAndroid Build Coastguard Worker  # option --source-filter.
108*61c4878aSAndroid Build Coastguard Worker  _clang_tidy_py_path =
109*61c4878aSAndroid Build Coastguard Worker      rebase_path("$dir_pw_toolchain/py/pw_toolchain/clang_tidy.py",
110*61c4878aSAndroid Build Coastguard Worker                  root_build_dir)
111*61c4878aSAndroid Build Coastguard Worker  _clang_tidy_py = "${python_path} ${_clang_tidy_py_path}"
112*61c4878aSAndroid Build Coastguard Worker  _source_root = rebase_path("//", root_build_dir)
113*61c4878aSAndroid Build Coastguard Worker  _source_exclude = ""
114*61c4878aSAndroid Build Coastguard Worker  foreach(pattern, _skipped_regexps) {
115*61c4878aSAndroid Build Coastguard Worker    _source_exclude = _source_exclude + " --source-exclude '${pattern}'"
116*61c4878aSAndroid Build Coastguard Worker  }
117*61c4878aSAndroid Build Coastguard Worker  _skip_include_path = ""
118*61c4878aSAndroid Build Coastguard Worker  foreach(pattern, _skipped_include_paths) {
119*61c4878aSAndroid Build Coastguard Worker    _skip_include_path =
120*61c4878aSAndroid Build Coastguard Worker        _skip_include_path + " --skip-include-path '${pattern}'"
121*61c4878aSAndroid Build Coastguard Worker  }
122*61c4878aSAndroid Build Coastguard Worker  _clang_tidy_path = ""
123*61c4878aSAndroid Build Coastguard Worker  if (defined(_static_analysis_args.clang_tidy_path)) {
124*61c4878aSAndroid Build Coastguard Worker    _clang_tidy_path =
125*61c4878aSAndroid Build Coastguard Worker        "--clang-tidy " +
126*61c4878aSAndroid Build Coastguard Worker        rebase_path(_static_analysis_args.clang_tidy_path, root_build_dir)
127*61c4878aSAndroid Build Coastguard Worker  }
128*61c4878aSAndroid Build Coastguard Worker
129*61c4878aSAndroid Build Coastguard Worker  toolchain(target_name) {
130*61c4878aSAndroid Build Coastguard Worker    # Uncomment this line to see which toolchains generate other toolchains.
131*61c4878aSAndroid Build Coastguard Worker    # print("Generating toolchain: ${target_name} by ${current_toolchain}")
132*61c4878aSAndroid Build Coastguard Worker
133*61c4878aSAndroid Build Coastguard Worker    tool("asm") {
134*61c4878aSAndroid Build Coastguard Worker      depfile = "{{output}}.d"
135*61c4878aSAndroid Build Coastguard Worker      command = pw_universal_stamp.command
136*61c4878aSAndroid Build Coastguard Worker      depsformat = "gcc"
137*61c4878aSAndroid Build Coastguard Worker      description = "as {{output}}"
138*61c4878aSAndroid Build Coastguard Worker      outputs = [
139*61c4878aSAndroid Build Coastguard Worker        # Use {{source_file_part}}, which includes the extension, instead of
140*61c4878aSAndroid Build Coastguard Worker        # {{source_name_part}} so that object files created from <file_name>.c
141*61c4878aSAndroid Build Coastguard Worker        # and <file_name>.cc sources are unique.
142*61c4878aSAndroid Build Coastguard Worker        "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o",
143*61c4878aSAndroid Build Coastguard Worker      ]
144*61c4878aSAndroid Build Coastguard Worker    }
145*61c4878aSAndroid Build Coastguard Worker
146*61c4878aSAndroid Build Coastguard Worker    assert(defined(invoker.cc), "toolchain is missing 'cc'")
147*61c4878aSAndroid Build Coastguard Worker    tool("cc") {
148*61c4878aSAndroid Build Coastguard Worker      _post_command_hook = ""
149*61c4878aSAndroid Build Coastguard Worker      if (defined(_static_analysis_args.cc_post) &&
150*61c4878aSAndroid Build Coastguard Worker          _static_analysis_args.cc_post != "") {
151*61c4878aSAndroid Build Coastguard Worker        _post_command_hook += " && " + _static_analysis_args.cc_post
152*61c4878aSAndroid Build Coastguard Worker      }
153*61c4878aSAndroid Build Coastguard Worker
154*61c4878aSAndroid Build Coastguard Worker      depfile = "{{output}}.d"
155*61c4878aSAndroid Build Coastguard Worker      command = string_join(" ",
156*61c4878aSAndroid Build Coastguard Worker                            [
157*61c4878aSAndroid Build Coastguard Worker                              _clang_tidy_py,
158*61c4878aSAndroid Build Coastguard Worker                              _source_exclude,
159*61c4878aSAndroid Build Coastguard Worker                              _skip_include_path,
160*61c4878aSAndroid Build Coastguard Worker                              _clang_tidy_path,
161*61c4878aSAndroid Build Coastguard Worker                              "--source-file {{source}}",
162*61c4878aSAndroid Build Coastguard Worker                              "--source-root '${_source_root}'",
163*61c4878aSAndroid Build Coastguard Worker                              "--export-fixes {{output}}.yaml",
164*61c4878aSAndroid Build Coastguard Worker                              "--",
165*61c4878aSAndroid Build Coastguard Worker                              invoker.cc,
166*61c4878aSAndroid Build Coastguard Worker                              "END_OF_INVOKER",
167*61c4878aSAndroid Build Coastguard Worker                              "-MMD -MF $depfile",  # Write out dependencies.
168*61c4878aSAndroid Build Coastguard Worker                              "{{cflags}}",
169*61c4878aSAndroid Build Coastguard Worker                              "{{cflags_c}}",  # Must come after {{cflags}}.
170*61c4878aSAndroid Build Coastguard Worker                              "{{defines}}",
171*61c4878aSAndroid Build Coastguard Worker                              "{{include_dirs}}",
172*61c4878aSAndroid Build Coastguard Worker                              "-c {{source}}",
173*61c4878aSAndroid Build Coastguard Worker                              "-o {{output}}",
174*61c4878aSAndroid Build Coastguard Worker                            ]) + " && touch {{output}}" + _post_command_hook
175*61c4878aSAndroid Build Coastguard Worker      depsformat = "gcc"
176*61c4878aSAndroid Build Coastguard Worker      description = "clang-tidy {{source}}"
177*61c4878aSAndroid Build Coastguard Worker      outputs =
178*61c4878aSAndroid Build Coastguard Worker          [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
179*61c4878aSAndroid Build Coastguard Worker    }
180*61c4878aSAndroid Build Coastguard Worker
181*61c4878aSAndroid Build Coastguard Worker    assert(defined(invoker.cxx), "toolchain is missing 'cxx'")
182*61c4878aSAndroid Build Coastguard Worker    tool("cxx") {
183*61c4878aSAndroid Build Coastguard Worker      _post_command_hook = ""
184*61c4878aSAndroid Build Coastguard Worker      if (defined(_static_analysis_args.cxx_post) &&
185*61c4878aSAndroid Build Coastguard Worker          _static_analysis_args.cxx_post != "") {
186*61c4878aSAndroid Build Coastguard Worker        _post_command_hook += " && " + _static_analysis_args.cxx_post
187*61c4878aSAndroid Build Coastguard Worker      }
188*61c4878aSAndroid Build Coastguard Worker
189*61c4878aSAndroid Build Coastguard Worker      depfile = "{{output}}.d"
190*61c4878aSAndroid Build Coastguard Worker      command = string_join(" ",
191*61c4878aSAndroid Build Coastguard Worker                            [
192*61c4878aSAndroid Build Coastguard Worker                              _clang_tidy_py,
193*61c4878aSAndroid Build Coastguard Worker                              _source_exclude,
194*61c4878aSAndroid Build Coastguard Worker                              _skip_include_path,
195*61c4878aSAndroid Build Coastguard Worker                              _clang_tidy_path,
196*61c4878aSAndroid Build Coastguard Worker                              "--source-file {{source}}",
197*61c4878aSAndroid Build Coastguard Worker                              "--source-root '${_source_root}'",
198*61c4878aSAndroid Build Coastguard Worker                              "--export-fixes {{output}}.yaml",
199*61c4878aSAndroid Build Coastguard Worker                              "--",
200*61c4878aSAndroid Build Coastguard Worker                              invoker.cxx,
201*61c4878aSAndroid Build Coastguard Worker                              "END_OF_INVOKER",
202*61c4878aSAndroid Build Coastguard Worker                              "-MMD -MF $depfile",  # Write out dependencies.
203*61c4878aSAndroid Build Coastguard Worker                              "{{cflags}}",
204*61c4878aSAndroid Build Coastguard Worker                              "{{cflags_cc}}",  # Must come after {{cflags}}.
205*61c4878aSAndroid Build Coastguard Worker                              "{{defines}}",
206*61c4878aSAndroid Build Coastguard Worker                              "{{include_dirs}}",
207*61c4878aSAndroid Build Coastguard Worker                              "-c {{source}}",
208*61c4878aSAndroid Build Coastguard Worker                              "-o {{output}}",
209*61c4878aSAndroid Build Coastguard Worker                            ]) + " && touch {{output}}" + _post_command_hook
210*61c4878aSAndroid Build Coastguard Worker      depsformat = "gcc"
211*61c4878aSAndroid Build Coastguard Worker      description = "clang-tidy {{source}}"
212*61c4878aSAndroid Build Coastguard Worker      outputs =
213*61c4878aSAndroid Build Coastguard Worker          [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
214*61c4878aSAndroid Build Coastguard Worker    }
215*61c4878aSAndroid Build Coastguard Worker
216*61c4878aSAndroid Build Coastguard Worker    tool("objc") {
217*61c4878aSAndroid Build Coastguard Worker      depfile = "{{output}}.d"
218*61c4878aSAndroid Build Coastguard Worker      command = pw_universal_stamp.command
219*61c4878aSAndroid Build Coastguard Worker      depsformat = "gcc"
220*61c4878aSAndroid Build Coastguard Worker      description = "objc {{source}}"
221*61c4878aSAndroid Build Coastguard Worker      outputs =
222*61c4878aSAndroid Build Coastguard Worker          [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
223*61c4878aSAndroid Build Coastguard Worker    }
224*61c4878aSAndroid Build Coastguard Worker
225*61c4878aSAndroid Build Coastguard Worker    tool("objcxx") {
226*61c4878aSAndroid Build Coastguard Worker      depfile = "{{output}}.d"
227*61c4878aSAndroid Build Coastguard Worker      command = pw_universal_stamp.command
228*61c4878aSAndroid Build Coastguard Worker      depsformat = "gcc"
229*61c4878aSAndroid Build Coastguard Worker      description = "objc++ {{output}}"
230*61c4878aSAndroid Build Coastguard Worker      outputs =
231*61c4878aSAndroid Build Coastguard Worker          [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ]
232*61c4878aSAndroid Build Coastguard Worker    }
233*61c4878aSAndroid Build Coastguard Worker
234*61c4878aSAndroid Build Coastguard Worker    tool("alink") {
235*61c4878aSAndroid Build Coastguard Worker      command = "rm -f {{output}} && touch {{output}}"
236*61c4878aSAndroid Build Coastguard Worker      description = "ar {{target_output_name}}{{output_extension}}"
237*61c4878aSAndroid Build Coastguard Worker      outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
238*61c4878aSAndroid Build Coastguard Worker      default_output_extension = ".a"
239*61c4878aSAndroid Build Coastguard Worker      default_output_dir = "{{target_out_dir}}/lib"
240*61c4878aSAndroid Build Coastguard Worker    }
241*61c4878aSAndroid Build Coastguard Worker
242*61c4878aSAndroid Build Coastguard Worker    tool("link") {
243*61c4878aSAndroid Build Coastguard Worker      if (host_os == "win") {
244*61c4878aSAndroid Build Coastguard Worker        # Force the extension to '.bat', empty bat scripts are still
245*61c4878aSAndroid Build Coastguard Worker        # executable and will not raise errors.
246*61c4878aSAndroid Build Coastguard Worker        _output = "{{output_dir}}/{{target_output_name}}.bat"
247*61c4878aSAndroid Build Coastguard Worker        command = pw_universal_stamp.command
248*61c4878aSAndroid Build Coastguard Worker        default_output_extension = ".bat"
249*61c4878aSAndroid Build Coastguard Worker      } else {
250*61c4878aSAndroid Build Coastguard Worker        default_output_extension = ""
251*61c4878aSAndroid Build Coastguard Worker        _output = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
252*61c4878aSAndroid Build Coastguard Worker        command = "touch {{output}} && chmod +x {{output}}"
253*61c4878aSAndroid Build Coastguard Worker      }
254*61c4878aSAndroid Build Coastguard Worker      description = "ld $_output"
255*61c4878aSAndroid Build Coastguard Worker      outputs = [ _output ]
256*61c4878aSAndroid Build Coastguard Worker      default_output_dir = "{{target_out_dir}}/bin"
257*61c4878aSAndroid Build Coastguard Worker    }
258*61c4878aSAndroid Build Coastguard Worker
259*61c4878aSAndroid Build Coastguard Worker    tool("solink") {
260*61c4878aSAndroid Build Coastguard Worker      _output = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
261*61c4878aSAndroid Build Coastguard Worker      command = pw_universal_stamp.command
262*61c4878aSAndroid Build Coastguard Worker      description = "ld -shared $_output"
263*61c4878aSAndroid Build Coastguard Worker      outputs = [ _output ]
264*61c4878aSAndroid Build Coastguard Worker      default_output_dir = "{{target_out_dir}}/lib"
265*61c4878aSAndroid Build Coastguard Worker      default_output_extension = ".so"
266*61c4878aSAndroid Build Coastguard Worker    }
267*61c4878aSAndroid Build Coastguard Worker
268*61c4878aSAndroid Build Coastguard Worker    tool("stamp") {
269*61c4878aSAndroid Build Coastguard Worker      # GN-ism: GN gets mad if you directly forward the contents of
270*61c4878aSAndroid Build Coastguard Worker      # pw_universal_stamp.
271*61c4878aSAndroid Build Coastguard Worker      _stamp = pw_universal_stamp
272*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(_stamp, "*")
273*61c4878aSAndroid Build Coastguard Worker    }
274*61c4878aSAndroid Build Coastguard Worker
275*61c4878aSAndroid Build Coastguard Worker    tool("copy") {
276*61c4878aSAndroid Build Coastguard Worker      # GN-ism: GN gets mad if you directly forward the contents of
277*61c4878aSAndroid Build Coastguard Worker      # pw_universal_copy.
278*61c4878aSAndroid Build Coastguard Worker      _copy = pw_universal_copy
279*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(_copy, "*")
280*61c4878aSAndroid Build Coastguard Worker    }
281*61c4878aSAndroid Build Coastguard Worker
282*61c4878aSAndroid Build Coastguard Worker    # Build arguments to be overridden when compiling cross-toolchain:
283*61c4878aSAndroid Build Coastguard Worker    #
284*61c4878aSAndroid Build Coastguard Worker    #   pw_toolchain_defaults: A scope setting defaults to apply to GN targets
285*61c4878aSAndroid Build Coastguard Worker    #     in this toolchain. It is analogous to $pw_target_defaults in
286*61c4878aSAndroid Build Coastguard Worker    #     $dir_pigweed/pw_vars_default.gni.
287*61c4878aSAndroid Build Coastguard Worker    #
288*61c4878aSAndroid Build Coastguard Worker    #   pw_toolchain_SCOPE: A copy of the invoker scope that defines the
289*61c4878aSAndroid Build Coastguard Worker    #     toolchain. Used for generating derivative toolchains.
290*61c4878aSAndroid Build Coastguard Worker    #
291*61c4878aSAndroid Build Coastguard Worker    toolchain_args = {
292*61c4878aSAndroid Build Coastguard Worker      pw_toolchain_SCOPE = {
293*61c4878aSAndroid Build Coastguard Worker      }
294*61c4878aSAndroid Build Coastguard Worker      pw_toolchain_SCOPE = {
295*61c4878aSAndroid Build Coastguard Worker        forward_variables_from(invoker, "*")
296*61c4878aSAndroid Build Coastguard Worker        name = target_name
297*61c4878aSAndroid Build Coastguard Worker      }
298*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(invoker_toolchain_args, "*")
299*61c4878aSAndroid Build Coastguard Worker
300*61c4878aSAndroid Build Coastguard Worker      # Disable compilation testing for static analysis toolchains.
301*61c4878aSAndroid Build Coastguard Worker      pw_compilation_testing_NEGATIVE_COMPILATION_ENABLED = false
302*61c4878aSAndroid Build Coastguard Worker
303*61c4878aSAndroid Build Coastguard Worker      # Always disable coverage generation since we will not actually run the
304*61c4878aSAndroid Build Coastguard Worker      # instrumented binaries to produce a profraw file.
305*61c4878aSAndroid Build Coastguard Worker      pw_toolchain_COVERAGE_ENABLED = false
306*61c4878aSAndroid Build Coastguard Worker    }
307*61c4878aSAndroid Build Coastguard Worker
308*61c4878aSAndroid Build Coastguard Worker    _generate_rust_tools = defined(invoker.rustc)
309*61c4878aSAndroid Build Coastguard Worker    if (_generate_rust_tools) {
310*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.ld)) {
311*61c4878aSAndroid Build Coastguard Worker        _rustc_linker = "-Clinker=${invoker.ld}"
312*61c4878aSAndroid Build Coastguard Worker      } else {
313*61c4878aSAndroid Build Coastguard Worker        _rustc_linker = ""
314*61c4878aSAndroid Build Coastguard Worker      }
315*61c4878aSAndroid Build Coastguard Worker
316*61c4878aSAndroid Build Coastguard Worker      _rustc_command = string_join(
317*61c4878aSAndroid Build Coastguard Worker              " ",
318*61c4878aSAndroid Build Coastguard Worker              [
319*61c4878aSAndroid Build Coastguard Worker                # TODO: b/234872510 - Ensure this works with Windows.
320*61c4878aSAndroid Build Coastguard Worker                "RUST_BACKTRACE=1",
321*61c4878aSAndroid Build Coastguard Worker                "{{rustenv}}",
322*61c4878aSAndroid Build Coastguard Worker                invoker.rustc,
323*61c4878aSAndroid Build Coastguard Worker                "{{source}}",
324*61c4878aSAndroid Build Coastguard Worker                "--crate-name {{crate_name}}",
325*61c4878aSAndroid Build Coastguard Worker                "--crate-type {{crate_type}}",
326*61c4878aSAndroid Build Coastguard Worker                _rustc_linker,
327*61c4878aSAndroid Build Coastguard Worker                "{{externs}}",
328*61c4878aSAndroid Build Coastguard Worker                "{{rustdeps}}",
329*61c4878aSAndroid Build Coastguard Worker                "{{rustflags}}",
330*61c4878aSAndroid Build Coastguard Worker                "-D warnings",
331*61c4878aSAndroid Build Coastguard Worker                "--color always",
332*61c4878aSAndroid Build Coastguard Worker                "--emit=dep-info={{output}}.d,link",
333*61c4878aSAndroid Build Coastguard Worker                "-o {{output_dir}}/{{target_output_name}}{{output_extension}}",
334*61c4878aSAndroid Build Coastguard Worker              ])
335*61c4878aSAndroid Build Coastguard Worker
336*61c4878aSAndroid Build Coastguard Worker      _output = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
337*61c4878aSAndroid Build Coastguard Worker
338*61c4878aSAndroid Build Coastguard Worker      tool("rust_bin") {
339*61c4878aSAndroid Build Coastguard Worker        description = "rustc {{output}}"
340*61c4878aSAndroid Build Coastguard Worker        default_output_dir = "{{target_out_dir}}/bin"
341*61c4878aSAndroid Build Coastguard Worker        depfile = "{{output}}.d"
342*61c4878aSAndroid Build Coastguard Worker        command = _rustc_command
343*61c4878aSAndroid Build Coastguard Worker        outputs = [ _output ]
344*61c4878aSAndroid Build Coastguard Worker      }
345*61c4878aSAndroid Build Coastguard Worker
346*61c4878aSAndroid Build Coastguard Worker      tool("rust_rlib") {
347*61c4878aSAndroid Build Coastguard Worker        description = "rustc {{output}}"
348*61c4878aSAndroid Build Coastguard Worker        default_output_dir = "{{target_out_dir}}/lib"
349*61c4878aSAndroid Build Coastguard Worker        depfile = "{{output}}.d"
350*61c4878aSAndroid Build Coastguard Worker        output_prefix = "lib"
351*61c4878aSAndroid Build Coastguard Worker        default_output_extension = ".rlib"
352*61c4878aSAndroid Build Coastguard Worker        command = _rustc_command
353*61c4878aSAndroid Build Coastguard Worker        outputs = [ _output ]
354*61c4878aSAndroid Build Coastguard Worker      }
355*61c4878aSAndroid Build Coastguard Worker
356*61c4878aSAndroid Build Coastguard Worker      tool("rust_staticlib") {
357*61c4878aSAndroid Build Coastguard Worker        description = "rustc {{output}}"
358*61c4878aSAndroid Build Coastguard Worker        default_output_dir = "{{target_out_dir}}/lib"
359*61c4878aSAndroid Build Coastguard Worker        depfile = "{{output}}.d"
360*61c4878aSAndroid Build Coastguard Worker        output_prefix = "lib"
361*61c4878aSAndroid Build Coastguard Worker        default_output_extension = ".a"
362*61c4878aSAndroid Build Coastguard Worker        command = _rustc_command
363*61c4878aSAndroid Build Coastguard Worker        outputs = [ _output ]
364*61c4878aSAndroid Build Coastguard Worker      }
365*61c4878aSAndroid Build Coastguard Worker
366*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.is_host_toolchain) && invoker.is_host_toolchain) {
367*61c4878aSAndroid Build Coastguard Worker        if (!defined(invoker_toolchain_args.current_os)) {
368*61c4878aSAndroid Build Coastguard Worker          toolchain_os = ""
369*61c4878aSAndroid Build Coastguard Worker        } else {
370*61c4878aSAndroid Build Coastguard Worker          # Determine OS of toolchain, which is the builtin argument "current_os".
371*61c4878aSAndroid Build Coastguard Worker          toolchain_os = invoker_toolchain_args.current_os
372*61c4878aSAndroid Build Coastguard Worker        }
373*61c4878aSAndroid Build Coastguard Worker
374*61c4878aSAndroid Build Coastguard Worker        if (toolchain_os == "mac") {
375*61c4878aSAndroid Build Coastguard Worker          _dylib_extension = ".dylib"
376*61c4878aSAndroid Build Coastguard Worker        } else if (toolchain_os == "win") {
377*61c4878aSAndroid Build Coastguard Worker          _dylib_extension = ".dll"
378*61c4878aSAndroid Build Coastguard Worker        } else {
379*61c4878aSAndroid Build Coastguard Worker          _dylib_extension = ".so"
380*61c4878aSAndroid Build Coastguard Worker        }
381*61c4878aSAndroid Build Coastguard Worker
382*61c4878aSAndroid Build Coastguard Worker        tool("rust_macro") {
383*61c4878aSAndroid Build Coastguard Worker          description = "rustc {{output}}"
384*61c4878aSAndroid Build Coastguard Worker          default_output_dir = "{{target_out_dir}}/lib"
385*61c4878aSAndroid Build Coastguard Worker          depfile = "{{output}}.d"
386*61c4878aSAndroid Build Coastguard Worker          output_prefix = "lib"
387*61c4878aSAndroid Build Coastguard Worker          default_output_extension = _dylib_extension
388*61c4878aSAndroid Build Coastguard Worker          command = _rustc_command
389*61c4878aSAndroid Build Coastguard Worker          outputs = [ _output ]
390*61c4878aSAndroid Build Coastguard Worker        }
391*61c4878aSAndroid Build Coastguard Worker      }
392*61c4878aSAndroid Build Coastguard Worker    }
393*61c4878aSAndroid Build Coastguard Worker  }
394*61c4878aSAndroid Build Coastguard Worker}
395