Packaging Primitives in
PyOxidizer’s run-time behavior is controlled by
Starlark (a Python-like language) configuration files. See Configuration Files
for documentation on these files, including low-level API documentation.
This document gives a medium-level overview of the important Starlark types and functions and how they all interact.
Targets Define Actions¶
As detailed at Targets, a PyOxidizer configuration
file is composed of named targets, which are functions returning an object
that may have a build or run action attached. Commands like
pyoxidizer build identify a target to evaluate then effectively
walk the dependency graph evaluating dependent targets until the
requested target is built.
Defining an Executable Embedding Python¶
In this example, we create an executable embedding Python:
def make_exe(): dist = default_python_distribution() return dist.to_python_executable("myapp") register_target("exe", make_exe) resolve_targets()
PythonDistribution.to_python_executable() accepts an optional
PythonPackagingPolicy instance that influences how the executable
is built and what resources are added where. See the
type documentation for the
list of parameters that can be influenced. Some of this behavior
is described in the sections below. Other examples are provided
throughout the Packaging User Guide documentation.
Configuring the Python Interpreter Run-Time Behavior¶
Starlark type configures the default behavior of the Python interpreter
embedded in built binaries.
PythonInterpreterConfig instance is associated with
PythonExecutable instances when they are created. A custom
instance can be passed into
to use non-default settings.
def make_exe(): dist = default_python_distribution() config = dist.make_python_interpreter_config() config.run_command = "print('hello, world')" return dist.to_python_executable("myapp", config=config) register_target("exe", make_exe) resolve_targets()
Control of low-level Python interpreter settings, such as whether environment variables (like
PYTHONPATH) should influence run-time behavior, whether stdio should be buffered, and the filesystem encoding to use.
Whether to enable the importing of Python modules from the filesystem and what the initial value of
The memory allocator that the Python interpreter should use.
What Python code to run when the interpreter is started.
terminfodatabase should be located.
Many of these settings are not needed for most programs and the defaults
are meant to be reasonable for most programs. However, some settings - such
run_* arguments defining what Python code to run by default - are
required by most configuration files.
Adding Python Packages to Executables¶
PythonExecutable Starlark type contains just the
Python interpreter and standard library derived from the
from which it came. While you can use PyOxidizer to produce an executable
containing just a normal Python distribution with nothing else, many people
will want to add their own Python packages/code.
Instances of these types can be created dynamically or by performing
common Python packaging operations (such as invoking
pip install) via
various methods on
PythonExecutable instances. These Python package
resource instances can then be added to
so they are part of the built binary.
Install Manifests Copy Files Next to Your Application¶
starlark_tugger.FileManifest Starlark type represents a
collection of files and their content. When
starlark_tugger.FileManifest instances are returned from a
target function, their build action results in their contents
being manifested in a directory having the name of the build target.
starlark_tugger.FileManifest instances can be used to
construct custom file install layouts.
Say you have an existing directory tree of files you want to copy
next to your built executable defined by the
starlark_tugger.glob() function can be used to discover
existing files on the filesystem and turn them into a
starlark_tugger.FileManifest. You can then return this
starlark_tugger.FileManifest directory or overlay it onto another
starlark_tugger.FileManifest.add_manifest(). Here’s an example:
def make_exe(): dist = default_python_distribution() return dist.to_python_executable("myapp") def make_install(exe): m = FileManifest() m.add_python_resource(".", exe) templates = glob(["/path/to/project/templates/**/*"], strip_prefix="/path/to/project/") m.add_manifest(templates) return m register_target("exe", make_exe) register_target("install", make_install, depends=["exe"], default=True) resolve_targets()
We introduce a new
install target and
make_install() function which
starlark_tugger.FileManifest. It adds the
PythonExecutable (represented by the
exe argument/variable) to
that manifest in the root directory, signified by
Next, it calls
glob() to find all files in the
/path/to/project/templates/ directory tree, strips the path prefix
/path/to/project/ from them, and then merges all of these files into
the final manifest.
InstallManifest is built, the final layout should look something
like the following:
See Packaging Files Instead of In-Memory Resources for more on this topic.