xref: /aosp_15_r20/external/pigweed/pw_build/python_dist.gni (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker# Copyright 2021 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/error.gni")
18*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/python.gni")
19*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/python_action.gni")
20*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/python_gn_args.gni")
21*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/zip.gni")
22*61c4878aSAndroid Build Coastguard Worker
23*61c4878aSAndroid Build Coastguard Worker# Builds a directory containing a collection of Python wheels.
24*61c4878aSAndroid Build Coastguard Worker#
25*61c4878aSAndroid Build Coastguard Worker# Given one or more pw_python_package targets, this target will build their
26*61c4878aSAndroid Build Coastguard Worker# .wheel sub-targets along with the .wheel sub-targets of all dependencies,
27*61c4878aSAndroid Build Coastguard Worker# direct and indirect, as understood by GN. The resulting .whl files will be
28*61c4878aSAndroid Build Coastguard Worker# collected into a single directory called 'python_wheels'.
29*61c4878aSAndroid Build Coastguard Worker#
30*61c4878aSAndroid Build Coastguard Worker# Args:
31*61c4878aSAndroid Build Coastguard Worker#   packages: A list of pw_python_package targets whose wheels should be
32*61c4878aSAndroid Build Coastguard Worker#       included; their dependencies will be pulled in as wheels also.
33*61c4878aSAndroid Build Coastguard Worker#   directory: output directory for the wheels; defaults to
34*61c4878aSAndroid Build Coastguard Worker#       $target_out_dir/$target_name
35*61c4878aSAndroid Build Coastguard Worker#   deps: additional dependencies
36*61c4878aSAndroid Build Coastguard Worker#
37*61c4878aSAndroid Build Coastguard Workertemplate("pw_python_wheels") {
38*61c4878aSAndroid Build Coastguard Worker  _wheel_paths_path = "${target_gen_dir}/${target_name}_wheel_paths.txt"
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard Worker  _deps = []
41*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.deps)) {
42*61c4878aSAndroid Build Coastguard Worker    _deps = invoker.deps
43*61c4878aSAndroid Build Coastguard Worker  }
44*61c4878aSAndroid Build Coastguard Worker
45*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.directory)) {
46*61c4878aSAndroid Build Coastguard Worker    _directory = invoker.directory
47*61c4878aSAndroid Build Coastguard Worker  } else {
48*61c4878aSAndroid Build Coastguard Worker    _directory = "$target_out_dir/$target_name"
49*61c4878aSAndroid Build Coastguard Worker  }
50*61c4878aSAndroid Build Coastguard Worker
51*61c4878aSAndroid Build Coastguard Worker  _packages = []
52*61c4878aSAndroid Build Coastguard Worker  foreach(_pkg, invoker.packages) {
53*61c4878aSAndroid Build Coastguard Worker    _pkg_name = get_label_info(_pkg, "label_no_toolchain")
54*61c4878aSAndroid Build Coastguard Worker    _pkg_toolchain = get_label_info(_pkg, "toolchain")
55*61c4878aSAndroid Build Coastguard Worker    _packages += [ "${_pkg_name}.wheel(${_pkg_toolchain})" ]
56*61c4878aSAndroid Build Coastguard Worker  }
57*61c4878aSAndroid Build Coastguard Worker
58*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.venv)) {
59*61c4878aSAndroid Build Coastguard Worker    _venv_target_label = pw_build_PYTHON_BUILD_VENV
60*61c4878aSAndroid Build Coastguard Worker    _venv_target_label = invoker.venv
61*61c4878aSAndroid Build Coastguard Worker    _venv_target_label =
62*61c4878aSAndroid Build Coastguard Worker        get_label_info(_venv_target_label, "label_no_toolchain")
63*61c4878aSAndroid Build Coastguard Worker    _packages +=
64*61c4878aSAndroid Build Coastguard Worker        [ "${_venv_target_label}.vendor_wheels($pw_build_PYTHON_TOOLCHAIN)" ]
65*61c4878aSAndroid Build Coastguard Worker  }
66*61c4878aSAndroid Build Coastguard Worker
67*61c4878aSAndroid Build Coastguard Worker  # Build a list of relative paths containing all the wheels we depend on.
68*61c4878aSAndroid Build Coastguard Worker  generated_file("${target_name}._wheel_paths") {
69*61c4878aSAndroid Build Coastguard Worker    data_keys = [ "pw_python_package_wheels" ]
70*61c4878aSAndroid Build Coastguard Worker    rebase = root_build_dir
71*61c4878aSAndroid Build Coastguard Worker    deps = _packages
72*61c4878aSAndroid Build Coastguard Worker    outputs = [ _wheel_paths_path ]
73*61c4878aSAndroid Build Coastguard Worker  }
74*61c4878aSAndroid Build Coastguard Worker
75*61c4878aSAndroid Build Coastguard Worker  pw_python_action(target_name) {
76*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, [ "public_deps" ])
77*61c4878aSAndroid Build Coastguard Worker    deps = _deps + [ ":$target_name._wheel_paths" ]
78*61c4878aSAndroid Build Coastguard Worker    module = "pw_build.collect_wheels"
79*61c4878aSAndroid Build Coastguard Worker    python_deps = [ "$dir_pw_build/py" ]
80*61c4878aSAndroid Build Coastguard Worker
81*61c4878aSAndroid Build Coastguard Worker    args = [
82*61c4878aSAndroid Build Coastguard Worker      "--prefix",
83*61c4878aSAndroid Build Coastguard Worker      rebase_path(root_build_dir, root_build_dir),
84*61c4878aSAndroid Build Coastguard Worker      "--suffix",
85*61c4878aSAndroid Build Coastguard Worker      rebase_path(_wheel_paths_path, root_build_dir),
86*61c4878aSAndroid Build Coastguard Worker      "--out-dir",
87*61c4878aSAndroid Build Coastguard Worker      rebase_path(_directory, root_build_dir),
88*61c4878aSAndroid Build Coastguard Worker    ]
89*61c4878aSAndroid Build Coastguard Worker
90*61c4878aSAndroid Build Coastguard Worker    stamp = true
91*61c4878aSAndroid Build Coastguard Worker  }
92*61c4878aSAndroid Build Coastguard Worker}
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker# Builds a .zip containing Python wheels and setup scripts.
95*61c4878aSAndroid Build Coastguard Worker#
96*61c4878aSAndroid Build Coastguard Worker# The resulting .zip archive will contain a directory with Python wheels for
97*61c4878aSAndroid Build Coastguard Worker# all pw_python_package targets listed in 'packages', plus wheels for any
98*61c4878aSAndroid Build Coastguard Worker# pw_python_package targets those packages depend on, directly or indirectly,
99*61c4878aSAndroid Build Coastguard Worker# as understood by GN.
100*61c4878aSAndroid Build Coastguard Worker#
101*61c4878aSAndroid Build Coastguard Worker# In addition to Python wheels, the resulting .zip will also contain simple
102*61c4878aSAndroid Build Coastguard Worker# setup scripts for Linux, MacOS, and Windows that take care of creating a
103*61c4878aSAndroid Build Coastguard Worker# Python venv and installing all the included wheels into it, and a README.md
104*61c4878aSAndroid Build Coastguard Worker# file with setup and usage instructions.
105*61c4878aSAndroid Build Coastguard Worker#
106*61c4878aSAndroid Build Coastguard Worker# Args:
107*61c4878aSAndroid Build Coastguard Worker#   packages: A list of pw_python_package targets whose wheels should be
108*61c4878aSAndroid Build Coastguard Worker#       included; their dependencies will be pulled in as wheels also.
109*61c4878aSAndroid Build Coastguard Worker#   inputs: An optional list of extra files to include in the generated .zip,
110*61c4878aSAndroid Build Coastguard Worker#       formatted the same was as the 'inputs' argument to pw_zip targets.
111*61c4878aSAndroid Build Coastguard Worker#   dirs: An optional list of directories to include in the generated .zip,
112*61c4878aSAndroid Build Coastguard Worker#       formatted the same way as the 'dirs' argument to pw_zip targets.
113*61c4878aSAndroid Build Coastguard Workertemplate("pw_python_zip_with_setup") {
114*61c4878aSAndroid Build Coastguard Worker  _outer_name = target_name
115*61c4878aSAndroid Build Coastguard Worker  _zip_path = "${target_out_dir}/${target_name}.zip"
116*61c4878aSAndroid Build Coastguard Worker
117*61c4878aSAndroid Build Coastguard Worker  _inputs = []
118*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.inputs)) {
119*61c4878aSAndroid Build Coastguard Worker    _inputs = invoker.inputs
120*61c4878aSAndroid Build Coastguard Worker  }
121*61c4878aSAndroid Build Coastguard Worker  _dirs = []
122*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.dirs)) {
123*61c4878aSAndroid Build Coastguard Worker    _dirs = invoker.dirs
124*61c4878aSAndroid Build Coastguard Worker  }
125*61c4878aSAndroid Build Coastguard Worker  _public_deps = []
126*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.public_deps)) {
127*61c4878aSAndroid Build Coastguard Worker    _public_deps = invoker.public_deps
128*61c4878aSAndroid Build Coastguard Worker  }
129*61c4878aSAndroid Build Coastguard Worker
130*61c4878aSAndroid Build Coastguard Worker  pw_python_wheels("$target_name.wheels") {
131*61c4878aSAndroid Build Coastguard Worker    packages = invoker.packages
132*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker,
133*61c4878aSAndroid Build Coastguard Worker                           [
134*61c4878aSAndroid Build Coastguard Worker                             "deps",
135*61c4878aSAndroid Build Coastguard Worker                             "venv",
136*61c4878aSAndroid Build Coastguard Worker                           ])
137*61c4878aSAndroid Build Coastguard Worker  }
138*61c4878aSAndroid Build Coastguard Worker
139*61c4878aSAndroid Build Coastguard Worker  pw_zip(target_name) {
140*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, [ "deps" ])
141*61c4878aSAndroid Build Coastguard Worker    inputs = _inputs + [
142*61c4878aSAndroid Build Coastguard Worker               "$dir_pw_build/python_dist/setup.bat > /${target_name}/",
143*61c4878aSAndroid Build Coastguard Worker               "$dir_pw_build/python_dist/setup.sh > /${target_name}/",
144*61c4878aSAndroid Build Coastguard Worker             ]
145*61c4878aSAndroid Build Coastguard Worker
146*61c4878aSAndroid Build Coastguard Worker    dirs = _dirs + [ "$target_out_dir/$target_name.wheels/ > /$target_name/python_wheels/" ]
147*61c4878aSAndroid Build Coastguard Worker
148*61c4878aSAndroid Build Coastguard Worker    output = _zip_path
149*61c4878aSAndroid Build Coastguard Worker
150*61c4878aSAndroid Build Coastguard Worker    # TODO: b/235245034 - Remove the plumbing-through of invoker's public_deps.
151*61c4878aSAndroid Build Coastguard Worker    public_deps = _public_deps + [ ":${_outer_name}.wheels" ]
152*61c4878aSAndroid Build Coastguard Worker
153*61c4878aSAndroid Build Coastguard Worker    if (defined(invoker.venv)) {
154*61c4878aSAndroid Build Coastguard Worker      _venv_target_label = get_label_info(invoker.venv, "label_no_toolchain")
155*61c4878aSAndroid Build Coastguard Worker      _requirements_target_name =
156*61c4878aSAndroid Build Coastguard Worker          get_label_info("${_venv_target_label}($pw_build_PYTHON_TOOLCHAIN)",
157*61c4878aSAndroid Build Coastguard Worker                         "name")
158*61c4878aSAndroid Build Coastguard Worker      _requirements_gen_dir =
159*61c4878aSAndroid Build Coastguard Worker          get_label_info("${_venv_target_label}($pw_build_PYTHON_TOOLCHAIN)",
160*61c4878aSAndroid Build Coastguard Worker                         "target_gen_dir")
161*61c4878aSAndroid Build Coastguard Worker
162*61c4878aSAndroid Build Coastguard Worker      inputs += [ "$_requirements_gen_dir/$_requirements_target_name/compiled_requirements.txt > /${target_name}/requirements.txt" ]
163*61c4878aSAndroid Build Coastguard Worker
164*61c4878aSAndroid Build Coastguard Worker      public_deps += [ "${_venv_target_label}._compile_requirements($pw_build_PYTHON_TOOLCHAIN)" ]
165*61c4878aSAndroid Build Coastguard Worker    }
166*61c4878aSAndroid Build Coastguard Worker  }
167*61c4878aSAndroid Build Coastguard Worker}
168*61c4878aSAndroid Build Coastguard Worker
169*61c4878aSAndroid Build Coastguard Worker# Generates a directory of Python packages from source files suitable for
170*61c4878aSAndroid Build Coastguard Worker# deployment outside of the project developer environment.
171*61c4878aSAndroid Build Coastguard Worker#
172*61c4878aSAndroid Build Coastguard Worker# The resulting directory contains only files mentioned in each package's
173*61c4878aSAndroid Build Coastguard Worker# setup.cfg file. This is useful for bundling multiple Python packages up
174*61c4878aSAndroid Build Coastguard Worker# into a single package for distribution to other locations like
175*61c4878aSAndroid Build Coastguard Worker# http://pypi.org.
176*61c4878aSAndroid Build Coastguard Worker#
177*61c4878aSAndroid Build Coastguard Worker# Args:
178*61c4878aSAndroid Build Coastguard Worker#   packages: A list of pw_python_package targets to be installed into the build
179*61c4878aSAndroid Build Coastguard Worker#     directory. Their dependencies will be pulled in as wheels also.
180*61c4878aSAndroid Build Coastguard Worker#
181*61c4878aSAndroid Build Coastguard Worker#   include_tests: If true, copy Python package tests to a `tests` subdir.
182*61c4878aSAndroid Build Coastguard Worker#
183*61c4878aSAndroid Build Coastguard Worker#   extra_files: A list of extra files that should be included in the output. The
184*61c4878aSAndroid Build Coastguard Worker#     format of each item in this list follows this convention:
185*61c4878aSAndroid Build Coastguard Worker#       //some/nested/source_file > nested/destination_file
186*61c4878aSAndroid Build Coastguard Worker#
187*61c4878aSAndroid Build Coastguard Worker#   generate_setup_cfg: A scope containing either common_config_file or 'name'
188*61c4878aSAndroid Build Coastguard Worker#     and 'version' If included this creates a merged setup.cfg for all python
189*61c4878aSAndroid Build Coastguard Worker#     Packages using either a common_config_file as a base or name and version
190*61c4878aSAndroid Build Coastguard Worker#     strings. This scope can optionally include:
191*61c4878aSAndroid Build Coastguard Worker#
192*61c4878aSAndroid Build Coastguard Worker#     include_default_pyproject_file: Include a standard pyproject.toml file
193*61c4878aSAndroid Build Coastguard Worker#       that uses setuptools.
194*61c4878aSAndroid Build Coastguard Worker#
195*61c4878aSAndroid Build Coastguard Worker#     append_git_sha_to_version: Append the current git SHA to the package
196*61c4878aSAndroid Build Coastguard Worker#       version string after a + sign.
197*61c4878aSAndroid Build Coastguard Worker#
198*61c4878aSAndroid Build Coastguard Worker#     append_date_to_version: Append the current date to the package version
199*61c4878aSAndroid Build Coastguard Worker#       string after a + sign.
200*61c4878aSAndroid Build Coastguard Worker#
201*61c4878aSAndroid Build Coastguard Worker#     include_extra_files_in_package_data: Add any extra_files to the setup.cfg
202*61c4878aSAndroid Build Coastguard Worker#       file under the [options.package_data] section.
203*61c4878aSAndroid Build Coastguard Worker#
204*61c4878aSAndroid Build Coastguard Worker#     auto_create_package_data_init_py_files: Default: true
205*61c4878aSAndroid Build Coastguard Worker#       Create __init__.py files as needed in all subdirs of extra_files when
206*61c4878aSAndroid Build Coastguard Worker#       including in [options.package_data].
207*61c4878aSAndroid Build Coastguard Worker#
208*61c4878aSAndroid Build Coastguard Workertemplate("pw_python_distribution") {
209*61c4878aSAndroid Build Coastguard Worker  _metadata_path_list_suffix = "_pw_python_distribution_metadata_path_list.txt"
210*61c4878aSAndroid Build Coastguard Worker  _output_dir = "${target_out_dir}/${target_name}/"
211*61c4878aSAndroid Build Coastguard Worker  _metadata_json_file_list =
212*61c4878aSAndroid Build Coastguard Worker      "${target_gen_dir}/${target_name}${_metadata_path_list_suffix}"
213*61c4878aSAndroid Build Coastguard Worker
214*61c4878aSAndroid Build Coastguard Worker  # If generating a setup.cfg file a common base file must be provided.
215*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.generate_setup_cfg)) {
216*61c4878aSAndroid Build Coastguard Worker    generate_setup_cfg = invoker.generate_setup_cfg
217*61c4878aSAndroid Build Coastguard Worker    assert(
218*61c4878aSAndroid Build Coastguard Worker        defined(generate_setup_cfg.common_config_file) ||
219*61c4878aSAndroid Build Coastguard Worker            (defined(generate_setup_cfg.name) &&
220*61c4878aSAndroid Build Coastguard Worker                 defined(generate_setup_cfg.version)),
221*61c4878aSAndroid Build Coastguard Worker        "Either 'common_config_file' or ('name' + 'version') are required in generate_setup_cfg")
222*61c4878aSAndroid Build Coastguard Worker  }
223*61c4878aSAndroid Build Coastguard Worker
224*61c4878aSAndroid Build Coastguard Worker  _inputs = []
225*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.generate_setup_cfg)) {
226*61c4878aSAndroid Build Coastguard Worker    if (defined(generate_setup_cfg.common_config_file)) {
227*61c4878aSAndroid Build Coastguard Worker      _inputs += [ generate_setup_cfg.common_config_file ]
228*61c4878aSAndroid Build Coastguard Worker    }
229*61c4878aSAndroid Build Coastguard Worker  }
230*61c4878aSAndroid Build Coastguard Worker  _extra_file_inputs = []
231*61c4878aSAndroid Build Coastguard Worker  _extra_file_args = []
232*61c4878aSAndroid Build Coastguard Worker
233*61c4878aSAndroid Build Coastguard Worker  # Convert extra_file strings to input, outputs and create_python_tree.py args.
234*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.extra_files)) {
235*61c4878aSAndroid Build Coastguard Worker    _delimiter = ">"
236*61c4878aSAndroid Build Coastguard Worker    _extra_file_outputs = []
237*61c4878aSAndroid Build Coastguard Worker    foreach(input, invoker.extra_files) {
238*61c4878aSAndroid Build Coastguard Worker      # Remove spaces before and after the delimiter
239*61c4878aSAndroid Build Coastguard Worker      input = string_replace(input, " $_delimiter", _delimiter)
240*61c4878aSAndroid Build Coastguard Worker      input = string_replace(input, "$_delimiter ", _delimiter)
241*61c4878aSAndroid Build Coastguard Worker
242*61c4878aSAndroid Build Coastguard Worker      input_list = []
243*61c4878aSAndroid Build Coastguard Worker      input_list = string_split(input, _delimiter)
244*61c4878aSAndroid Build Coastguard Worker
245*61c4878aSAndroid Build Coastguard Worker      # Save the input file
246*61c4878aSAndroid Build Coastguard Worker      _extra_file_inputs += [ input_list[0] ]
247*61c4878aSAndroid Build Coastguard Worker
248*61c4878aSAndroid Build Coastguard Worker      # Save the output file
249*61c4878aSAndroid Build Coastguard Worker      _this_output = _output_dir + "/" + input_list[1]
250*61c4878aSAndroid Build Coastguard Worker      _extra_file_outputs += [ _this_output ]
251*61c4878aSAndroid Build Coastguard Worker
252*61c4878aSAndroid Build Coastguard Worker      # Compose an arg for passing to create_python_tree.py with properly
253*61c4878aSAndroid Build Coastguard Worker      # rebased paths.
254*61c4878aSAndroid Build Coastguard Worker      _extra_file_args +=
255*61c4878aSAndroid Build Coastguard Worker          [ string_join(" $_delimiter ",
256*61c4878aSAndroid Build Coastguard Worker                        [
257*61c4878aSAndroid Build Coastguard Worker                          rebase_path(input_list[0], root_build_dir),
258*61c4878aSAndroid Build Coastguard Worker                          rebase_path(_this_output, root_build_dir),
259*61c4878aSAndroid Build Coastguard Worker                        ]) ]
260*61c4878aSAndroid Build Coastguard Worker    }
261*61c4878aSAndroid Build Coastguard Worker  }
262*61c4878aSAndroid Build Coastguard Worker
263*61c4878aSAndroid Build Coastguard Worker  _include_tests = defined(invoker.include_tests) && invoker.include_tests
264*61c4878aSAndroid Build Coastguard Worker
265*61c4878aSAndroid Build Coastguard Worker  _public_deps = []
266*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.public_deps)) {
267*61c4878aSAndroid Build Coastguard Worker    _public_deps += invoker.public_deps
268*61c4878aSAndroid Build Coastguard Worker  }
269*61c4878aSAndroid Build Coastguard Worker
270*61c4878aSAndroid Build Coastguard Worker  # Set source files for the Python package metadata json file.
271*61c4878aSAndroid Build Coastguard Worker  _sources = []
272*61c4878aSAndroid Build Coastguard Worker  _setup_sources = [
273*61c4878aSAndroid Build Coastguard Worker    "$_output_dir/pyproject.toml",
274*61c4878aSAndroid Build Coastguard Worker    "$_output_dir/setup.cfg",
275*61c4878aSAndroid Build Coastguard Worker  ]
276*61c4878aSAndroid Build Coastguard Worker  _test_sources = []
277*61c4878aSAndroid Build Coastguard Worker
278*61c4878aSAndroid Build Coastguard Worker  # Create the Python package_metadata.json file so this can be used as a
279*61c4878aSAndroid Build Coastguard Worker  # Python dependency.
280*61c4878aSAndroid Build Coastguard Worker  _package_metadata_json_file =
281*61c4878aSAndroid Build Coastguard Worker      "$target_gen_dir/$target_name/package_metadata.json"
282*61c4878aSAndroid Build Coastguard Worker
283*61c4878aSAndroid Build Coastguard Worker  # Get Python package metadata and write to disk as JSON.
284*61c4878aSAndroid Build Coastguard Worker  _package_metadata = {
285*61c4878aSAndroid Build Coastguard Worker    gn_target_name =
286*61c4878aSAndroid Build Coastguard Worker        get_label_info(":${invoker.target_name}", "label_no_toolchain")
287*61c4878aSAndroid Build Coastguard Worker
288*61c4878aSAndroid Build Coastguard Worker    # Get package source files
289*61c4878aSAndroid Build Coastguard Worker    sources = rebase_path(_sources, root_build_dir)
290*61c4878aSAndroid Build Coastguard Worker
291*61c4878aSAndroid Build Coastguard Worker    # Get setup.cfg, pyproject.toml, or setup.py file
292*61c4878aSAndroid Build Coastguard Worker    setup_sources = rebase_path(_setup_sources, root_build_dir)
293*61c4878aSAndroid Build Coastguard Worker
294*61c4878aSAndroid Build Coastguard Worker    # Get test source files
295*61c4878aSAndroid Build Coastguard Worker    tests = rebase_path(_test_sources, root_build_dir)
296*61c4878aSAndroid Build Coastguard Worker
297*61c4878aSAndroid Build Coastguard Worker    # Get package input files (package data)
298*61c4878aSAndroid Build Coastguard Worker    inputs = []
299*61c4878aSAndroid Build Coastguard Worker    if (defined(invoker.inputs)) {
300*61c4878aSAndroid Build Coastguard Worker      inputs = rebase_path(invoker.inputs, root_build_dir)
301*61c4878aSAndroid Build Coastguard Worker    }
302*61c4878aSAndroid Build Coastguard Worker    inputs += rebase_path(_extra_file_inputs, root_build_dir)
303*61c4878aSAndroid Build Coastguard Worker  }
304*61c4878aSAndroid Build Coastguard Worker
305*61c4878aSAndroid Build Coastguard Worker  # Finally, write out the json
306*61c4878aSAndroid Build Coastguard Worker  write_file(_package_metadata_json_file, _package_metadata, "json")
307*61c4878aSAndroid Build Coastguard Worker
308*61c4878aSAndroid Build Coastguard Worker  group("$target_name._package_metadata") {
309*61c4878aSAndroid Build Coastguard Worker    metadata = {
310*61c4878aSAndroid Build Coastguard Worker      pw_python_package_metadata_json = [ _package_metadata_json_file ]
311*61c4878aSAndroid Build Coastguard Worker    }
312*61c4878aSAndroid Build Coastguard Worker
313*61c4878aSAndroid Build Coastguard Worker    # Forward the package_metadata subtarget for all packages bundled in this
314*61c4878aSAndroid Build Coastguard Worker    # distribution.
315*61c4878aSAndroid Build Coastguard Worker    public_deps = []
316*61c4878aSAndroid Build Coastguard Worker    foreach(dep, invoker.packages) {
317*61c4878aSAndroid Build Coastguard Worker      public_deps += [ get_label_info(dep, "label_no_toolchain") +
318*61c4878aSAndroid Build Coastguard Worker                       "._package_metadata($pw_build_PYTHON_TOOLCHAIN)" ]
319*61c4878aSAndroid Build Coastguard Worker    }
320*61c4878aSAndroid Build Coastguard Worker  }
321*61c4878aSAndroid Build Coastguard Worker
322*61c4878aSAndroid Build Coastguard Worker  _package_metadata_targets = []
323*61c4878aSAndroid Build Coastguard Worker  foreach(pkg, invoker.packages) {
324*61c4878aSAndroid Build Coastguard Worker    _package_metadata_targets +=
325*61c4878aSAndroid Build Coastguard Worker        [ get_label_info(pkg, "label_no_toolchain") +
326*61c4878aSAndroid Build Coastguard Worker          "._package_metadata($pw_build_PYTHON_TOOLCHAIN)" ]
327*61c4878aSAndroid Build Coastguard Worker  }
328*61c4878aSAndroid Build Coastguard Worker
329*61c4878aSAndroid Build Coastguard Worker  # Build a list of relative paths containing all the python
330*61c4878aSAndroid Build Coastguard Worker  # package_metadata.json files we depend on.
331*61c4878aSAndroid Build Coastguard Worker  generated_file("${target_name}.${_metadata_path_list_suffix}") {
332*61c4878aSAndroid Build Coastguard Worker    data_keys = [ "pw_python_package_metadata_json" ]
333*61c4878aSAndroid Build Coastguard Worker    rebase = root_build_dir
334*61c4878aSAndroid Build Coastguard Worker    deps = _package_metadata_targets
335*61c4878aSAndroid Build Coastguard Worker    outputs = [ _metadata_json_file_list ]
336*61c4878aSAndroid Build Coastguard Worker  }
337*61c4878aSAndroid Build Coastguard Worker
338*61c4878aSAndroid Build Coastguard Worker  # Run the python action on the metadata_path_list.txt file
339*61c4878aSAndroid Build Coastguard Worker  pw_python_action(target_name) {
340*61c4878aSAndroid Build Coastguard Worker    # Save the Python package metadata so this can be installed using
341*61c4878aSAndroid Build Coastguard Worker    # pw_internal_pip_install.
342*61c4878aSAndroid Build Coastguard Worker    metadata = {
343*61c4878aSAndroid Build Coastguard Worker      pw_python_package_metadata_json = [ _package_metadata_json_file ]
344*61c4878aSAndroid Build Coastguard Worker    }
345*61c4878aSAndroid Build Coastguard Worker
346*61c4878aSAndroid Build Coastguard Worker    deps = invoker.packages +
347*61c4878aSAndroid Build Coastguard Worker           [ ":${invoker.target_name}.${_metadata_path_list_suffix}" ]
348*61c4878aSAndroid Build Coastguard Worker
349*61c4878aSAndroid Build Coastguard Worker    script = "$dir_pw_build/py/pw_build/create_python_tree.py"
350*61c4878aSAndroid Build Coastguard Worker    inputs = _inputs + _extra_file_inputs
351*61c4878aSAndroid Build Coastguard Worker    public_deps = _public_deps
352*61c4878aSAndroid Build Coastguard Worker    _pw_internal_run_in_venv = false
353*61c4878aSAndroid Build Coastguard Worker
354*61c4878aSAndroid Build Coastguard Worker    args = [
355*61c4878aSAndroid Build Coastguard Worker      "--repo-root",
356*61c4878aSAndroid Build Coastguard Worker      rebase_path("//", root_build_dir),
357*61c4878aSAndroid Build Coastguard Worker      "--tree-destination-dir",
358*61c4878aSAndroid Build Coastguard Worker      rebase_path(_output_dir, root_build_dir),
359*61c4878aSAndroid Build Coastguard Worker      "--input-list-files",
360*61c4878aSAndroid Build Coastguard Worker      rebase_path(_metadata_json_file_list, root_build_dir),
361*61c4878aSAndroid Build Coastguard Worker    ]
362*61c4878aSAndroid Build Coastguard Worker
363*61c4878aSAndroid Build Coastguard Worker    # Add required setup.cfg args if we are generating a merged config.
364*61c4878aSAndroid Build Coastguard Worker    if (defined(generate_setup_cfg)) {
365*61c4878aSAndroid Build Coastguard Worker      if (defined(generate_setup_cfg.common_config_file)) {
366*61c4878aSAndroid Build Coastguard Worker        args += [
367*61c4878aSAndroid Build Coastguard Worker          "--setupcfg-common-file",
368*61c4878aSAndroid Build Coastguard Worker          rebase_path(generate_setup_cfg.common_config_file, root_build_dir),
369*61c4878aSAndroid Build Coastguard Worker        ]
370*61c4878aSAndroid Build Coastguard Worker      }
371*61c4878aSAndroid Build Coastguard Worker      if (defined(generate_setup_cfg.append_git_sha_to_version)) {
372*61c4878aSAndroid Build Coastguard Worker        args += [ "--setupcfg-version-append-git-sha" ]
373*61c4878aSAndroid Build Coastguard Worker      }
374*61c4878aSAndroid Build Coastguard Worker      if (defined(generate_setup_cfg.append_date_to_version)) {
375*61c4878aSAndroid Build Coastguard Worker        args += [ "--setupcfg-version-append-date" ]
376*61c4878aSAndroid Build Coastguard Worker      }
377*61c4878aSAndroid Build Coastguard Worker      if (defined(generate_setup_cfg.name)) {
378*61c4878aSAndroid Build Coastguard Worker        args += [
379*61c4878aSAndroid Build Coastguard Worker          "--setupcfg-override-name",
380*61c4878aSAndroid Build Coastguard Worker          generate_setup_cfg.name,
381*61c4878aSAndroid Build Coastguard Worker        ]
382*61c4878aSAndroid Build Coastguard Worker      }
383*61c4878aSAndroid Build Coastguard Worker      if (defined(generate_setup_cfg.version)) {
384*61c4878aSAndroid Build Coastguard Worker        args += [
385*61c4878aSAndroid Build Coastguard Worker          "--setupcfg-override-version",
386*61c4878aSAndroid Build Coastguard Worker          generate_setup_cfg.version,
387*61c4878aSAndroid Build Coastguard Worker        ]
388*61c4878aSAndroid Build Coastguard Worker      }
389*61c4878aSAndroid Build Coastguard Worker      if (defined(generate_setup_cfg.include_default_pyproject_file) &&
390*61c4878aSAndroid Build Coastguard Worker          generate_setup_cfg.include_default_pyproject_file == true) {
391*61c4878aSAndroid Build Coastguard Worker        args += [ "--create-default-pyproject-toml" ]
392*61c4878aSAndroid Build Coastguard Worker      }
393*61c4878aSAndroid Build Coastguard Worker      if (defined(generate_setup_cfg.include_extra_files_in_package_data)) {
394*61c4878aSAndroid Build Coastguard Worker        args += [ "--setupcfg-extra-files-in-package-data" ]
395*61c4878aSAndroid Build Coastguard Worker      }
396*61c4878aSAndroid Build Coastguard Worker      _auto_create_package_data_init_py_files = true
397*61c4878aSAndroid Build Coastguard Worker      if (defined(generate_setup_cfg.auto_create_package_data_init_py_files)) {
398*61c4878aSAndroid Build Coastguard Worker        _auto_create_package_data_init_py_files =
399*61c4878aSAndroid Build Coastguard Worker            generate_setup_cfg.auto_create_package_data_init_py_files
400*61c4878aSAndroid Build Coastguard Worker      }
401*61c4878aSAndroid Build Coastguard Worker      if (_auto_create_package_data_init_py_files) {
402*61c4878aSAndroid Build Coastguard Worker        args += [ "--auto-create-package-data-init-py-files" ]
403*61c4878aSAndroid Build Coastguard Worker      }
404*61c4878aSAndroid Build Coastguard Worker    }
405*61c4878aSAndroid Build Coastguard Worker
406*61c4878aSAndroid Build Coastguard Worker    if (_extra_file_args == []) {
407*61c4878aSAndroid Build Coastguard Worker      # No known output files - stamp instead.
408*61c4878aSAndroid Build Coastguard Worker      stamp = true
409*61c4878aSAndroid Build Coastguard Worker    } else {
410*61c4878aSAndroid Build Coastguard Worker      args += [ "--extra-files" ]
411*61c4878aSAndroid Build Coastguard Worker      args += _extra_file_args
412*61c4878aSAndroid Build Coastguard Worker
413*61c4878aSAndroid Build Coastguard Worker      # Include extra_files as outputs
414*61c4878aSAndroid Build Coastguard Worker      outputs = _extra_file_outputs
415*61c4878aSAndroid Build Coastguard Worker    }
416*61c4878aSAndroid Build Coastguard Worker
417*61c4878aSAndroid Build Coastguard Worker    if (_include_tests) {
418*61c4878aSAndroid Build Coastguard Worker      args += [ "--include-tests" ]
419*61c4878aSAndroid Build Coastguard Worker    }
420*61c4878aSAndroid Build Coastguard Worker  }
421*61c4878aSAndroid Build Coastguard Worker
422*61c4878aSAndroid Build Coastguard Worker  # Template to build a bundled Python package wheel.
423*61c4878aSAndroid Build Coastguard Worker  pw_python_action("$target_name._build_wheel") {
424*61c4878aSAndroid Build Coastguard Worker    _wheel_out_dir = "$target_out_dir/$target_name"
425*61c4878aSAndroid Build Coastguard Worker    _wheel_requirement = "$_wheel_out_dir/requirements.txt"
426*61c4878aSAndroid Build Coastguard Worker    metadata = {
427*61c4878aSAndroid Build Coastguard Worker      pw_python_package_wheels = [ _wheel_out_dir ]
428*61c4878aSAndroid Build Coastguard Worker    }
429*61c4878aSAndroid Build Coastguard Worker
430*61c4878aSAndroid Build Coastguard Worker    script = "$dir_pw_build/py/pw_build/generate_python_wheel.py"
431*61c4878aSAndroid Build Coastguard Worker
432*61c4878aSAndroid Build Coastguard Worker    args = [
433*61c4878aSAndroid Build Coastguard Worker      "--package-dir",
434*61c4878aSAndroid Build Coastguard Worker      rebase_path(_output_dir, root_build_dir),
435*61c4878aSAndroid Build Coastguard Worker      "--out-dir",
436*61c4878aSAndroid Build Coastguard Worker      rebase_path(_wheel_out_dir, root_build_dir),
437*61c4878aSAndroid Build Coastguard Worker    ]
438*61c4878aSAndroid Build Coastguard Worker
439*61c4878aSAndroid Build Coastguard Worker    # Add hashes to the _wheel_requirement output.
440*61c4878aSAndroid Build Coastguard Worker    if (pw_build_PYTHON_PIP_INSTALL_REQUIRE_HASHES) {
441*61c4878aSAndroid Build Coastguard Worker      args += [ "--generate-hashes" ]
442*61c4878aSAndroid Build Coastguard Worker    }
443*61c4878aSAndroid Build Coastguard Worker
444*61c4878aSAndroid Build Coastguard Worker    public_deps = []
445*61c4878aSAndroid Build Coastguard Worker    if (defined(invoker.public_deps)) {
446*61c4878aSAndroid Build Coastguard Worker      public_deps += invoker.public_deps
447*61c4878aSAndroid Build Coastguard Worker    }
448*61c4878aSAndroid Build Coastguard Worker    public_deps += [ ":${invoker.target_name}" ]
449*61c4878aSAndroid Build Coastguard Worker
450*61c4878aSAndroid Build Coastguard Worker    outputs = [ _wheel_requirement ]
451*61c4878aSAndroid Build Coastguard Worker  }
452*61c4878aSAndroid Build Coastguard Worker  group("$target_name.wheel") {
453*61c4878aSAndroid Build Coastguard Worker    public_deps = [ ":${invoker.target_name}._build_wheel" ]
454*61c4878aSAndroid Build Coastguard Worker  }
455*61c4878aSAndroid Build Coastguard Worker
456*61c4878aSAndroid Build Coastguard Worker  # Allow using pw_python_distribution targets as a python_dep in
457*61c4878aSAndroid Build Coastguard Worker  # pw_python_group. To do this, create a pw_python_group with the relevant
458*61c4878aSAndroid Build Coastguard Worker  # packages and create wrappers for each subtarget, except those that are
459*61c4878aSAndroid Build Coastguard Worker  # actually implemented by this template.
460*61c4878aSAndroid Build Coastguard Worker  #
461*61c4878aSAndroid Build Coastguard Worker  # This is an ugly workaround that will be removed when the Python build is
462*61c4878aSAndroid Build Coastguard Worker  # refactored (b/235278298).
463*61c4878aSAndroid Build Coastguard Worker  pw_python_group("$target_name._pw_python_group") {
464*61c4878aSAndroid Build Coastguard Worker    python_deps = invoker.packages
465*61c4878aSAndroid Build Coastguard Worker  }
466*61c4878aSAndroid Build Coastguard Worker
467*61c4878aSAndroid Build Coastguard Worker  wrapped_subtargets = pw_python_package_subtargets - [
468*61c4878aSAndroid Build Coastguard Worker                         "wheel",
469*61c4878aSAndroid Build Coastguard Worker                         "_build_wheel",
470*61c4878aSAndroid Build Coastguard Worker                       ]
471*61c4878aSAndroid Build Coastguard Worker
472*61c4878aSAndroid Build Coastguard Worker  foreach(subtarget, wrapped_subtargets) {
473*61c4878aSAndroid Build Coastguard Worker    group("$target_name.$subtarget") {
474*61c4878aSAndroid Build Coastguard Worker      public_deps = [ ":${invoker.target_name}._pw_python_group.$subtarget" ]
475*61c4878aSAndroid Build Coastguard Worker    }
476*61c4878aSAndroid Build Coastguard Worker  }
477*61c4878aSAndroid Build Coastguard Worker}
478*61c4878aSAndroid Build Coastguard Worker
479*61c4878aSAndroid Build Coastguard Worker# TODO: b/232800695 - Remove this template when all projects no longer use it.
480*61c4878aSAndroid Build Coastguard Workertemplate("pw_create_python_source_tree") {
481*61c4878aSAndroid Build Coastguard Worker  pw_python_distribution("$target_name") {
482*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*")
483*61c4878aSAndroid Build Coastguard Worker  }
484*61c4878aSAndroid Build Coastguard Worker}
485*61c4878aSAndroid Build Coastguard Worker
486*61c4878aSAndroid Build Coastguard Worker# Runs pip install on a set of pw_python_packages. This will install
487*61c4878aSAndroid Build Coastguard Worker# pw_python_packages into the user's developer environment.
488*61c4878aSAndroid Build Coastguard Worker#
489*61c4878aSAndroid Build Coastguard Worker# Args:
490*61c4878aSAndroid Build Coastguard Worker#   packages: A list of pw_python_package targets to be pip installed.
491*61c4878aSAndroid Build Coastguard Worker#     These will be installed one at a time.
492*61c4878aSAndroid Build Coastguard Worker#
493*61c4878aSAndroid Build Coastguard Worker#   editable: If true, --editable is passed to the pip install command.
494*61c4878aSAndroid Build Coastguard Worker#
495*61c4878aSAndroid Build Coastguard Worker#   force_reinstall: If true, --force-reinstall is passed to the pip install
496*61c4878aSAndroid Build Coastguard Worker#     command.
497*61c4878aSAndroid Build Coastguard Workertemplate("pw_python_pip_install") {
498*61c4878aSAndroid Build Coastguard Worker  if (current_toolchain == pw_build_PYTHON_TOOLCHAIN) {
499*61c4878aSAndroid Build Coastguard Worker    # Create a target group for the Python package metadata only.
500*61c4878aSAndroid Build Coastguard Worker    group("$target_name._package_metadata") {
501*61c4878aSAndroid Build Coastguard Worker      # Forward the package_metadata subtarget for all python_deps.
502*61c4878aSAndroid Build Coastguard Worker      public_deps = []
503*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.packages)) {
504*61c4878aSAndroid Build Coastguard Worker        foreach(dep, invoker.packages) {
505*61c4878aSAndroid Build Coastguard Worker          public_deps += [ get_label_info(dep, "label_no_toolchain") +
506*61c4878aSAndroid Build Coastguard Worker                           "._package_metadata($pw_build_PYTHON_TOOLCHAIN)" ]
507*61c4878aSAndroid Build Coastguard Worker        }
508*61c4878aSAndroid Build Coastguard Worker      }
509*61c4878aSAndroid Build Coastguard Worker    }
510*61c4878aSAndroid Build Coastguard Worker
511*61c4878aSAndroid Build Coastguard Worker    pw_python_action("$target_name") {
512*61c4878aSAndroid Build Coastguard Worker      script = "$dir_pw_build/py/pw_build/pip_install_python_deps.py"
513*61c4878aSAndroid Build Coastguard Worker
514*61c4878aSAndroid Build Coastguard Worker      assert(
515*61c4878aSAndroid Build Coastguard Worker          defined(invoker.packages),
516*61c4878aSAndroid Build Coastguard Worker          "packages = [ 'python_package' ] is required by pw_internal_pip_install")
517*61c4878aSAndroid Build Coastguard Worker
518*61c4878aSAndroid Build Coastguard Worker      public_deps = []
519*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.public_deps)) {
520*61c4878aSAndroid Build Coastguard Worker        public_deps += invoker.public_deps
521*61c4878aSAndroid Build Coastguard Worker      }
522*61c4878aSAndroid Build Coastguard Worker
523*61c4878aSAndroid Build Coastguard Worker      python_deps = []
524*61c4878aSAndroid Build Coastguard Worker      python_metadata_deps = []
525*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.packages)) {
526*61c4878aSAndroid Build Coastguard Worker        public_deps += invoker.packages
527*61c4878aSAndroid Build Coastguard Worker        python_deps += invoker.packages
528*61c4878aSAndroid Build Coastguard Worker        python_metadata_deps += invoker.packages
529*61c4878aSAndroid Build Coastguard Worker      }
530*61c4878aSAndroid Build Coastguard Worker
531*61c4878aSAndroid Build Coastguard Worker      python_deps = []
532*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.python_deps)) {
533*61c4878aSAndroid Build Coastguard Worker        python_deps += invoker.python_deps
534*61c4878aSAndroid Build Coastguard Worker      }
535*61c4878aSAndroid Build Coastguard Worker
536*61c4878aSAndroid Build Coastguard Worker      _pw_internal_run_in_venv = false
537*61c4878aSAndroid Build Coastguard Worker      _forward_python_metadata_deps = true
538*61c4878aSAndroid Build Coastguard Worker
539*61c4878aSAndroid Build Coastguard Worker      _editable_install = false
540*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.editable)) {
541*61c4878aSAndroid Build Coastguard Worker        _editable_install = invoker.editable
542*61c4878aSAndroid Build Coastguard Worker      }
543*61c4878aSAndroid Build Coastguard Worker
544*61c4878aSAndroid Build Coastguard Worker      _pkg_gn_labels = []
545*61c4878aSAndroid Build Coastguard Worker      foreach(pkg, invoker.packages) {
546*61c4878aSAndroid Build Coastguard Worker        _pkg_gn_labels += [ get_label_info(pkg, "label_no_toolchain") ]
547*61c4878aSAndroid Build Coastguard Worker      }
548*61c4878aSAndroid Build Coastguard Worker
549*61c4878aSAndroid Build Coastguard Worker      _pip_install_log_file = "$target_gen_dir/$target_name/pip_install_log.txt"
550*61c4878aSAndroid Build Coastguard Worker
551*61c4878aSAndroid Build Coastguard Worker      args = [
552*61c4878aSAndroid Build Coastguard Worker        "--gn-packages",
553*61c4878aSAndroid Build Coastguard Worker        string_join(",", _pkg_gn_labels),
554*61c4878aSAndroid Build Coastguard Worker      ]
555*61c4878aSAndroid Build Coastguard Worker
556*61c4878aSAndroid Build Coastguard Worker      if (_editable_install) {
557*61c4878aSAndroid Build Coastguard Worker        args += [ "--editable-pip-install" ]
558*61c4878aSAndroid Build Coastguard Worker      }
559*61c4878aSAndroid Build Coastguard Worker
560*61c4878aSAndroid Build Coastguard Worker      args += [
561*61c4878aSAndroid Build Coastguard Worker        "--log",
562*61c4878aSAndroid Build Coastguard Worker        rebase_path(_pip_install_log_file, root_build_dir),
563*61c4878aSAndroid Build Coastguard Worker      ]
564*61c4878aSAndroid Build Coastguard Worker      args += pw_build_PYTHON_PIP_DEFAULT_OPTIONS
565*61c4878aSAndroid Build Coastguard Worker      args += [
566*61c4878aSAndroid Build Coastguard Worker        "install",
567*61c4878aSAndroid Build Coastguard Worker        "--no-build-isolation",
568*61c4878aSAndroid Build Coastguard Worker      ]
569*61c4878aSAndroid Build Coastguard Worker
570*61c4878aSAndroid Build Coastguard Worker      if (!_editable_install) {
571*61c4878aSAndroid Build Coastguard Worker        if (pw_build_PYTHON_PIP_INSTALL_REQUIRE_HASHES) {
572*61c4878aSAndroid Build Coastguard Worker          args += [ "--require-hashes" ]
573*61c4878aSAndroid Build Coastguard Worker
574*61c4878aSAndroid Build Coastguard Worker          # The --require-hashes option can only install wheels via
575*61c4878aSAndroid Build Coastguard Worker          # requirement.txt files that contain hashes. Depend on this package's
576*61c4878aSAndroid Build Coastguard Worker          # _build_wheel target.
577*61c4878aSAndroid Build Coastguard Worker          foreach(pkg, _pkg_gn_labels) {
578*61c4878aSAndroid Build Coastguard Worker            public_deps += [ "${pkg}._build_wheel" ]
579*61c4878aSAndroid Build Coastguard Worker          }
580*61c4878aSAndroid Build Coastguard Worker        }
581*61c4878aSAndroid Build Coastguard Worker        if (pw_build_PYTHON_PIP_INSTALL_OFFLINE) {
582*61c4878aSAndroid Build Coastguard Worker          args += [ "--no-index" ]
583*61c4878aSAndroid Build Coastguard Worker        }
584*61c4878aSAndroid Build Coastguard Worker        if (pw_build_PYTHON_PIP_INSTALL_DISABLE_CACHE) {
585*61c4878aSAndroid Build Coastguard Worker          args += [ "--no-cache-dir" ]
586*61c4878aSAndroid Build Coastguard Worker        }
587*61c4878aSAndroid Build Coastguard Worker        if (pw_build_PYTHON_PIP_INSTALL_FIND_LINKS != []) {
588*61c4878aSAndroid Build Coastguard Worker          foreach(link_dir, pw_build_PYTHON_PIP_INSTALL_FIND_LINKS) {
589*61c4878aSAndroid Build Coastguard Worker            args += [
590*61c4878aSAndroid Build Coastguard Worker              "--find-links",
591*61c4878aSAndroid Build Coastguard Worker              rebase_path(link_dir, root_build_dir),
592*61c4878aSAndroid Build Coastguard Worker            ]
593*61c4878aSAndroid Build Coastguard Worker          }
594*61c4878aSAndroid Build Coastguard Worker        }
595*61c4878aSAndroid Build Coastguard Worker      }
596*61c4878aSAndroid Build Coastguard Worker
597*61c4878aSAndroid Build Coastguard Worker      _force_reinstall = false
598*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.force_reinstall)) {
599*61c4878aSAndroid Build Coastguard Worker        _force_reinstall = true
600*61c4878aSAndroid Build Coastguard Worker      }
601*61c4878aSAndroid Build Coastguard Worker      if (_force_reinstall) {
602*61c4878aSAndroid Build Coastguard Worker        args += [ "--force-reinstall" ]
603*61c4878aSAndroid Build Coastguard Worker      }
604*61c4878aSAndroid Build Coastguard Worker
605*61c4878aSAndroid Build Coastguard Worker      inputs = pw_build_PIP_CONSTRAINTS
606*61c4878aSAndroid Build Coastguard Worker
607*61c4878aSAndroid Build Coastguard Worker      foreach(_constraints_file, pw_build_PIP_CONSTRAINTS) {
608*61c4878aSAndroid Build Coastguard Worker        args += [
609*61c4878aSAndroid Build Coastguard Worker          "--constraint",
610*61c4878aSAndroid Build Coastguard Worker          rebase_path(_constraints_file, root_build_dir),
611*61c4878aSAndroid Build Coastguard Worker        ]
612*61c4878aSAndroid Build Coastguard Worker      }
613*61c4878aSAndroid Build Coastguard Worker
614*61c4878aSAndroid Build Coastguard Worker      stamp = true
615*61c4878aSAndroid Build Coastguard Worker
616*61c4878aSAndroid Build Coastguard Worker      # Parallel pip installations don't work, so serialize pip invocations.
617*61c4878aSAndroid Build Coastguard Worker      pool = "$dir_pw_build/pool:pip($default_toolchain)"
618*61c4878aSAndroid Build Coastguard Worker    }
619*61c4878aSAndroid Build Coastguard Worker  } else {
620*61c4878aSAndroid Build Coastguard Worker    group("$target_name") {
621*61c4878aSAndroid Build Coastguard Worker      deps = [ ":$target_name($pw_build_PYTHON_TOOLCHAIN)" ]
622*61c4878aSAndroid Build Coastguard Worker    }
623*61c4878aSAndroid Build Coastguard Worker    not_needed("*")
624*61c4878aSAndroid Build Coastguard Worker    not_needed(invoker, "*")
625*61c4878aSAndroid Build Coastguard Worker  }
626*61c4878aSAndroid Build Coastguard Worker
627*61c4878aSAndroid Build Coastguard Worker  group("$target_name.install") {
628*61c4878aSAndroid Build Coastguard Worker    public_deps = [ ":${invoker.target_name}" ]
629*61c4878aSAndroid Build Coastguard Worker  }
630*61c4878aSAndroid Build Coastguard Worker
631*61c4878aSAndroid Build Coastguard Worker  # Allow using pw_internal_pip_install targets as a python_dep in
632*61c4878aSAndroid Build Coastguard Worker  # pw_python_group. To do this, create a pw_python_group with the relevant
633*61c4878aSAndroid Build Coastguard Worker  # packages and create wrappers for each subtarget, except those that are
634*61c4878aSAndroid Build Coastguard Worker  # actually implemented by this template.
635*61c4878aSAndroid Build Coastguard Worker  #
636*61c4878aSAndroid Build Coastguard Worker  # This is an ugly workaround that will be removed when the Python build is
637*61c4878aSAndroid Build Coastguard Worker  # refactored (b/235278298).
638*61c4878aSAndroid Build Coastguard Worker  pw_python_group("$target_name._pw_python_group") {
639*61c4878aSAndroid Build Coastguard Worker    python_deps = invoker.packages
640*61c4878aSAndroid Build Coastguard Worker  }
641*61c4878aSAndroid Build Coastguard Worker
642*61c4878aSAndroid Build Coastguard Worker  foreach(subtarget, pw_python_package_subtargets - [ "install" ]) {
643*61c4878aSAndroid Build Coastguard Worker    group("$target_name.$subtarget") {
644*61c4878aSAndroid Build Coastguard Worker      _test_and_lint_subtargets = [
645*61c4878aSAndroid Build Coastguard Worker        "tests",
646*61c4878aSAndroid Build Coastguard Worker        "lint",
647*61c4878aSAndroid Build Coastguard Worker        "lint.mypy",
648*61c4878aSAndroid Build Coastguard Worker        "lint.pylint",
649*61c4878aSAndroid Build Coastguard Worker        "lint.ruff",
650*61c4878aSAndroid Build Coastguard Worker      ]
651*61c4878aSAndroid Build Coastguard Worker      if (pw_build_TEST_TRANSITIVE_PYTHON_DEPS ||
652*61c4878aSAndroid Build Coastguard Worker          filter_exclude([ subtarget ], _test_and_lint_subtargets) != []) {
653*61c4878aSAndroid Build Coastguard Worker        public_deps = [ ":${invoker.target_name}._pw_python_group.$subtarget" ]
654*61c4878aSAndroid Build Coastguard Worker      }
655*61c4878aSAndroid Build Coastguard Worker      not_needed([ "_test_and_lint_subtargets" ])
656*61c4878aSAndroid Build Coastguard Worker    }
657*61c4878aSAndroid Build Coastguard Worker  }
658*61c4878aSAndroid Build Coastguard Worker}
659*61c4878aSAndroid Build Coastguard Worker
660*61c4878aSAndroid Build Coastguard Worker# TODO: b/232800695 - Remove this template when all projects no longer use it.
661*61c4878aSAndroid Build Coastguard Workertemplate("pw_internal_pip_install") {
662*61c4878aSAndroid Build Coastguard Worker  pw_python_pip_install("$target_name") {
663*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*")
664*61c4878aSAndroid Build Coastguard Worker  }
665*61c4878aSAndroid Build Coastguard Worker}
666