A code generator would be a build dependency, since it’s something that runs on the build machine. For example, Cython is a pure-Python build dependency, and Bison is an “external” one.
The other definition later in the PEP is clearer: a host dependency “must be available during the build and is built for the host machine’s OS and architecture. These are usually libraries the project links against.”
This area is obviously confusing a lot of people, so maybe the PEPs could give some more examples. In particular, the Examples section of PEP 804 covers pip (which installs packages) and Grayskull (which converts packages to a different ecosystem). But it doesn’t discuss building packages, which is the third major use case of the PEP, and the one where the host vs. build platform distinction matters most.
Here’s a sketch of how I imagine builds working; feel free to use it in the PEP or point out where I’ve got anything wrong:
When not cross-compiling, the host and build platforms are the same, so the build and host dependencies are handled in the same way. The build frontend (e.g. pypa/build) would use pyproject-external or similar to determine what these dependencies are, and do one of the following:
- Install them locally in the isolated build environment, with a tool like conda.
- Install them with a system package manager like apt.
- Show the user a message explaining how to install them manually.
When cross-compiling. the host and build platforms are different, such as building for Android or Pyodide on Linux, or for iOS on macOS.
- Build dependencies are handled in the same way as the non-cross-compiling case.
- Host dependencies cannot be installed with the system package manager, because they’re not for the build machine’s platform. So they’ll need to be installed with something like conda. Imagine that conda and conda-forge add support for Android, then the build frontend could do something like this:
- Create a conda environment for Android (using
conda create --subdir).
- Use pyproject-external to determine the
conda install commands for the host dependencies.
- Run those commands within the Android environment.
- Arrange for the environment to be used by the build by setting CFLAGS, LDFLAGS, PKG_CONFIG_LIBDIR, etc..
This is effectively what we’re already doing to support Android in cibuildwheel, except the Android environment isn’t created with conda, but by unpacking an Android release from python.org, which only contains Python, OpenSSL and SQLite. We’re still using pypa/build under the hood, but because it doesn’t know about cross-compilation, we’re breaking the build up into smaller steps and using pypa/build’s API to do each of them for the build or host platform as appropriate.
This approach has been good enough to enable several packages to release Android and iOS wheels on PyPI. But I expect that as we get into more complex packages, many of them will need their host dependencies to be pre-built. So this PEP has come at just the right time for those of us who are working on Python cross-compilation, and I’m happy with its overall design.