blob: c5e1898f88874971f8b270fbbd2290678de166c0 [file] [log] [blame]
Wyatt Heplerb3ea9802021-02-23 09:46:09 -08001.. _module-pw_build-python:
2
3-------------------
4Python GN templates
5-------------------
6The Python build is implemented with GN templates defined in
Joe Ethierfbe66152021-03-31 16:02:36 -07007``pw_build/python.gni``. See the .gni file for complete usage documentation.
Wyatt Heplerb3ea9802021-02-23 09:46:09 -08008
9.. seealso:: :ref:`docs-python-build`
10
11pw_python_package
12=================
13The main Python template is ``pw_python_package``. Each ``pw_python_package``
14target represents a Python package. As described in
15:ref:`module-pw_build-python-target`, each ``pw_python_package`` expands to
16several subtargets. In summary, these are:
17
18- ``<name>`` - Represents the files themselves
19- ``<name>.lint`` - Runs static analysis
20- ``<name>.tests`` - Runs all tests for this package
21- ``<name>.install`` - Installs the package
22- ``<name>.wheel`` - Builds a Python wheel
23
Wyatt Heplerb85cda42021-04-07 13:13:15 -070024GN permits using abbreviated labels when the target name matches the directory
25name (e.g. ``//foo`` for ``//foo:foo``). For consistency with this, Python
26package subtargets are aliased to the directory when the target name is the
27same as the directory. For example, these two labels are equivalent:
28
29.. code-block::
30
31 //path/to/my_python_package:my_python_package.tests
32 //path/to/my_python_package:tests
33
Wyatt Heplerf6f74f42021-04-13 19:26:20 -070034The actions in a ``pw_python_package`` (e.g. installing packages and running
35Pylint) are done within a single GN toolchain to avoid duplication in
36multi-toolchain builds. This toolchain can be set with the
Joe Ethierfbe66152021-03-31 16:02:36 -070037``pw_build_PYTHON_TOOLCHAIN`` GN arg, which defaults to
38``$dir_pw_build/python_toolchain:python``.
Wyatt Heplerf6f74f42021-04-13 19:26:20 -070039
Wyatt Heplerb3ea9802021-02-23 09:46:09 -080040Arguments
41---------
42- ``setup`` - List of setup file paths (setup.py or pyproject.toml & setup.cfg),
43 which must all be in the same directory.
Wyatt Heplerb85cda42021-04-07 13:13:15 -070044- ``generate_setup``: As an alternative to ``setup``, generate setup files with
Anthony DiGirolamoafb861c2021-08-12 16:48:04 -070045 the keywords in this scope. ``name`` is required. This follows the same
46 structure as a ``setup.cfg`` file's `declarative config
47 <https://setuptools.readthedocs.io/en/latest/userguide/declarative_config.html>`_
48 For example:
Wyatt Heplerb85cda42021-04-07 13:13:15 -070049
50 .. code-block::
51
52 generate_setup = {
Anthony DiGirolamoafb861c2021-08-12 16:48:04 -070053 metadata = {
54 name = "a_nifty_package"
55 version = "1.2a"
56 }
57 options = {
58 install_requires = [ "a_pip_package" ]
59 }
Wyatt Heplerb85cda42021-04-07 13:13:15 -070060 }
61
Wyatt Heplerb3ea9802021-02-23 09:46:09 -080062- ``sources`` - Python sources files in the package.
63- ``tests`` - Test files for this Python package.
64- ``python_deps`` - Dependencies on other pw_python_packages in the GN build.
65- ``python_test_deps`` - Test-only pw_python_package dependencies.
66- ``other_deps`` - Dependencies on GN targets that are not pw_python_packages.
67- ``inputs`` - Other files to track, such as package_data.
Wyatt Heplerdcfcecf2021-03-01 08:36:19 -080068- ``proto_library`` - A pw_proto_library target to embed in this Python package.
Wyatt Heplerb85cda42021-04-07 13:13:15 -070069 ``generate_setup`` is required in place of setup if proto_library is used. See
Wyatt Heplerdcfcecf2021-03-01 08:36:19 -080070 :ref:`module-pw_protobuf_compiler-add-to-python-package`.
Wyatt Heplerc2ce5242021-03-17 08:42:14 -070071- ``static_analysis`` List of static analysis tools to run; ``"*"`` (default)
72 runs all tools. The supported tools are ``"mypy"`` and ``"pylint"``.
Wyatt Heplerb3ea9802021-02-23 09:46:09 -080073- ``pylintrc`` - Optional path to a pylintrc configuration file to use. If not
74 provided, Pylint's default rcfile search is used. Pylint is executed
75 from the package's setup directory, so pylintrc files in that directory
76 will take precedence over others.
77- ``mypy_ini`` - Optional path to a mypy configuration file to use. If not
78 provided, mypy's default configuration file search is used. mypy is
79 executed from the package's setup directory, so mypy.ini files in that
80 directory will take precedence over others.
81
82Example
83-------
84This is an example Python package declaration for a ``pw_my_module`` module.
85
86.. code-block::
87
88 import("//build_overrides/pigweed.gni")
89
90 import("$dir_pw_build/python.gni")
91
92 pw_python_package("py") {
93 setup = [ "setup.py" ]
94 sources = [
95 "pw_my_module/__init__.py",
96 "pw_my_module/alfa.py",
97 "pw_my_module/bravo.py",
98 "pw_my_module/charlie.py",
99 ]
100 tests = [
101 "alfa_test.py",
102 "charlie_test.py",
103 ]
104 python_deps = [
105 "$dir_pw_status/py",
106 ":some_protos.python",
107 ]
108 python_test_deps = [ "$dir_pw_build/py" ]
109 pylintrc = "$dir_pigweed/.pylintrc"
110 }
111
112pw_python_script
113================
114A ``pw_python_script`` represents a set of standalone Python scripts and/or
115tests. These files support all of the arguments of ``pw_python_package`` except
116those ``setup``. These targets can be installed, but this only installs their
117dependencies.
118
Wyatt Hepler473efe02021-05-04 14:15:16 -0700119``pw_python_script`` allows creating a
120:ref:`pw_python_action <module-pw_build-python-action>` associated with the
121script. To create an action, pass an ``action`` scope to ``pw_python_script``.
122If there is only a single source file, it serves as the action's ``script`` by
123default.
124
125An action in ``pw_python_script`` can always be replaced with a standalone
126``pw_python_action``, but using the embedded action has some advantages:
127
128- The embedded action target bridges the gap between actions and Python targets.
129 A Python script can be expressed in a single, concise GN target, rather than
130 in two overlapping, dependent targets.
131- The action automatically depends on the ``pw_python_script``. This ensures
132 that the script's dependencies are installed and the action automatically
133 reruns when the script's sources change, without needing to specify a
134 dependency, a step which is easy to forget.
135- Using a ``pw_python_script`` with an embedded action is a simple way to check
136 an existing action's script with Pylint or Mypy or to add tests.
137
Wyatt Heplerb3ea9802021-02-23 09:46:09 -0800138pw_python_group
139===============
140Represents a group of ``pw_python_package`` and ``pw_python_script`` targets.
141These targets do not add any files. Their subtargets simply forward to those of
142their dependencies.
143
Wyatt Heplerb3ea9802021-02-23 09:46:09 -0800144pw_python_requirements
145======================
146Represents a set of local and PyPI requirements, with no associated source
147files. These targets serve the role of a ``requirements.txt`` file.
Joe Ethierfbe66152021-03-31 16:02:36 -0700148
Michael Spang01faaf72021-06-09 22:38:40 -0400149When packages are installed by Pigweed, additional version constraints can be
150provided using the ``pw_build_PIP_CONSTRAINTS`` GN arg. This option should
151contain a list of paths to pass to the ``--constraint`` option of ``pip
152install``. This can be used to synchronize dependency upgrades across a project
153which facilitates reproducibility of builds.
154
155Note using multiple ``pw_python_requirements`` that install different versions
156of the same package will currently cause unpredictable results, while using
157constraints should have correct results (which may be an error indicating a
158conflict).
159
Joe Ethierfbe66152021-03-31 16:02:36 -0700160.. _module-pw_build-python-dist:
161
162---------------------
163Python distributables
164---------------------
165Pigweed also provides some templates to make it easier to bundle Python packages
166for deployment. These templates are found in ``pw_build/python_dist.gni``. See
167the .gni file for complete usage doclumentation.
168
169pw_python_wheels
170================
171Collects Python wheels for one or more ``pw_python_package`` targets, plus any
172additional ``pw_python_package`` targets they depend on, directly or indirectly.
173Note that this does not include Python dependencies that come from outside the
174GN build, like packages from PyPI, for example. Those should still be declared
175in the package's ``setup.py`` file as usual.
176
177Arguments
178---------
179- ``packages`` - List of ``pw_python_package`` targets whose wheels should be
180 included; their dependencies will be pulled in as wheels also.
181
182Wheel collection under the hood
183-------------------------------
184The ``.wheel`` subtarget of every ``pw_python_package`` generates a wheel
185(``.whl``) for the Python package. The ``pw_python_wheels`` template figures
186out which wheels to collect by traversing the ``pw_python_package_wheels``
187`GN metadata
Rob Mohr463700d2021-05-22 10:31:03 -0700188<https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#var_metadata>`_ key,
Joe Ethierfbe66152021-03-31 16:02:36 -0700189which lists the output directory for each wheel.
190
191The ``pw_mirror_tree`` template is then used to collect wheels in an output
192directory:
193
194.. code-block::
195
196 import("$dir_pw_build/mirror_tree.gni")
197
198 pw_mirror_tree("my_wheels") {
199 path_data_keys = [ "pw_python_package_wheels" ]
200 deps = [ ":python_packages.wheel" ]
201 directory = "$root_out_dir/the_wheels"
202 }
203
204pw_python_zip_with_setup
205========================
206Generates a ``.zip`` archive suitable for deployment outside of the project's
207developer environment. The generated ``.zip`` contains Python wheels
208(``.whl`` files) for one or more ``pw_python_package`` targets, plus wheels for
209any additional ``pw_python_package`` targets in the GN build they depend on,
210directly or indirectly. Dependencies from outside the GN build, such as packages
211from PyPI, must be listed in packages' ``setup.py`` files as usual.
212
213The ``.zip`` also includes simple setup scripts for Linux,
214MacOS, and Windows. The setup scripts automatically create a Python virtual
215environment and install the whole collection of wheels into it using ``pip``.
216
217Optionally, additional files and directories can be included in the archive.
218
219Arguments
220---------
221- ``packages`` - A list of `pw_python_package` targets whose wheels should be
222 included; their dependencies will be pulled in as wheels also.
223- ``inputs`` - An optional list of extra files to include in the generated
224 ``.zip``, formatted the same way as the ``inputs`` argument to ``pw_zip``
225 targets.
226- ``dirs`` - An optional list of directories to include in the generated
227 ``.zip``, formatted the same was as the ``dirs`` argument to ``pw_zip``
228 targets.
229
230Example
231-------
232
233.. code-block::
234
235 import("//build_overrides/pigweed.gni")
236
237 import("$dir_pw_build/python_dist.gni")
238
239 pw_python_zip_with_setup("my_tools") {
240 packages = [ ":some_python_package" ]
241 inputs = [ "$dir_pw_build/python_dist/README.md > /${target_name}/" ]
242 }