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