xref: /aosp_15_r20/external/pigweed/pw_build/python_action.gni (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker# Copyright 2020 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_build/python_gn_args.gni")
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Worker# Defines an action that runs a Python script.
20*61c4878aSAndroid Build Coastguard Worker#
21*61c4878aSAndroid Build Coastguard Worker# This wraps a regular Python script GN action with an invocation of a script-
22*61c4878aSAndroid Build Coastguard Worker# runner script that adds useful features. pw_python_action() uses the same
23*61c4878aSAndroid Build Coastguard Worker# actions as GN's action(), with the following additions or changes:
24*61c4878aSAndroid Build Coastguard Worker#
25*61c4878aSAndroid Build Coastguard Worker#   module          May be used in place of the script argument to run the
26*61c4878aSAndroid Build Coastguard Worker#                   provided Python module with `python -m` instead of a script.
27*61c4878aSAndroid Build Coastguard Worker#                   Either script or module must be provided.
28*61c4878aSAndroid Build Coastguard Worker#
29*61c4878aSAndroid Build Coastguard Worker#   capture_output  If true, script output is hidden unless the script fails
30*61c4878aSAndroid Build Coastguard Worker#                   with an error. Defaults to true.
31*61c4878aSAndroid Build Coastguard Worker#
32*61c4878aSAndroid Build Coastguard Worker#   stamp           File to touch if the script is successful. Actions that
33*61c4878aSAndroid Build Coastguard Worker#                   don't create output files can use this stamp file instead of
34*61c4878aSAndroid Build Coastguard Worker#                   creating their own placeholder file. If true, a generic file
35*61c4878aSAndroid Build Coastguard Worker#                   is used. If false or not set, no file is touched.
36*61c4878aSAndroid Build Coastguard Worker#
37*61c4878aSAndroid Build Coastguard Worker#   environment     Environment variables to set, passed as a list of NAME=VALUE
38*61c4878aSAndroid Build Coastguard Worker#                   strings.
39*61c4878aSAndroid Build Coastguard Worker#
40*61c4878aSAndroid Build Coastguard Worker#   args            Same as the standard action args, except special expressions
41*61c4878aSAndroid Build Coastguard Worker#                   may be used to extract information not normally accessible
42*61c4878aSAndroid Build Coastguard Worker#                   in GN. These include the following:
43*61c4878aSAndroid Build Coastguard Worker#
44*61c4878aSAndroid Build Coastguard Worker#                     <TARGET_FILE(//some/label:here)> - expands to the
45*61c4878aSAndroid Build Coastguard Worker#                         output file (such as a .a or .elf) from a GN target
46*61c4878aSAndroid Build Coastguard Worker#                     <TARGET_FILE_IF_EXISTS(//some/label:here)> - expands to
47*61c4878aSAndroid Build Coastguard Worker#                         the output file if the target exists, or nothing
48*61c4878aSAndroid Build Coastguard Worker#                     <TARGET_OBJECTS(//some/label:here)> - expands to the
49*61c4878aSAndroid Build Coastguard Worker#                         object files produced by the provided GN target
50*61c4878aSAndroid Build Coastguard Worker#
51*61c4878aSAndroid Build Coastguard Worker#   python_deps     Dependencies on pw_python_package or related Python targets.
52*61c4878aSAndroid Build Coastguard Worker#
53*61c4878aSAndroid Build Coastguard Worker#   python_metadata_deps  Python-related dependencies that are only used as deps
54*61c4878aSAndroid Build Coastguard Worker#                         for generating Python package metadata list, not the
55*61c4878aSAndroid Build Coastguard Worker#                         overall Python script action. This should rarely be
56*61c4878aSAndroid Build Coastguard Worker#                         used by non-Pigweed code.
57*61c4878aSAndroid Build Coastguard Worker#
58*61c4878aSAndroid Build Coastguard Worker#   working_directory  Switch to the provided working directory before running
59*61c4878aSAndroid Build Coastguard Worker#                      the Python script or action.
60*61c4878aSAndroid Build Coastguard Worker#
61*61c4878aSAndroid Build Coastguard Worker#   command_launcher   Arguments to prepend to the Python command, e.g.
62*61c4878aSAndroid Build Coastguard Worker#                      '/usr/bin/fakeroot --' to run the Python script within a
63*61c4878aSAndroid Build Coastguard Worker#                      fakeroot environment.
64*61c4878aSAndroid Build Coastguard Worker#
65*61c4878aSAndroid Build Coastguard Worker#   venv            Optional gn target of the pw_python_venv that should be used
66*61c4878aSAndroid Build Coastguard Worker#                   to run this action.
67*61c4878aSAndroid Build Coastguard Worker#
68*61c4878aSAndroid Build Coastguard Workertemplate("pw_python_action") {
69*61c4878aSAndroid Build Coastguard Worker  assert(defined(invoker.script) != defined(invoker.module),
70*61c4878aSAndroid Build Coastguard Worker         "pw_python_action requires either 'script' or 'module'")
71*61c4878aSAndroid Build Coastguard Worker
72*61c4878aSAndroid Build Coastguard Worker  _script_args = [
73*61c4878aSAndroid Build Coastguard Worker    # GN root directory relative to the build directory (in which the runner
74*61c4878aSAndroid Build Coastguard Worker    # script is invoked).
75*61c4878aSAndroid Build Coastguard Worker    "--gn-root",
76*61c4878aSAndroid Build Coastguard Worker    rebase_path("//", root_build_dir),
77*61c4878aSAndroid Build Coastguard Worker
78*61c4878aSAndroid Build Coastguard Worker    # Current directory, used to resolve relative paths.
79*61c4878aSAndroid Build Coastguard Worker    "--current-path",
80*61c4878aSAndroid Build Coastguard Worker    rebase_path(".", root_build_dir),
81*61c4878aSAndroid Build Coastguard Worker
82*61c4878aSAndroid Build Coastguard Worker    "--default-toolchain=$default_toolchain",
83*61c4878aSAndroid Build Coastguard Worker    "--current-toolchain=$current_toolchain",
84*61c4878aSAndroid Build Coastguard Worker  ]
85*61c4878aSAndroid Build Coastguard Worker
86*61c4878aSAndroid Build Coastguard Worker  _use_build_dir_virtualenv = true
87*61c4878aSAndroid Build Coastguard Worker
88*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.environment)) {
89*61c4878aSAndroid Build Coastguard Worker    foreach(variable, invoker.environment) {
90*61c4878aSAndroid Build Coastguard Worker      _script_args += [ "--env=$variable" ]
91*61c4878aSAndroid Build Coastguard Worker    }
92*61c4878aSAndroid Build Coastguard Worker  }
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.inputs)) {
95*61c4878aSAndroid Build Coastguard Worker    _inputs = invoker.inputs
96*61c4878aSAndroid Build Coastguard Worker  } else {
97*61c4878aSAndroid Build Coastguard Worker    _inputs = []
98*61c4878aSAndroid Build Coastguard Worker  }
99*61c4878aSAndroid Build Coastguard Worker
100*61c4878aSAndroid Build Coastguard Worker  # List the script to run as an input so that the action is re-run when it is
101*61c4878aSAndroid Build Coastguard Worker  # modified.
102*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.script)) {
103*61c4878aSAndroid Build Coastguard Worker    _inputs += [ invoker.script ]
104*61c4878aSAndroid Build Coastguard Worker  }
105*61c4878aSAndroid Build Coastguard Worker
106*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.outputs)) {
107*61c4878aSAndroid Build Coastguard Worker    _outputs = invoker.outputs
108*61c4878aSAndroid Build Coastguard Worker  } else {
109*61c4878aSAndroid Build Coastguard Worker    _outputs = []
110*61c4878aSAndroid Build Coastguard Worker  }
111*61c4878aSAndroid Build Coastguard Worker
112*61c4878aSAndroid Build Coastguard Worker  # If a stamp file is requested, add it as an output of the runner script.
113*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.stamp) && invoker.stamp != false) {
114*61c4878aSAndroid Build Coastguard Worker    if (invoker.stamp == true) {
115*61c4878aSAndroid Build Coastguard Worker      _stamp_file = "$target_gen_dir/$target_name.pw_pystamp"
116*61c4878aSAndroid Build Coastguard Worker    } else {
117*61c4878aSAndroid Build Coastguard Worker      _stamp_file = invoker.stamp
118*61c4878aSAndroid Build Coastguard Worker    }
119*61c4878aSAndroid Build Coastguard Worker
120*61c4878aSAndroid Build Coastguard Worker    _outputs += [ _stamp_file ]
121*61c4878aSAndroid Build Coastguard Worker    _script_args += [
122*61c4878aSAndroid Build Coastguard Worker      "--touch",
123*61c4878aSAndroid Build Coastguard Worker      rebase_path(_stamp_file, root_build_dir),
124*61c4878aSAndroid Build Coastguard Worker    ]
125*61c4878aSAndroid Build Coastguard Worker  }
126*61c4878aSAndroid Build Coastguard Worker
127*61c4878aSAndroid Build Coastguard Worker  # Capture output or not (defaults to true).
128*61c4878aSAndroid Build Coastguard Worker  if (!defined(invoker.capture_output) || invoker.capture_output) {
129*61c4878aSAndroid Build Coastguard Worker    _script_args += [ "--capture-output" ]
130*61c4878aSAndroid Build Coastguard Worker  }
131*61c4878aSAndroid Build Coastguard Worker
132*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.module)) {
133*61c4878aSAndroid Build Coastguard Worker    _script_args += [
134*61c4878aSAndroid Build Coastguard Worker      "--module",
135*61c4878aSAndroid Build Coastguard Worker      invoker.module,
136*61c4878aSAndroid Build Coastguard Worker    ]
137*61c4878aSAndroid Build Coastguard Worker
138*61c4878aSAndroid Build Coastguard Worker    # Pip installs should only ever need to occur in the Pigweed
139*61c4878aSAndroid Build Coastguard Worker    # environment. For these actions do not use the build_dir virtualenv.
140*61c4878aSAndroid Build Coastguard Worker    if (invoker.module == "pip") {
141*61c4878aSAndroid Build Coastguard Worker      _use_build_dir_virtualenv = false
142*61c4878aSAndroid Build Coastguard Worker    }
143*61c4878aSAndroid Build Coastguard Worker  }
144*61c4878aSAndroid Build Coastguard Worker
145*61c4878aSAndroid Build Coastguard Worker  # Override to force using or not using the venv.
146*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker._pw_internal_run_in_venv)) {
147*61c4878aSAndroid Build Coastguard Worker    _use_build_dir_virtualenv = invoker._pw_internal_run_in_venv
148*61c4878aSAndroid Build Coastguard Worker  }
149*61c4878aSAndroid Build Coastguard Worker
150*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.working_directory)) {
151*61c4878aSAndroid Build Coastguard Worker    _script_args += [
152*61c4878aSAndroid Build Coastguard Worker      "--working-directory",
153*61c4878aSAndroid Build Coastguard Worker      invoker.working_directory,
154*61c4878aSAndroid Build Coastguard Worker    ]
155*61c4878aSAndroid Build Coastguard Worker  }
156*61c4878aSAndroid Build Coastguard Worker
157*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.command_launcher)) {
158*61c4878aSAndroid Build Coastguard Worker    _script_args += [
159*61c4878aSAndroid Build Coastguard Worker      "--command-launcher",
160*61c4878aSAndroid Build Coastguard Worker      invoker.command_launcher,
161*61c4878aSAndroid Build Coastguard Worker    ]
162*61c4878aSAndroid Build Coastguard Worker  }
163*61c4878aSAndroid Build Coastguard Worker
164*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker._pw_action_type)) {
165*61c4878aSAndroid Build Coastguard Worker    _action_type = invoker._pw_action_type
166*61c4878aSAndroid Build Coastguard Worker  } else {
167*61c4878aSAndroid Build Coastguard Worker    _action_type = "action"
168*61c4878aSAndroid Build Coastguard Worker  }
169*61c4878aSAndroid Build Coastguard Worker
170*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.deps)) {
171*61c4878aSAndroid Build Coastguard Worker    _deps = invoker.deps
172*61c4878aSAndroid Build Coastguard Worker  } else {
173*61c4878aSAndroid Build Coastguard Worker    _deps = []
174*61c4878aSAndroid Build Coastguard Worker  }
175*61c4878aSAndroid Build Coastguard Worker
176*61c4878aSAndroid Build Coastguard Worker  _py_metadata_deps = []
177*61c4878aSAndroid Build Coastguard Worker
178*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.python_deps)) {
179*61c4878aSAndroid Build Coastguard Worker    foreach(dep, invoker.python_deps) {
180*61c4878aSAndroid Build Coastguard Worker      _deps += [ get_label_info(dep, "label_no_toolchain") + ".install(" +
181*61c4878aSAndroid Build Coastguard Worker                 get_label_info(dep, "toolchain") + ")" ]
182*61c4878aSAndroid Build Coastguard Worker
183*61c4878aSAndroid Build Coastguard Worker      # Ensure each python_dep is added to the PYTHONPATH by depinding on the
184*61c4878aSAndroid Build Coastguard Worker      # ._package_metadata subtarget.
185*61c4878aSAndroid Build Coastguard Worker      _py_metadata_deps += [ get_label_info(dep, "label_no_toolchain") +
186*61c4878aSAndroid Build Coastguard Worker                             "._package_metadata($pw_build_PYTHON_TOOLCHAIN)" ]
187*61c4878aSAndroid Build Coastguard Worker    }
188*61c4878aSAndroid Build Coastguard Worker
189*61c4878aSAndroid Build Coastguard Worker    # Add the base target as a dep so the action reruns when any source files
190*61c4878aSAndroid Build Coastguard Worker    # change, even if the package does not have to be reinstalled.
191*61c4878aSAndroid Build Coastguard Worker    _deps += invoker.python_deps
192*61c4878aSAndroid Build Coastguard Worker    _deps += _py_metadata_deps
193*61c4878aSAndroid Build Coastguard Worker  }
194*61c4878aSAndroid Build Coastguard Worker
195*61c4878aSAndroid Build Coastguard Worker  # Check for additional PYTHONPATH dependencies.
196*61c4878aSAndroid Build Coastguard Worker  _extra_python_metadata_deps = []
197*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.python_metadata_deps)) {
198*61c4878aSAndroid Build Coastguard Worker    foreach(dep, invoker.python_metadata_deps) {
199*61c4878aSAndroid Build Coastguard Worker      _extra_python_metadata_deps +=
200*61c4878aSAndroid Build Coastguard Worker          [ get_label_info(dep, "label_no_toolchain") +
201*61c4878aSAndroid Build Coastguard Worker            "._package_metadata($pw_build_PYTHON_TOOLCHAIN)" ]
202*61c4878aSAndroid Build Coastguard Worker    }
203*61c4878aSAndroid Build Coastguard Worker  }
204*61c4878aSAndroid Build Coastguard Worker
205*61c4878aSAndroid Build Coastguard Worker  _metadata_path_list_file =
206*61c4878aSAndroid Build Coastguard Worker      "${target_gen_dir}/${target_name}_metadata_path_list.txt"
207*61c4878aSAndroid Build Coastguard Worker
208*61c4878aSAndroid Build Coastguard Worker  # GN metadata only dependencies used for setting PYTHONPATH.
209*61c4878aSAndroid Build Coastguard Worker  _metadata_deps = _py_metadata_deps + _extra_python_metadata_deps
210*61c4878aSAndroid Build Coastguard Worker
211*61c4878aSAndroid Build Coastguard Worker  # Build a list of relative paths containing all the python
212*61c4878aSAndroid Build Coastguard Worker  # package_metadata.json files we depend on.
213*61c4878aSAndroid Build Coastguard Worker  _metadata_path_list_target = "${target_name}._metadata_path_list.txt"
214*61c4878aSAndroid Build Coastguard Worker  generated_file(_metadata_path_list_target) {
215*61c4878aSAndroid Build Coastguard Worker    data_keys = [ "pw_python_package_metadata_json" ]
216*61c4878aSAndroid Build Coastguard Worker    rebase = root_build_dir
217*61c4878aSAndroid Build Coastguard Worker    deps = _metadata_deps
218*61c4878aSAndroid Build Coastguard Worker    outputs = [ _metadata_path_list_file ]
219*61c4878aSAndroid Build Coastguard Worker  }
220*61c4878aSAndroid Build Coastguard Worker  _deps += [ ":${_metadata_path_list_target}" ]
221*61c4878aSAndroid Build Coastguard Worker
222*61c4878aSAndroid Build Coastguard Worker  # Set venv options if needed.
223*61c4878aSAndroid Build Coastguard Worker  if (_use_build_dir_virtualenv) {
224*61c4878aSAndroid Build Coastguard Worker    _venv_target_label = pw_build_PYTHON_BUILD_VENV
225*61c4878aSAndroid Build Coastguard Worker    if (defined(invoker.venv)) {
226*61c4878aSAndroid Build Coastguard Worker      _venv_target_label = invoker.venv
227*61c4878aSAndroid Build Coastguard Worker    }
228*61c4878aSAndroid Build Coastguard Worker    _venv_target_label =
229*61c4878aSAndroid Build Coastguard Worker        get_label_info(_venv_target_label, "label_no_toolchain") +
230*61c4878aSAndroid Build Coastguard Worker        "($pw_build_PYTHON_TOOLCHAIN)"
231*61c4878aSAndroid Build Coastguard Worker
232*61c4878aSAndroid Build Coastguard Worker    _venv_json =
233*61c4878aSAndroid Build Coastguard Worker        get_label_info(_venv_target_label, "target_gen_dir") + "/" +
234*61c4878aSAndroid Build Coastguard Worker        get_label_info(_venv_target_label, "name") + "/venv_metadata.json"
235*61c4878aSAndroid Build Coastguard Worker    _script_args += [
236*61c4878aSAndroid Build Coastguard Worker      "--python-virtualenv-config",
237*61c4878aSAndroid Build Coastguard Worker      rebase_path(_venv_json, root_build_dir),
238*61c4878aSAndroid Build Coastguard Worker    ]
239*61c4878aSAndroid Build Coastguard Worker  }
240*61c4878aSAndroid Build Coastguard Worker  _script_args += [
241*61c4878aSAndroid Build Coastguard Worker    "--python-dep-list-files",
242*61c4878aSAndroid Build Coastguard Worker    rebase_path(_metadata_path_list_file, root_build_dir),
243*61c4878aSAndroid Build Coastguard Worker  ]
244*61c4878aSAndroid Build Coastguard Worker
245*61c4878aSAndroid Build Coastguard Worker  # "--" indicates the end of arguments to the runner script.
246*61c4878aSAndroid Build Coastguard Worker  # Everything beyond this point is interpreted as the command and arguments
247*61c4878aSAndroid Build Coastguard Worker  # of the Python script to run.
248*61c4878aSAndroid Build Coastguard Worker  _script_args += [ "--" ]
249*61c4878aSAndroid Build Coastguard Worker
250*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.script)) {
251*61c4878aSAndroid Build Coastguard Worker    _script_args += [ rebase_path(invoker.script, root_build_dir) ]
252*61c4878aSAndroid Build Coastguard Worker  }
253*61c4878aSAndroid Build Coastguard Worker
254*61c4878aSAndroid Build Coastguard Worker  _forward_python_metadata_deps = false
255*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker._forward_python_metadata_deps)) {
256*61c4878aSAndroid Build Coastguard Worker    _forward_python_metadata_deps = true
257*61c4878aSAndroid Build Coastguard Worker  }
258*61c4878aSAndroid Build Coastguard Worker  if (_forward_python_metadata_deps) {
259*61c4878aSAndroid Build Coastguard Worker    _script_args += [
260*61c4878aSAndroid Build Coastguard Worker      "--python-dep-list-files",
261*61c4878aSAndroid Build Coastguard Worker      rebase_path(_metadata_path_list_file, root_build_dir),
262*61c4878aSAndroid Build Coastguard Worker    ]
263*61c4878aSAndroid Build Coastguard Worker  }
264*61c4878aSAndroid Build Coastguard Worker
265*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.args)) {
266*61c4878aSAndroid Build Coastguard Worker    _script_args += invoker.args
267*61c4878aSAndroid Build Coastguard Worker  }
268*61c4878aSAndroid Build Coastguard Worker
269*61c4878aSAndroid Build Coastguard Worker  # Assume third party PyPI deps should be available in the build_dir virtualenv.
270*61c4878aSAndroid Build Coastguard Worker  _install_venv_3p_deps = true
271*61c4878aSAndroid Build Coastguard Worker  if (!_use_build_dir_virtualenv ||
272*61c4878aSAndroid Build Coastguard Worker      (defined(invoker._skip_installing_external_python_deps) &&
273*61c4878aSAndroid Build Coastguard Worker       invoker._skip_installing_external_python_deps)) {
274*61c4878aSAndroid Build Coastguard Worker    _install_venv_3p_deps = false
275*61c4878aSAndroid Build Coastguard Worker  }
276*61c4878aSAndroid Build Coastguard Worker
277*61c4878aSAndroid Build Coastguard Worker  # Check that script or module is a present and not a no-op.
278*61c4878aSAndroid Build Coastguard Worker  _run_script_or_module = false
279*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.script) || defined(invoker.module)) {
280*61c4878aSAndroid Build Coastguard Worker    _run_script_or_module = true
281*61c4878aSAndroid Build Coastguard Worker  }
282*61c4878aSAndroid Build Coastguard Worker
283*61c4878aSAndroid Build Coastguard Worker  target(_action_type, target_name) {
284*61c4878aSAndroid Build Coastguard Worker    _ignore_vars = [
285*61c4878aSAndroid Build Coastguard Worker      "script",
286*61c4878aSAndroid Build Coastguard Worker      "args",
287*61c4878aSAndroid Build Coastguard Worker      "deps",
288*61c4878aSAndroid Build Coastguard Worker      "inputs",
289*61c4878aSAndroid Build Coastguard Worker      "outputs",
290*61c4878aSAndroid Build Coastguard Worker    ]
291*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*", _ignore_vars)
292*61c4878aSAndroid Build Coastguard Worker
293*61c4878aSAndroid Build Coastguard Worker    script = "$dir_pw_build/py/pw_build/python_runner.py"
294*61c4878aSAndroid Build Coastguard Worker    args = _script_args
295*61c4878aSAndroid Build Coastguard Worker    inputs = _inputs
296*61c4878aSAndroid Build Coastguard Worker    outputs = _outputs
297*61c4878aSAndroid Build Coastguard Worker    deps = _deps
298*61c4878aSAndroid Build Coastguard Worker
299*61c4878aSAndroid Build Coastguard Worker    if (_install_venv_3p_deps && _run_script_or_module) {
300*61c4878aSAndroid Build Coastguard Worker      deps += [ get_label_info(_venv_target_label, "label_no_toolchain") +
301*61c4878aSAndroid Build Coastguard Worker                "._install_3p_deps($pw_build_PYTHON_TOOLCHAIN)" ]
302*61c4878aSAndroid Build Coastguard Worker    }
303*61c4878aSAndroid Build Coastguard Worker  }
304*61c4878aSAndroid Build Coastguard Worker}
305*61c4878aSAndroid Build Coastguard Worker
306*61c4878aSAndroid Build Coastguard Worker# Runs pw_python_action once per file over a set of sources.
307*61c4878aSAndroid Build Coastguard Worker#
308*61c4878aSAndroid Build Coastguard Worker# This template brings pw_python_action's features to action_foreach. Usage is
309*61c4878aSAndroid Build Coastguard Worker# the same as pw_python_action, except that sources must be provided and source
310*61c4878aSAndroid Build Coastguard Worker# expansion (e.g. "{{source}}") may be used in args and outputs.
311*61c4878aSAndroid Build Coastguard Worker#
312*61c4878aSAndroid Build Coastguard Worker# See the pw_python_action and action_foreach documentation for full details.
313*61c4878aSAndroid Build Coastguard Workertemplate("pw_python_action_foreach") {
314*61c4878aSAndroid Build Coastguard Worker  assert(defined(invoker.sources) && invoker.sources != [],
315*61c4878aSAndroid Build Coastguard Worker         "pw_python_action_foreach requires a list of one or more sources")
316*61c4878aSAndroid Build Coastguard Worker
317*61c4878aSAndroid Build Coastguard Worker  pw_python_action(target_name) {
318*61c4878aSAndroid Build Coastguard Worker    if (defined(invoker.stamp) && invoker.stamp != false) {
319*61c4878aSAndroid Build Coastguard Worker      if (invoker.stamp == true) {
320*61c4878aSAndroid Build Coastguard Worker        # Use source file names in the generated stamp file path so they are
321*61c4878aSAndroid Build Coastguard Worker        # unique for each source.
322*61c4878aSAndroid Build Coastguard Worker        stamp = "$target_gen_dir/{{source_file_part}}.pw_pystamp"
323*61c4878aSAndroid Build Coastguard Worker      } else {
324*61c4878aSAndroid Build Coastguard Worker        stamp = invoker.stamp
325*61c4878aSAndroid Build Coastguard Worker      }
326*61c4878aSAndroid Build Coastguard Worker    } else {
327*61c4878aSAndroid Build Coastguard Worker      stamp = false
328*61c4878aSAndroid Build Coastguard Worker    }
329*61c4878aSAndroid Build Coastguard Worker
330*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*", [ "stamp" ])
331*61c4878aSAndroid Build Coastguard Worker
332*61c4878aSAndroid Build Coastguard Worker    _pw_action_type = "action_foreach"
333*61c4878aSAndroid Build Coastguard Worker  }
334*61c4878aSAndroid Build Coastguard Worker}
335