.. py:currentmodule:: oxidized_importer .. _pyembed_crate_configuration: =================== 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 :ref:`pyembed_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. .. _pyembed_build_artifacts: 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