Merge pull request #1976 from davidhewitt/pyo3-build-config-docs

docs: pyo3 config files
This commit is contained in:
David Hewitt 2021-11-11 08:53:36 +00:00 committed by GitHub
commit 20091826a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 13 deletions

View file

@ -28,8 +28,9 @@ To summarize, there are six main parts to the PyO3 codebase.
- [`src/class`] - [`src/class`]
5. [Procedural macros to simplify usage for users.](#5-procedural-macros-to-simplify-usage-for-users) 5. [Procedural macros to simplify usage for users.](#5-procedural-macros-to-simplify-usage-for-users)
- [`src/derive_utils.rs`], [`pyo3-macros`] and [`pyo3-macros-backend`] - [`src/derive_utils.rs`], [`pyo3-macros`] and [`pyo3-macros-backend`]
6. [`build.rs`](#6-buildrs) 6. [`build.rs` and `pyo3-build-config`](#6-buildrs-and-pyo3-build-config)
- [`build.rs`](https://github.com/PyO3/pyo3/tree/main/build.rs) - [`build.rs`](https://github.com/PyO3/pyo3/tree/main/build.rs)
- [`pyo3-build-config`]
## 1. Low-level bindings of Python/C API ## 1. Low-level bindings of Python/C API
@ -50,7 +51,7 @@ With `Py_LIMITED_API`, we can build a Python-version-agnostic binary called an
`Py_37` means that the API is available from Python >= 3.7. `Py_37` means that the API is available from Python >= 3.7.
There are also `Py_38`, `Py_39`, and so on. There are also `Py_38`, `Py_39`, and so on.
`PyPy` means that the API definition is for PyPy. `PyPy` means that the API definition is for PyPy.
Those flags are set in [`build.rs`](#6-buildrs). Those flags are set in [`build.rs`](#6-buildrs-and-pyo3-build-config).
## 2. Bindings to Python objects ## 2. Bindings to Python objects
@ -166,25 +167,37 @@ some internal tricks for making `#[pyproto]` flexible.
[`src/derive_utils.rs`] contains some utilities used in code generated by these proc-macros, [`src/derive_utils.rs`] contains some utilities used in code generated by these proc-macros,
such as parsing function arguments. such as parsing function arguments.
## 6. `build.rs` ## 6. `build.rs` and `pyo3-build-config`
PyO3's [`build.rs`](https://github.com/PyO3/pyo3/tree/main/build.rs) is relatively long PyO3 supports a wide range of OSes, interpreters and use cases. The correct environment must be
(about 900 lines) to support multiple architectures, interpreters, and usages. detected at build time in order to set up relevant conditional compilation correctly. This logic
Below is a non-exhaustive list of its functionality: is captured in the [`pyo3-build-config`] crate, which is a `build-dependency` of `pyo3` and
`pyo3-macros`, and can also be used by downstream users in the same way.
- Cross-compiling support. In [`pyo3-build-config`]'s `build.rs` the build environment is detected and inlined into the crate
- If `TARGET` architecture and `HOST` architecture differ, we find cross compile information as a "config file". This works in all cases except for cross-compiling, where it is necessary to
from environment variables (`PYO3_CROSS_LIB_DIR` and `PYO3_CROSS_PYTHON_VERSION`) or system files. capture this from the `pyo3` `build.rs` to get some extra environment variables that Cargo doesn't
set for build dependencies.
The `pyo3` `build.rs` also runs some safety checks such as ensuring the Python version detected is
actually supported.
Some of the functionality of `pyo3-build-config`:
- Find the interpreter for build and detect the Python version. - Find the interpreter for build and detect the Python version.
- We have to set some version flags like `Py_37`. - We have to set some version flags like `#[cfg(Py_3_7)]`.
- If the interpreter is PyPy, we set `PyPy`. - If the interpreter is PyPy, we set `#[cfg(PyPy)`.
- If `PYO3_NO_PYTHON` environment variable is set then the interpreter detection is bypassed - If the `PYO3_CONFIG_FILE` environment variable is set then that file's contents will be used
instead of any detected configuration.
- If the `PYO3_NO_PYTHON` environment variable is set then the interpreter detection is bypassed
entirely and only abi3 extensions can be built. entirely and only abi3 extensions can be built.
- Check if we are building a Python extension. - Check if we are building a Python extension.
- If we are building an extension (e.g., Python library installable by `pip`), - If we are building an extension (e.g., Python library installable by `pip`),
we don't link `libpython`. we don't link `libpython`.
Currently we use the `extension-module` feature for this purpose. This may change in the future. Currently we use the `extension-module` feature for this purpose. This may change in the future.
See [#1123](https://github.com/PyO3/pyo3/pull/1123). See [#1123](https://github.com/PyO3/pyo3/pull/1123).
- Cross-compiling configuration
- If `TARGET` architecture and `HOST` architecture differ, we find cross compile information
from environment variables (`PYO3_CROSS_LIB_DIR` and `PYO3_CROSS_PYTHON_VERSION`) or system files.
<!-- External Links --> <!-- External Links -->
@ -194,6 +207,7 @@ Below is a non-exhaustive list of its functionality:
[`pyo3-macros`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros [`pyo3-macros`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros
[`pyo3-macros-backend`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros-backend [`pyo3-macros-backend`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros-backend
[`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config
<!-- Directories --> <!-- Directories -->

View file

@ -18,11 +18,13 @@ PYO3_VERSION_TAG = os.environ.get("PYO3_VERSION_TAG", "main")
if PYO3_VERSION_TAG == "main": if PYO3_VERSION_TAG == "main":
PYO3_DOCS_URL = "https://pyo3.rs/main/doc" PYO3_DOCS_URL = "https://pyo3.rs/main/doc"
PYO3_DOCS_VERSION = "latest"
PYO3_CRATE_VERSION = 'git = "https://github.com/pyo3/pyo3"' PYO3_CRATE_VERSION = 'git = "https://github.com/pyo3/pyo3"'
else: else:
# v0.13.2 -> 0.13.2 # v0.13.2 -> 0.13.2
version = PYO3_VERSION_TAG.lstrip("v") version = PYO3_VERSION_TAG.lstrip("v")
PYO3_DOCS_URL = f"https://docs.rs/pyo3/{version}" PYO3_DOCS_URL = f"https://docs.rs/pyo3/{version}"
PYO3_DOCS_VERSION = version
PYO3_CRATE_VERSION = f'version = "{version}"' PYO3_CRATE_VERSION = f'version = "{version}"'
@ -35,6 +37,7 @@ def replace_section_content(section):
section["Chapter"]["content"] section["Chapter"]["content"]
.replace("{{#PYO3_VERSION_TAG}}", PYO3_VERSION_TAG) .replace("{{#PYO3_VERSION_TAG}}", PYO3_VERSION_TAG)
.replace("{{#PYO3_DOCS_URL}}", PYO3_DOCS_URL) .replace("{{#PYO3_DOCS_URL}}", PYO3_DOCS_URL)
.replace("{{#PYO3_DOCS_VERSION}}", PYO3_DOCS_VERSION)
.replace("{{#PYO3_CRATE_VERSION}}", PYO3_CRATE_VERSION) .replace("{{#PYO3_CRATE_VERSION}}", PYO3_CRATE_VERSION)
) )

View file

@ -44,7 +44,11 @@ Caused by:
build_flags=WITH_THREAD build_flags=WITH_THREAD
``` ```
> Note: if you save the output config to a file, it is possible to manually override the contents and feed it back into PyO3 using the `PYO3_CONFIG_FILE` env var. For now, this is an advanced feature that should not be needed for most users. The format of the config file and its contents are deliberately unstable and undocumented. If you have a production use-case for this config file, please file an issue and help us stabilize it! ### Advanced: config files
If you save the above output config from `PYO3_PRINT_CONFIG` to a file, it is possible to manually override the contents and feed it back into PyO3 using the `PYO3_CONFIG_FILE` env var.
If your build environment is unusual enough that PyO3's regular configuration detection doesn't work, using a config file like this will give you the flexibility to make PyO3 work for you. To see the full set of options supported, see the documentation for the [`InterpreterConfig` struct](https://docs.rs/pyo3-build-config/{{#PYO3_DOCS_VERSION}}/pyo3_build_config/struct.InterpreterConfig.html).
## Building Python extension modules ## Building Python extension modules