blob: f3431fcc0dc5af9eb8447ecef1c930f01193f72b [file] [log] [blame]
Avi Drissman73a09d12022-09-08 20:33:381# Copyright 2018 The Chromium Authors
Andrew Grievea7f1ee902018-05-18 16:17:222# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5# Creates a group() that lists Python sources as |data|.
6# Having such targets serves two purposes:
7# 1) Causes files to be included in runtime_deps, so that they are uploaded to
8# swarming when running tests remotely.
9# 2) Causes "gn analyze" to know about all Python inputs so that tests will be
10# re-run when relevant Python files change.
11#
12# All non-trivial Python scripts should use a "pydeps" file to track their
13# sources. To create a .pydep file for a target in //example:
14#
15# build/print_python_deps.py \
16# --root example \
17# --output example/$target_name.pydeps \
18# path/to/your/script.py
19#
20# Keep the .pydep file up-to-date by adding to //PRESUBMIT.py under one of:
21# _ANDROID_SPECIFIC_PYDEPS_FILES, _GENERIC_PYDEPS_FILES
22#
23# Variables
24# pydeps_file: Path to .pydeps file to read sources from (optional).
25# data: Additional files to include in data. E.g. non-.py files needed by the
26# library, or .py files that are conditionally / lazily imported.
27#
28# Example
29# python_library("my_library_py") {
30# pydeps_file = "my_library.pydeps"
31# data = [ "foo.dat" ]
32# }
33template("python_library") {
34 group(target_name) {
35 forward_variables_from(invoker,
36 [
37 "data_deps",
38 "deps",
39 "testonly",
40 "visibility",
41 ])
42
43 if (defined(invoker.pydeps_file)) {
Andrew Grieve93f64402020-03-13 17:04:2244 # Read and filter out comments.
45 _pydeps_lines = read_file(invoker.pydeps_file, "list lines")
46 _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ])
Andrew Grievea7f1ee902018-05-18 16:17:2247
Tibor Goldschwendt1774a2a62019-04-30 15:36:2848 # Dependencies are listed relative to the pydeps file directory, but data
49 # parameter expects paths that are relative to the current BUILD.gn
50 _script_dir = get_path_info(invoker.pydeps_file, "dir")
Andrew Grieve93f64402020-03-13 17:04:2251 _rebased_pydeps_entries = rebase_path(_pydeps_entries, ".", _script_dir)
Tibor Goldschwendt1774a2a62019-04-30 15:36:2852
Andrew Grievea7f1ee902018-05-18 16:17:2253 # Even though the .pydep file is not used at runtime, it must be added
54 # so that "gn analyze" will mark the target as changed when .py files
55 # are removed but none are added or modified.
Andrew Grieve93f64402020-03-13 17:04:2256 data = _rebased_pydeps_entries + [ invoker.pydeps_file ]
Andrew Grievea7f1ee902018-05-18 16:17:2257 } else {
58 data = []
59 }
60 if (defined(invoker.data)) {
61 data += invoker.data
62 }
63 }
64}
David 'Digit' Turner0006f4732018-08-07 07:12:3665
66# A template used for actions that execute a Python script, which has an
67# associated .pydeps file. In other words:
68#
69# - This is very similar to just an action(), except that |script| must point
70# to a Python script (e.g. "//build/.../foo.py") that has a corresponding
71# .pydeps file in the source tree (e.g. "//build/.../foo.pydeps").
72#
73# - The .pydeps file contains a list of python dependencies (imports really)
74# and is generated _manually_ by using a command like:
75#
76# build/print_python_deps.py --inplace build/android/gyp/foo.py
77#
Andrew Grievea4b37d62019-02-06 15:37:4578# Example
79# action_with_pydeps("create_foo") {
80# script = "myscript.py"
81# args = [...]
82# }
David 'Digit' Turner0006f4732018-08-07 07:12:3683template("action_with_pydeps") {
David 'Digit' Turner0006f4732018-08-07 07:12:3684 action(target_name) {
Dirk Pranke173e0912021-03-12 17:08:2985 # Ensure that testonly and visibility are forwarded
David 'Digit' Turner0006f4732018-08-07 07:12:3686 # explicitly, since this performs recursive scope lookups, which is
87 # required to ensure their definition from scopes above the caller are
88 # properly handled. All other variables are forwarded with "*", which
89 # doesn't perform recursive lookups at all. See https://crbug.com/862232
90 forward_variables_from(invoker,
91 [
92 "testonly",
93 "visibility",
94 ])
95 forward_variables_from(invoker,
96 "*",
97 [
98 "testonly",
99 "visibility",
100 ])
101
Andrew Grieve93f64402020-03-13 17:04:22102 # Read and filter out comments.
103 # Happens every time the template is instantiated, but benchmarking shows no
104 # perceivable impact on overall 'gn gen' speed.
105 _pydeps_file = invoker.script + "deps"
Dirk Prankebfd2cd5632020-08-20 01:10:08106
Mohamed Heikale217fc852020-07-06 19:44:03107 _pydeps_lines =
108 read_file(_pydeps_file, "list lines") # https://crbug.com/1102058
Andrew Grieve93f64402020-03-13 17:04:22109 _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ])
110
David 'Digit' Turner0006f4732018-08-07 07:12:36111 if (!defined(inputs)) {
112 inputs = []
113 }
114
115 # Dependencies are listed relative to the script directory, but inputs
116 # expects paths that are relative to the current BUILD.gn
Andrew Grievea4b37d62019-02-06 15:37:45117 _script_dir = get_path_info(_pydeps_file, "dir")
Andrew Grieve93f64402020-03-13 17:04:22118 inputs += rebase_path(_pydeps_entries, ".", _script_dir)
David 'Digit' Turner0006f4732018-08-07 07:12:36119 }
120}
121
122template("action_foreach_with_pydeps") {
David 'Digit' Turner0006f4732018-08-07 07:12:36123 action_foreach(target_name) {
Dirk Pranke173e0912021-03-12 17:08:29124 # Ensure that testonly and visibility are forwarded
David 'Digit' Turner0006f4732018-08-07 07:12:36125 # explicitly, since this performs recursive scope lookups, which is
126 # required to ensure their definition from scopes above the caller are
127 # properly handled. All other variables are forwarded with "*", which
128 # doesn't perform recursive lookups at all. See https://crbug.com/862232
129 forward_variables_from(invoker,
130 [
131 "testonly",
132 "visibility",
133 ])
134 forward_variables_from(invoker,
135 "*",
136 [
137 "testonly",
138 "visibility",
139 ])
140
Andrew Grieve93f64402020-03-13 17:04:22141 # Read and filter out comments.
142 # Happens every time the template is instantiated, but benchmarking shows no
143 # perceivable impact on overall 'gn gen' speed.
Dirk Prankebfd2cd5632020-08-20 01:10:08144 if (defined(invoker.deps_file)) {
145 _pydeps_file = invoker.deps_file
146 } else {
147 _pydeps_file = invoker.script + "deps"
148 }
Andrew Grieve93f64402020-03-13 17:04:22149 _pydeps_lines = read_file(_pydeps_file, "list lines")
150 _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ])
151
David 'Digit' Turner0006f4732018-08-07 07:12:36152 if (!defined(inputs)) {
153 inputs = []
154 }
155
156 # Dependencies are listed relative to the script directory, but inputs
157 # expects paths that are relative to the current BUILD.gn
158 _script_dir = get_path_info(script, "dir")
Andrew Grieve93f64402020-03-13 17:04:22159 inputs += rebase_path(_pydeps_entries, ".", _script_dir)
David 'Digit' Turner0006f4732018-08-07 07:12:36160 }
161}