blob: 590488569822b324fda4bcda3b0589528bd6dbf6 [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") {
Anthony DiGirolamo7f8941f2021-08-24 10:02:04 -070093 setup = [
94 "pyproject.toml",
95 "setup.cfg",
96 "setup.py",
97 ]
Wyatt Heplerb3ea9802021-02-23 09:46:09 -080098 sources = [
99 "pw_my_module/__init__.py",
100 "pw_my_module/alfa.py",
101 "pw_my_module/bravo.py",
102 "pw_my_module/charlie.py",
103 ]
104 tests = [
105 "alfa_test.py",
106 "charlie_test.py",
107 ]
108 python_deps = [
109 "$dir_pw_status/py",
110 ":some_protos.python",
111 ]
112 python_test_deps = [ "$dir_pw_build/py" ]
113 pylintrc = "$dir_pigweed/.pylintrc"
114 }
115
116pw_python_script
117================
118A ``pw_python_script`` represents a set of standalone Python scripts and/or
119tests. These files support all of the arguments of ``pw_python_package`` except
120those ``setup``. These targets can be installed, but this only installs their
121dependencies.
122
Wyatt Hepler473efe02021-05-04 14:15:16 -0700123``pw_python_script`` allows creating a
124:ref:`pw_python_action <module-pw_build-python-action>` associated with the
125script. To create an action, pass an ``action`` scope to ``pw_python_script``.
126If there is only a single source file, it serves as the action's ``script`` by
127default.
128
129An action in ``pw_python_script`` can always be replaced with a standalone
130``pw_python_action``, but using the embedded action has some advantages:
131
132- The embedded action target bridges the gap between actions and Python targets.
133 A Python script can be expressed in a single, concise GN target, rather than
134 in two overlapping, dependent targets.
135- The action automatically depends on the ``pw_python_script``. This ensures
136 that the script's dependencies are installed and the action automatically
137 reruns when the script's sources change, without needing to specify a
138 dependency, a step which is easy to forget.
139- Using a ``pw_python_script`` with an embedded action is a simple way to check
140 an existing action's script with Pylint or Mypy or to add tests.
141
Wyatt Heplerb3ea9802021-02-23 09:46:09 -0800142pw_python_group
143===============
144Represents a group of ``pw_python_package`` and ``pw_python_script`` targets.
145These targets do not add any files. Their subtargets simply forward to those of
146their dependencies.
147
Wyatt Heplerb3ea9802021-02-23 09:46:09 -0800148pw_python_requirements
149======================
150Represents a set of local and PyPI requirements, with no associated source
151files. These targets serve the role of a ``requirements.txt`` file.
Joe Ethierfbe66152021-03-31 16:02:36 -0700152
Michael Spang01faaf72021-06-09 22:38:40 -0400153When packages are installed by Pigweed, additional version constraints can be
154provided using the ``pw_build_PIP_CONSTRAINTS`` GN arg. This option should
155contain a list of paths to pass to the ``--constraint`` option of ``pip
156install``. This can be used to synchronize dependency upgrades across a project
157which facilitates reproducibility of builds.
158
159Note using multiple ``pw_python_requirements`` that install different versions
160of the same package will currently cause unpredictable results, while using
161constraints should have correct results (which may be an error indicating a
162conflict).
163
Joe Ethierfbe66152021-03-31 16:02:36 -0700164.. _module-pw_build-python-dist:
165
166---------------------
167Python distributables
168---------------------
169Pigweed also provides some templates to make it easier to bundle Python packages
170for deployment. These templates are found in ``pw_build/python_dist.gni``. See
171the .gni file for complete usage doclumentation.
172
173pw_python_wheels
174================
175Collects Python wheels for one or more ``pw_python_package`` targets, plus any
176additional ``pw_python_package`` targets they depend on, directly or indirectly.
177Note that this does not include Python dependencies that come from outside the
178GN build, like packages from PyPI, for example. Those should still be declared
179in the package's ``setup.py`` file as usual.
180
181Arguments
182---------
183- ``packages`` - List of ``pw_python_package`` targets whose wheels should be
184 included; their dependencies will be pulled in as wheels also.
185
186Wheel collection under the hood
187-------------------------------
188The ``.wheel`` subtarget of every ``pw_python_package`` generates a wheel
189(``.whl``) for the Python package. The ``pw_python_wheels`` template figures
190out which wheels to collect by traversing the ``pw_python_package_wheels``
191`GN metadata
Rob Mohr463700d2021-05-22 10:31:03 -0700192<https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#var_metadata>`_ key,
Joe Ethierfbe66152021-03-31 16:02:36 -0700193which lists the output directory for each wheel.
194
195The ``pw_mirror_tree`` template is then used to collect wheels in an output
196directory:
197
198.. code-block::
199
200 import("$dir_pw_build/mirror_tree.gni")
201
202 pw_mirror_tree("my_wheels") {
203 path_data_keys = [ "pw_python_package_wheels" ]
204 deps = [ ":python_packages.wheel" ]
205 directory = "$root_out_dir/the_wheels"
206 }
207
208pw_python_zip_with_setup
209========================
210Generates a ``.zip`` archive suitable for deployment outside of the project's
211developer environment. The generated ``.zip`` contains Python wheels
212(``.whl`` files) for one or more ``pw_python_package`` targets, plus wheels for
213any additional ``pw_python_package`` targets in the GN build they depend on,
214directly or indirectly. Dependencies from outside the GN build, such as packages
215from PyPI, must be listed in packages' ``setup.py`` files as usual.
216
217The ``.zip`` also includes simple setup scripts for Linux,
218MacOS, and Windows. The setup scripts automatically create a Python virtual
219environment and install the whole collection of wheels into it using ``pip``.
220
221Optionally, additional files and directories can be included in the archive.
222
223Arguments
224---------
225- ``packages`` - A list of `pw_python_package` targets whose wheels should be
226 included; their dependencies will be pulled in as wheels also.
227- ``inputs`` - An optional list of extra files to include in the generated
228 ``.zip``, formatted the same way as the ``inputs`` argument to ``pw_zip``
229 targets.
230- ``dirs`` - An optional list of directories to include in the generated
231 ``.zip``, formatted the same was as the ``dirs`` argument to ``pw_zip``
232 targets.
233
234Example
235-------
236
237.. code-block::
238
239 import("//build_overrides/pigweed.gni")
240
241 import("$dir_pw_build/python_dist.gni")
242
243 pw_python_zip_with_setup("my_tools") {
244 packages = [ ":some_python_package" ]
245 inputs = [ "$dir_pw_build/python_dist/README.md > /${target_name}/" ]
246 }