Crate Configuration¶
Cargo Features to Control Building¶
The pyembed
crate has a set of build-mode-*
Cargo feature flags to
control how build artifacts are created and consumed.
The features are described in the following sections.
build-mode-default
¶
This is the default build mode. It is enabled by default.
This build mode uses default Python linking behavior and feature detection
as implemented by the cpython
and python3-sys
crates. It will attempt
to find a python
in PATH
or from the PYTHON_SYS_EXECUTABLE
environment variable and dynamically link against it.
This is the default mode for convenience, as it enables the pyembed
crate
to build in the most environments. However, the built binaries will have a
dependency against a foreign libpython
and likely aren’t suitable for
distribution.
pyembed
has a dependency on Python 3.8+. If an older Python is detected,
it can result in build errors, including unresolved symbol errors.
build-mode-pyoxidizer-exe
¶
A pyoxidizer
executable will be run to generate build artifacts.
The path to this executable can be defined via the PYOXIDIZER_EXE
environment variable. Otherwise PATH
will be used.
At build time, pyoxidizer run-build-script
will be run. A
PyOxidizer
configuration file will be discovered using PyOxidizer’s
heuristics for doing so. OUT_DIR
will be set if running from cargo
,
so a pyoxidizer.bzl
next to the main Rust project being built should
be found and used.
pyoxidizer run-build-script
will resolve the default build script target
by default. To override which target should be resolved, specify the target
name via the PYOXIDIZER_BUILD_TARGET
environment variable. e.g.:
$ PYOXIDIZER_BUILD_TARGET=build-artifacts cargo build
build-mode-prebuilt-artifacts
¶
This mode tells the build script to reuse artifacts that were already built.
(Perhaps you called pyoxidizer build
or pyoxidizer run-build-script
outside the context of a normal cargo build
.)
In this mode, the build script will look for artifacts in the directory
specified by PYOXIDIZER_ARTIFACT_DIR
if set, falling back to OUT_DIR
.
See Build Artifacts for documentation on the required
artifacts.
build-mode-standalone
¶
Do not attempt to invoke pyoxidizer
or find artifacts it would have
built. It is possible to build the pyembed
crate in this mode if
the rust-cpython
and python3-sys
crates can find a Python
interpreter. But, the pyembed
crate may not be usable or work in
the way you want it to.
This mode is intended to be used for performing quick testing on the
pyembed
crate. It is quite possible that linking errors will occur
in this mode unless you take additional actions to point Cargo at
appropriate libraries.
cpython-link-unresolved-static
¶
Configures the link mode of the cpython
crate to use a static
pythonXY
library without resolving the symbol at its own build
time. The pyembed
crate or a crate building it will need to emit
cargo:rustc-link-lib=static=pythonXY
and any
cargo:rustc-link-search=native={}
lines to specify an explicit
pythonXY
library to link against.
This is the link mode used to produce self-contained binaries containing
libpython
and pyembed
code.
cpython-link-default
¶
Configures the link mode of the cpython
crate to use default
semantics. The crate’s build script will find a pre-built Python
library by querying the python
defined by PYTHON_SYS_EXECUTABLE
or found on PATH
. See the cpython
crate’s documentation for
more.
This link mode should be used when linking against an existing libpython
that can be found by the cpython
crate’s build script.
Build Artifacts¶
When using build-mode-prebuilt-artifacts
or build-mode-pyoxidizer-exe
,
the pyembed
crate consumes special artifacts as part of its build process
to provide the embedded Python interpreter. These artifacts are typically
generated by PyOxidizer. However, there is nothing stopping anyone from
producing equivalent artifacts via other means and having pyembed
consume
them.
The way this mode works is the build script is pointed at a directory
containing artifacts. The only required artifact is a cargo_metadata.txt
file. This file contains lines which will be printed to stdout by the
crate build script. These lines typically contain cargo:
lines, which
influence Cargo’s configuration for the crate.
The cargo:
lines must define a pre-built pythonXY
library to
link against. That library name is literally pythonXY
and XY
is not
a placeholder for a version string!
Use cases like PyOxidizer derive a custom library containing Python’s
core symbols. The cargo:
lines for this use case will look something
like the following:
cargo:rustc-link-lib=depend0
cargo:rustc-link-lib=depend1
cargo:rustc-link-lib=static=depend2
cargo:rustc-link-lib=static=depend3
cargo:rustc-link-lib=static=pythonXY
cargo:rustc-link-search=native=/path/to/libraries
Essentially what PyOxidizer does is compile a custom library containing Python.
This will be named pythonXY.lib
or pythonXY.dll
on Windows and
libpythonXY.a
or libpythonXY.so
on UNIX platforms. It then lists link
library dependencies as needed and registers the generated pythonXY
library
to be linked from the context of the pyembed
crate.
Deriving a custom library containing Python is fairly complex! From the
perspective of build-mode-prebuilt-artifacts
, all that is strictly
needed is for the cargo_metadata.txt
to define how to link against a
pythonXY
library. It is even possible to alias pythonXY
to an
existing Python library already on your system (this is effectively
what build-mode-default
does). So a minimal cargo_metadata.txt
might look something like this:
cargo:rustc-link-lib=pythonXY:python3.9 cargo:rustc-link-search=native=/path/to/directory/containing/python/library