Recipe file reference#
A Rattler-Build recipe is a recipe.yaml file. This page documents its fields
and their accepted values. To migrate a meta.yaml recipe, see
Converting from conda-build.
Top-level structure#
The recipe spec has the following parts:
-
schema_version: optional integer identifying the recipe schema version. Only1is currently accepted; omit this field to default to schema version 1. -
context: to set up variables that can later be used in Jinja string interpolation -
package: defines name, version etc. of the top-level package -
source: points to the sources that need to be downloaded in order to build the recipe -
build: defines how to build the recipe and what build number to use -
requirements: defines requirements of the top-level package -
tests: defines tests for the top-level package -
outputs: a recipe can have multiple outputs. Each output can and should have apackage,requirementsandtestsection -
about: package metadata such as homepage, license and description -
extra: free-form metadata that rattler-build does not interpret
Schema#
The recipe JSON Schema is used for validation and editor integration. See Automatic recipe linting for setup instructions.
Example#
# this sets up "context variables" (in this case name and version) that
# can later be used in Jinja expressions
context:
version: 1.1.0
name: imagesize
# top level package information (name and version)
package:
name: ${{ name }}
version: ${{ version }}
# location to get the source from
source:
url: https://pypi.io/packages/source/${{ name[0] }}/${{ name }}/${{ name }}-${{ version }}.tar.gz
sha256: f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5
# build number (should be incremented if a new build is made, but version is not incrementing)
build:
number: 1
script: python -m pip install .
# the requirements at build and runtime
requirements:
host:
- python
- pip
run:
- python
# tests to validate that the package works as expected
tests:
- python:
imports:
- imagesize
# information about the package
about:
homepage: https://github.com/shibukawa/imagesize_py
license: MIT
summary: "Getting image size from png/jpeg/jpeg2000/gif file"
description: |
This module analyzes jpeg/jpeg2000/png/gif image header and
return image size.
repository: https://github.com/shibukawa/imagesize_py
documentation: https://pypi.python.org/pypi/imagesize
# the below is conda-forge specific!
extra:
recipe-maintainers:
- somemaintainer
Package section#
Specifies package information.
- name: The lower case name of the package. It may contain "
-", but no spaces. - version: The version number of the package. Use the PEP-386 verlib
conventions. Cannot contain "
-". YAML interprets version numbers such as 1.0 as floats, meaning that 0.10 will be the same as 0.1. To avoid this, put the version number in quotes so that it is interpreted as a string.
Source section#
Specifies where the package source comes from. A source can be a URL archive, a Git repository, or a local path, and can include patches.
Source from tarball or zip archive#
source:
url: https://pypi.python.org/packages/source/b/bsdiff4/bsdiff4-1.1.4.tar.gz
md5: 29f6089290505fc1a852e176bd276c43
sha256: 5a022ff4c1d1de87232b1c70bde50afbb98212fd246be4a867d8737173cf1f8f
A source may be verified with sha256 and/or md5; sha1 is not supported.
If an extracted archive contains only 1 folder at its top level, its contents will be moved 1 level up, so that the extracted package contents sit in the root of the work folder.
An empty sha256 or md5 (e.g. sha256: "") is accepted as an all-zeros
placeholder (0000...0000). This is handy while scaffolding a recipe before the
real checksum is known: the build still downloads the source and reports the
actual checksum in the resulting mismatch, which you can then paste back into
the recipe.
Supported archive formats#
When the URL points to one of the archive formats listed below, the file is downloaded to the source cache and automatically extracted into the work directory. Detection is based on the file extension only.
- Tar archives:
.tar,.tar.gz(.tgz,.taz),.tar.bz2(.tbz,.tbz2,.tz2),.tar.xz(.txz),.tar.lzma(.tlz),.tar.zst(.tzst),.tar.Z(.taZ),.tar.lz,.tar.lzo - Zip archives:
.zip - 7-Zip archives:
.7z
Files with any other extension (for example .rpm, .deb, .dmg,
.AppImage, single binaries, …) are downloaded and placed in the work
directory as-is, without extraction. If you need to unpack such a file, install
the appropriate tooling as a build requirement and extract it from your
build script. The same applies when file_name is
set on an archive source — extraction is then disabled for that source.
Specifying a file name#
For URL and local path sources, file_name renames the downloaded file in the work directory.
The primary use case is giving a clean name to pre-built binaries whose URL path segments are not
descriptive:
source:
url: https://github.com/owner/project/releases/download/v1.0.0/project-v1.0.0-linux-amd64
sha256: <sha256>
file_name: project # rename to a clean, platform-independent name
Setting file_name disables automatic archive extraction
When file_name is set on an archive source (.tar.gz, .zip, .7z, etc.), the archive is
not extracted — it is placed in the work directory as-is under the given name.
This is true even if file_name is set to the same name the archive would have had by default:
source:
url: https://pypi.python.org/packages/source/b/bsdiff4/bsdiff4-1.1.4.tar.gz
sha256: 5a022ff4c1d1de87232b1c70bde50afbb98212fd246be4a867d8737173cf1f8f
# The archive is NOT extracted — it is placed as bsdiff4-1.1.4.tar.gz in the work directory
file_name: bsdiff4-1.1.4.tar.gz
To download an archive and have it extracted automatically (the default behaviour), omit
file_name:
Source from git#
source:
git: https://github.com/ilanschnell/bsdiff4.git
# branch: master # note: defaults to fetching the repo's default branch
You can use rev to pin the commit version directly:
source:
git: https://github.com/ilanschnell/bsdiff4.git
rev: "50a1f7ed6c168eb0815d424cba2df62790f168f0"
Or you can use the tag:
git can also be a relative path to the recipe directory:
Furthermore, if you want to fetch just the current "HEAD" (this may result in
non-deterministic builds), then you can use depth.
source:
git: https://github.com/ilanschnell/bsdiff4.git
depth: 1 # note: the behaviour defaults to -1
Note: tag or rev may not be available within commit depth range, hence we don't
allow using rev or the tag and depth of them together if not set to -1.
source:
git: https://github.com/ilanschnell/bsdiff4.git
tag: "1.1.4"
depth: 1 # error: use of `depth` with `rev` is invalid, they are mutually exclusive
When you want to use git-lfs, you need to set lfs: true. This will also pull
the lfs files from the repository.
By default, Rattler-Build will recursively initialize and update all git
submodules. For repositories with large or numerous submodules that aren't needed
for the build, you can disable this by setting submodules: false:
source:
git: https://github.com/riscv-collab/riscv-gnu-toolchain.git
tag: "2024.09.03"
submodules: false # note: defaults to true
If you need only specific submodules, set submodules: false and initialize them
manually in your build script.
Verifying commit hash with expected_commit#
Note
This feature is only available with --experimental as it was not part of the standardization yet.
For security and reproducibility, you can specify an expected_commit field to verify that the checked out commit matches the expected SHA hash. This is useful to detect if a tag or branch has been moved to point to a different commit:
source:
git: https://github.com/ilanschnell/bsdiff4.git
tag: "1.1.4"
expected_commit: 50a1f7ed6c168eb0815d424cba2df62790f168f0
If the actual commit does not match the expected commit, the build will fail with an error message indicating the mismatch. This feature is inspired by Wolfi/Melange and provides an additional layer of security for your builds.
Source from a local path#
If the path is relative, it is taken relative to the recipe directory. The source is copied to the work directory before building.
By default, all files in the local path that are ignored by git are also ignored
by Rattler-Build. You can disable this behavior by setting use_gitignore to
false.
Patches#
Patches may optionally be applied to the source.
source:
#[source information here]
patches:
- my.patch # the patch file is expected to be found in the recipe
Patch paths are resolved relative to the recipe directory. They may also refer to a restricted set of build-time directory variables that are only known once the build has started:
${{ SRC_DIR }}– the source working directory${{ RECIPE_DIR }}– the recipe directory${{ BUILD_DIR }}– the top-level build directory
This is useful when a patch ships inside another source. Because sources are
fetched in order into the shared SRC_DIR, a later source can apply a patch
that was extracted from an earlier one:
source:
- url: https://example.com/tool-{{ version }}.tar.gz # ships patches under src/
sha256: "..."
- url: https://example.com/lib-{{ version }}.tar.gz
sha256: "..."
target_directory: lib_src
patches:
- ${{ SRC_DIR }}/src/patches/0001-fix.patch
Only the variables listed above are allowed in patches; any other variable
is treated as undefined and produces an error.
Destination path#
Within Rattler-Build's work directory, you may specify a particular folder to
place the source into. Rattler-Build will always drop you into the same folder
([build folder]/work), but it's up to you whether you want your source extracted
into that folder, or nested deeper. This feature is particularly useful when dealing
with multiple sources, but can apply to recipes with single sources as well.
Attestation verification (experimental)#
Note
This feature requires the --experimental flag.
For URL sources, you can specify an attestation block to verify that the downloaded archive
was built by an expected publisher using Sigstore attestations.
source:
url: https://files.pythonhosted.org/packages/.../flask-3.1.1.tar.gz
sha256: "..."
attestation:
publishers:
- github:pallets/flask
The attestation config has the following fields:
publishers- A list of publisher identities ingithub:owner/repoformat. At least one publisher must match for verification to succeed.bundle_url(optional) - URL to the Sigstore bundle file. For PyPI sources, this is automatically derived from the PyPI attestation API. For GitHub releases, use the patternhttps://github.com/{owner}/{repo}/releases/download/{tag}/{filename}.sigstore.json.
See the Sigstore source attestation documentation for more details and examples.
Source from multiple sources#
Some software is most easily built by aggregating several pieces.
The syntax is a list of source dictionaries. Each member of this list follows the same rules as the single source. All features for each member are supported.
Example:
source:
- url: https://package1.com/a.tar.bz2
target_directory: stuff
- url: https://package1.com/b.tar.bz2
target_directory: stuff
- git: https://github.com/mamba-org/boa
target_directory: boa
Here, the two URL tarballs will go into one folder, and the git repo is checked
out into its own space. git will not clone into a non-empty folder.
Include only certain files from source#
While you can specify only the files you need from a source, source.filter gives you the option to filter with globs instead.
Glob patterns throughout the recipe file can also use an include / exclude
pair:
source:
path: /path/to/source
filter:
include:
- include/**/*.h
exclude:
- include/**/private.h
See the glob syntax reference for supported patterns and matching behavior.
The filter field is available for path, url, and git sources. It is
applied to the files that are copied into the work directory — the copied tree
for directory path sources, the contents of the extracted archive for url
sources (and path sources pointing to an archive), and the checked-out tree
for git sources. This is useful for trimming large sources down to the parts
you actually need to build:
source:
- url: https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-${{ version }}.tar.gz
sha256: ad18b70e287954c3d62bc7e0b86e7b7af2adf87bcfce21c15fe717f101d7aace
filter:
# we don't want to accidentally build more than clang here
- cmake/*
- clang/*
- clang-tools-extra/*
source:
url: https://github.com/pytorch/pytorch/releases/download/v${{ version }}/pytorch-v${{ version }}.tar.gz
sha256: 757145cfd55c7c8c01f58c959f76230641cc67fdd1d8b6a130f93ad1bc116f5f
filter:
exclude:
# ensure we use our own fmt
- third_party/fmt/*
Build section#
Specifies build information.
Fields that select paths accept the patterns described in the glob syntax reference. Build file patterns are relative to the package prefix.
Build number and string#
The build number should be incremented for new builds of the same version. The
number defaults to 0. The build string cannot contain "-". The string defaults
to the default Rattler-Build build string plus the build number.
Dynamic linking#
This section contains settings for the shared libraries and executables on Linux and macOS.
build:
dynamic_linking:
rpaths:
- lib/
binary_relocation: true
rpath_allowlist:
- /usr/lib/**
missing_dso_allowlist:
- "**/libcuda.so*"
overdepending_behavior: error
overlinking_behavior: error
Fields (all optional):
rpaths- List of RPATH entries to set on ELF and Mach-O binaries. Defaults to["lib/"].binary_relocation- Controls which binaries get their prefixes rewritten during installation. Acceptstrue(all binaries, default),false(none) or a list of glob patterns to include.rpath_allowlist- Glob patterns of RPATH entries that may point outside the package prefix without triggering an overlinking warning.missing_dso_allowlist- Glob patterns of dynamic libraries that are allowed to be missing from the host environment without failing the overlinking check.overdepending_behavior- What to do when a declared dependency is not actually linked. One ofignoreorerror.overlinking_behavior- What to do when a binary links against a library that is not a declared dependency. One ofignoreorerror.
Package variant flags (V3, beta)#
Beta — opt in with --v3
This field is part of the V3 repodata revision and is only accepted when
Rattler-Build is invoked with --v3. Without the flag, recipes that set
build.flags fail to evaluate. See V3 packages for
background and a complete description.
Variant flags are short lowercase tags that describe a variant of the
package (e.g. cuda, blas:openblas). They are written into the package's
index.json and can be matched downstream with the V3 flags=[…]
MatchSpec key.
A flag must match the regex ^[a-z0-9_]+(:[a-z0-9_]+)?$ — lowercase ASCII,
digits and underscores, optionally with a single :-separated suffix. The
list is conditional and templated like other recipe lists, and any flag that
depends on a Jinja variable participates in variant hashing:
Script#
By default, Rattler-Build uses a build.sh file on Unix (macOS and Linux) and a
build.bat file on Windows, if they exist in the same folder as the recipe.yaml
file. With the script parameter you can either supply a different filename or
write out short build scripts. You may need to use selectors to use different
scripts for different platforms.
build:
# A very simple build script
script: pip install .
# The build script can also be a list
script:
- pip install .
- echo "hello world"
- if: unix
then:
- echo "unix"
Script object form#
For anything beyond a bare command list, script can be written as a mapping
with the following fields (all optional):
content- Inline commands to execute. Equivalent to passing a string or list directly asscript:. Accepts a string, a list of strings, orif/then/elseconditionals. Mutually exclusive withfile.file- Path to an external script file (relative to the recipe directory). If the filename has no extension, the platform-appropriate extension is appended (.shon Unix,.baton Windows). Mutually exclusive withcontent.env- Mapping of environment variables to set for the script. Values can be hard-coded strings or Jinja expressions, andenv.get(...)can be used to forward variables from the outer environment with an optional default.secrets- List of environment variable names whose values should be forwarded from the outer environment but masked in logs and stripped from the rendered recipe. The variables must already be set in the environment runningrattler-build.interpreter- Explicit interpreter to runcontentwith. Supported values arebash(default on Unix),cmd(Windowscmd.exe),powershell,nu(nushell),brush,python,perl,rscript,rubyandnode/nodejs. When unset, the interpreter is auto-detected from the script's file extension (.sh/.bash,.bat/.cmd,.ps1,.nu,.py,.pl,.r,.rb,.js).cwd- Working directory for the script. Relative paths are resolved against the host prefix ($PREFIX/%PREFIX%). Defaults to the build work directory.
Where interpreters come from
Every build and test script is launched through a native shell wrapper
(bash on Unix, cmd.exe on Windows) that activates the build/host
prefixes and then invokes the chosen interpreter as a command.
An interpreter that runs the build script is a build-time tool, so add it to
requirements.build (for example interpreter: nu → nushell,
interpreter: rscript → r-base, interpreter: node → nodejs). It is
resolved from the activated environment in the same order the PATH would:
the build prefix, then the host prefix, and for most interpreters the
system PATH as a last resort. So a host dependency is also found, but
build is the correct place; relying on a system copy works but makes builds
non-reproducible. When the build and host environments are merged
(build.merge_build_and_host_envs), that single environment is used.
Two interpreters are resolved differently:
- bash/cmd (and powershell on Windows) may be taken from the
system PATH on their native platform.
- brush is resolved only from the build environment (not the host
prefix or the system PATH), so it must be in requirements.build.
build:
script:
content:
- python -m pip install . -vv --no-deps --no-build-isolation
env:
# Hard-coded value
USE_SYSTEM_DEPS: "on"
# Forwarded from the outer environment with a default
CMAKE_ARGS: ${{ env.get("CMAKE_ARGS", default="") }}
secrets:
# Masked in logs; must be exported in the outer environment
- GITHUB_TOKEN
interpreter: bash
Using an external script file:
build:
script:
file: build/install.py
interpreter: python
env:
USE_SYSTEM_DEPS: "on"
requirements:
build:
# `python` is the interpreter, so it must be available in the build env
- python
Selecting nushell with the required build dependency:
build:
script:
interpreter: nu
content: |
echo "Hello from nushell!"
requirements:
build:
- nushell
Build steps (experimental)#
build.steps is an experimental alternative to build.script and requires
--experimental. script and steps are mutually exclusive, including
steps: [].
Each step is a scoped build-wrapper section. Step-local env values and cwd
changes apply only to that step. A step supports:
run- Required inline command, multiline string, or list of commands.if- Optional Jinja selector expression evaluated before the step runs. Do not wrap expressions in${{ }}.interpreter- Optional interpreter override for this step.cwd- Optional working directory for this step. Relative paths are resolved against the host prefix ($PREFIX/%PREFIX%).env- Optional environment variables scoped to this step.
build:
steps:
- if: unix
run:
- mkdir -p "$PREFIX/bin"
- cp "$RECIPE_DIR/tool" "$PREFIX/bin/tool"
- run: python -m pip install . --no-deps
env:
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ version }}
Windows multiline steps
On Windows, a multiline run: | block is emitted as one command-list item.
Fail-fast guards are inserted between list items, not between the physical
lines inside one multiline scalar.
See Build script for more examples and the full behaviour of environment variables, secrets, and interpreters.
Skipping builds#
Lists conditions under which Rattler-Build should skip the build of this recipe. Particularly useful for defining recipes that are platform-specific. By default, a build is never skipped.
Each entry is a Jinja expression (without the surrounding ${{ ... }}). Entries
that are not valid Jinja - an unbalanced bracket, for example - are reported as an
error instead of being silently treated as "do not skip". An entry that references a
variable which is not part of the variant still counts as "do not skip".
Architecture-independent packages#
Allows you to specify "no architecture" when building a package, thus making it compatible with all platforms and architectures. Architecture-independent packages can be installed on any platform.
Assigning the noarch key as generic tells conda to not try any manipulation of
the contents.
noarch: generic is most useful for packages such as static JavaScript assets
and source archives. For pure Python packages (similar to none-any wheels)
that can run on any Python version, you can use the noarch: python value instead:
Note
At the time of this writing, noarch packages should not make use
of preprocess-selectors: noarch packages are built with the directives which
evaluate to true in the platform it is built on, which probably will result
in incorrect/incomplete installation in other platforms.
Conditional noarch#
The noarch key can be set conditionally from a variant variable, which is
useful for recipes that build a noarch: python package in some variants and
an arch-specific package in others:
build:
# no noarch when `use_noarch` is false or undefined
noarch: ${{ "python" if use_noarch }}
# or, with an explicit else branch:
noarch: ${{ "python" if use_noarch else none }}
An expression that renders to an empty or null-like value (none, null,
~, or the empty string) — as well as a literal noarch: null — is treated
the same as omitting the noarch key entirely. Referencing an undefined
variable is still an error: if the variable is only defined on some platforms,
provide an explicit fallback with the default filter, e.g.
${{ "python" if use_noarch | default(false) }}.
Include only certain files in the package#
Sometimes you may want to include only a subset of the files installed by the
build process in your package. For this, the files key can be used. Only new
files are considered for inclusion (ie. files that were not in the host
environment beforehand).
build:
# select files to be included in the package
# this can be used to remove files from the package, even if they are installed in the
# environment
files:
- list
- of
- globs
The include / exclude glob form is also supported:
Omitting files packages every new file; giving it hands the selection to the
globs, so an empty list packages nothing:
A conditional list with no matching branch is still an explicit key, so it too packages nothing:
build:
files:
- if: linux
then: lib/libfoo.so
- if: osx
then: lib/libfoo.dylib
# on Windows no branch matches, so the package is empty
This matters most for outputs that inherit from a staging output, where every
file restored from the cache counts as new.
Python specific options#
Entry points#
The following example creates a Python entry point named "bsdiff4" that calls
bsdiff4.cli.main_bsdiff4(). This is needed in noarch: python packages to create
OS specific entry points at installation time.
build:
python:
entry_points:
- bsdiff4 = bsdiff4.cli:main_bsdiff4
- bspatch4 = bsdiff4.cli:main_bspatch4
Version independent (ABI3) packages#
Since Rattler-Build 0.35.0 and CEP 20 you can create version-independent Python packages that still contain compiled code.
ABI3 packages support building a native Python extension using a specific Python version and running it against any later Python version. ABI3 or stable ABI is supported by only CPython - the reference Python implementation with the Global Interpreter Lock (GIL) enabled.
Other build.python options#
skip_pyc_compilation- List of glob patterns of Python files that should be skipped when pre-compiling.pycfiles during the build. Only relevant for non-noarchPython packages.use_python_app_entrypoint- When set totrue, generates entry points that launch through thepython.appwrapper on macOS. Useful for GUI applications that need access to the main event loop.site_packages_path- Overrides the relativesite-packagesdirectory that thepythonpackage itself exports. Only meaningful when building thepythonpackage.
build:
python:
entry_points:
- mytool = mytool.cli:main
skip_pyc_compilation:
- "mypkg/vendored/**"
use_python_app_entrypoint: true
Post-processing#
Applies regex-based text replacements to files in the package during the packaging phase. Each entry specifies a set of files to match and a regex substitution to apply.
build:
post_process:
- files:
- "bin/*"
regex: "/old/path"
replacement: "/new/path"
- files:
- "**/*.cmake"
- "**/*.pc"
regex: "/home/builder"
replacement: "$PREFIX"
Each post_process entry has the following fields:
files(required) — A list of glob patterns selecting which files to process. Supportsinclude/excludemappings andif/then/elseconditionals.regex(required) — A regular expression pattern to match within each selected file.replacement(required) — The replacement string. Supports regex capture group references (e.g.$1,${name}).
All three fields are required for each entry.
Conditional post-processing#
post_process entries support if/then/else conditionals, including
nesting:
build:
post_process:
- if: unix
then:
- files:
- "lib/**/*.la"
regex: "/build/prefix"
replacement: "$PREFIX"
- files:
- "**/*.txt"
regex: "old_name"
replacement: "new_name"
In the example above, the .la file replacement runs only on Unix, while the
.txt replacement runs unconditionally.
Behavior#
- Post-processing runs during packaging, after relocation and Python post-processing, but before linking checks.
- Files are read as UTF-8 text using Rust’s read_to_string. If a matched file is not valid UTF-8, the build will fail.
- The regex uses
replace_allsemantics from Rust'sregexcrate: all non-overlapping matches in a file are replaced. - Steps are applied sequentially. Later entries see the results of earlier ones.
Output inheritance#
In multi-output recipes, each output inherits the top-level post_process if
the output does not define its own. If an output defines its own post_process, it fully overrides the top-level list. No merging is performed.
Always include / copy files#
By default, rattler-build packages only files that the build script creates
in the host prefix. The always_include_files and always_copy_files keys
override this on a per-glob basis:
always_include_files- Glob patterns of files to add to the package even if they were already present in the host environment before the build ran. Useful when the build replaces a file that another dependency installed.always_copy_files- Glob patterns of files that should be copied rather than hard-linked into the install prefix. Use this for files the build script mutates in place, so mutations in one package do not leak into other environments sharing the same package cache.
Merge build and host environments#
By default, build and host are separate prefixes so that cross-compilation
works correctly. For recipes that do not cross-compile, setting
merge_build_and_host_envs: true merges the two environments into a single
prefix, matching the behaviour of legacy conda-build recipes that don't
distinguish between build and host.
Prefix detection#
Controls how rattler-build finds and rewrites the build prefix inside
packaged files so that installed packages work from any install location.
build:
prefix_detection:
# Files that should always be treated as text or binary regardless of
# auto-detection
force_file_type:
text:
- bin/*.py
binary:
- lib/**/*.so
# Files that should be skipped entirely during prefix replacement
# (true = skip all, false = skip none, list = glob patterns)
ignore:
- share/doc/**
# Skip prefix detection in binary files (Unix only)
ignore_binary_files: false
force_file_type.text/force_file_type.binary- Glob patterns that force specific files to be treated as text or binary during prefix detection, overriding the automatic heuristics.ignore- Either a boolean or a list of glob patterns.trueskips prefix replacement for all files,false(default) enables it for all, and a list skips only the matching files.ignore_binary_files- Skip prefix replacement in binary files (Unix only). Binary relocation is still handled separately underdynamic_linking.
Variant configuration#
The variant key controls how the build participates in the variant matrix
derived from variant_config.yaml and pin_subpackage(..., exact=True).
use_keys- Variant keys that must be part of this build's variant matrix even if they are not referenced elsewhere in the recipe.ignore_keys- Variant keys that should be stripped from this build's variant even if they are referenced. Packages built withignore_keyswill not get a separate output per value of that key.down_prioritize_variant- Integer priority offset applied to this variant during solving (defaults to0). Higher values make the variant less preferred when multiple variants satisfy a dependency. This is implemented viatrack_features, so it is the magnitude of the value that matters (the sign is ignored).
Include build recipe#
The recipe and rendered recipe.yaml file are included in
the package_metadata by default. You can disable this by passing
--no-include-recipe on the command line.
Note
See the full build options guide for longer-form explanations and examples of the build keys documented above.
Requirements section#
Specifies the build and runtime requirements. Dependencies of these requirements are included automatically.
Versions for requirements must follow the conda/mamba match specification. See
build-version-spec.
V3 MatchSpec keys (beta — opt in with --v3)
When Rattler-Build is invoked with --v3, dependency strings everywhere
in this section (build, host, run, run_constraints, extras,
run_exports) accept three additional bracket keys:
flags=[…]— match by package variant flag (pytorch[flags=[cuda]],numpy[flags=[blas:*]]).when="…"— only include the dependency when the embedded predicate is satisfied (scipy[when="python >=3.10"]). Replaces the deprecated; ifsyntax.extras=[…]— pull in optional dependency groups declared by the producing package (mypkg[extras=[plot]]).
Without --v3 these keys are rejected at parse time. See
V3 packages for the full description.
Build#
Tools required to build the package.
These packages are run on the build system and include things such as version
control systems (git, svn) make tools (GNU make, Autotool, CMake) and compilers
(real cross, pseudo-cross, or native when not cross-compiling), and any source
pre-processors.
Packages which provide "sysroot" files, like the CDT packages (see below), also
belong in the build section.
Host#
Represents packages that need to be specific to the target platform when the
target platform is not necessarily the same as the native build platform. For
example, in order for a recipe to be "cross-capable", shared libraries
requirements must be listed in the host section, rather than the build section,
so that the shared libraries that get linked are ones for the target platform,
rather than the native build platform. You should also include the base
interpreter for packages that need one. In other words, a Python package would
list python here and an R package would list mro-base or r-base.
requirements:
build:
- ${{ compiler('c') }}
- if: linux
then:
- ${{ cdt('xorg-x11-proto-devel') }}
host:
- python
Note
When both "build" and "host" sections are defined, the build section can
be thought of as "build tools" - things that run on the native platform, but
output results for the target platform (e.g. a cross-compiler that runs on
linux-64, but targets linux-armv7).
The PREFIX environment variable points to the host prefix. With respect to
activation during builds, both the host and build environments are activated.
The build prefix is activated before the host prefix so that the host prefix has
priority over the build prefix. Executables that don't exist in the host prefix
should be found in the build prefix.
The build and host prefixes are always separate when both are defined, or when
${{ compiler() }} Jinja2 functions are used. The only time that build and host
are merged is when the host section is absent, and no ${{ compiler() }} Jinja2
functions are used in recipe.yaml.
Run#
Packages required to run the package.
These are the dependencies that are installed automatically whenever the package is installed. Package names should follow the package match specifications.
To build a recipe against different versions of NumPy and ensure that each
version is part of the package dependencies, list numpy as a requirement in
recipe.yaml and use a conda_build_config.yaml file with multiple NumPy
versions.
Run constraints#
Packages that are optional at runtime but must obey the supplied additional constraint if they are installed.
Package names should follow the package match specifications.
For example, let's say we have an environment that has package "a" installed at
version 1.0. If we install package "b" that has a run_constraints entry of
"a >1.0", then mamba would need to upgrade "a" in the environment in order to
install "b".
This is especially useful in the context of virtual packages, where the
run_constraints dependency is not a package that mamba manages, but rather a
virtual
package
that represents a system property that mamba can't change. For example, a
package on Linux may impose a run_constraints dependency on __glibc >=2.12.
This is the version bound consistent with CentOS 6. Software built against glibc
2.12 will be compatible with CentOS 6. This run_constraints dependency helps
mamba, conda or pixi tell the user that a given package can't be installed if their system
glibc version is too old.
Optional dependencies / extras#
requirements.extras is supported in both legacy and V3 packages. extras
is a mapping from a group name to a list of dependencies that are not
installed by default. Consumers opt in via the V3-only extras=[…]
MatchSpec key, which requires --v3. This mirrors the
optional-dependencies idea from pyproject.toml.
requirements:
run:
- python >=3.10
extras:
plot:
- matplotlib >=3.8
full:
- matplotlib >=3.8
- pandas >=2
A downstream recipe can then pull a group in by name:
In the built package, optional groups are written into
index.json#/extra_depends.
Run exports#
Packages may have runtime requirements such as shared libraries (e.g. zlib), which are required for linking at build time, and for resolving the link at run time.
With run_exports packages runtime requirements can be implicitly added.
run_exports are weak by default, these two requirements for the zlib package are therefore equivalent:
requirements:
run_exports:
weak:
- ${{ pin_subpackage('libzlib', exact=True) }}
The alternative to weak is strong.
For gcc this would look like this:
requirements:
run_exports:
strong:
- ${{ pin_subpackage('libgcc', exact=True) }}
weak exports will only be implicitly added as runtime requirement, if the package is a host dependency.
strong exports will be added for both build and host dependencies.
In addition to weak and strong, the run_exports mapping supports the
following keys:
weak_constraints- Likeweak, but the exported specs are added to the downstream package'srun_constraintsrather than itsrunrequirements.strong_constraints- Same asweak_constraints, but applies to both build and host dependencies.noarch- Run exports that are only added for downstreamnoarchpackages. Useful when a package ships architecture-specific builds but wants to pin differently for pure-Python consumers.
requirements:
run_exports:
strong:
- ${{ pin_subpackage('libfoo', exact=True) }}
weak_constraints:
- foo-plugin >=2
noarch:
- python >=3.9
In the following example you can see the implicitly added runtime dependencies.
requirements:
build:
- gcc # has a strong run export
host:
- zlib # has a (weak) run export
# - libgcc <-- implicitly added by gcc
run:
# - libgcc <-- implicitly added by gcc
# - libzlib <-- implicitly added by libzlib
Ignore run exports#
There maybe cases where an upstream package has a problematic run_exports constraint.
You can ignore it in your recipe by listing the upstream package name in the
ignore_run_exports section in requirements.
You can ignore them by package name, or by naming the runtime dependency directly.
Using a runtime dependency name:
Note
ignore_run_exports only applies to runtime dependencies coming from an upstream package.
Tests section#
Rattler-Build supports four different types of tests. The "script test" installs
the package and runs a list of commands. The "Python test" attempts to import a
list of Python modules and runs pip check. The "downstream test" runs the tests
of a downstream package that reverse depends on the package being built. And lastly,
the "package content test" checks if the built package contains the mentioned items.
The tests section is a list of these items:
tests:
- script:
- echo "hello world"
requirements:
run:
- pytest
files:
source:
- test-data.txt
- python:
imports:
- bsdiff4
pip_check: true # this is the default
- downstream: numpy
Script test#
The script test has 3 top-level keys: script, files and requirements. Only
the script key is required.
Test commands#
Commands that are run as part of the test.
External scripts#
You can also easily run a script from your recipe directory.
Note that your package should either depend on the interpreter (e.g. Python or R)
or you need to add a requirements section to the test that installs the interpreter.
Extra test files#
Test files that are copied from the source work directory into the temporary test directory and are needed during testing (note that the source work directory is otherwise not available at all during testing).
You can also include files that come from the recipe folder. They are copied
into the test directory as well.
At test execution time, the test directory is the current working directory.
tests:
- script:
- ls
files:
source:
- myfile.txt
- tests/
- some/directory/pattern*.sh
recipe:
- extra-file.txt
Test requirements#
In addition to the runtime requirements, you can specify requirements needed
during testing. The runtime requirements that you specified in the "run" section
described above are automatically included during testing (because the built
package is installed as it regularly would be).
In the build section you can specify additional requirements that are only
needed on the build system for cross-compilation (e.g. emulators or compilers).
Python tests#
For this test type you can list a set of Python modules that need to be importable. The test will fail if any of the modules cannot be imported.
The test will also automatically run pip check to check for any broken
dependencies. This can be disabled by setting pip_check: false in the YAML.
tests:
- python:
imports:
- bsdiff4
- bspatch4
pip_check: true # can be left out because this is the default
python_version: 3.12.* # optional: use list for multiple versions, default resolves to environment
Internally this will write a small Python script that imports the modules:
Perl tests#
For this test type you can list a set of Perl modules that need to be importable. The test will fail if any of the modules cannot be imported.
Internally this will write a small Perl script that imports the modules:
R tests#
For this test type you can list a set of R modules that need to be importable. The test will fail if any of the modules cannot be imported.
Internally this will write a small R script that imports the modules:
Ruby tests#
For this test type you can list a set of Ruby modules or gems that need to be loadable. The test will fail if any of them cannot be required.
Internally this will write a small Ruby script that requires each module:
Check for package contents#
Checks if the built package contains the mentioned items. These checks are executed directly at the end of the build process to make sure that all expected files are present in the package. File checks use the standard glob syntax relative to the installed test prefix.
tests:
- package_contents:
# checks for the existence of files inside $PREFIX or %PREFIX%
# or, checks that there is at least one file matching the specified `glob`
# pattern inside the prefix
files:
- etc/libmamba/test.txt
- etc/libmamba
- etc/libmamba/*.mamba.txt
# For more advanced cases, you can use the expanded form with exists and not_exists:
# files:
# exists:
# - etc/libmamba/test.txt
# - etc/libmamba
# - etc/libmamba/*.mamba.txt
# not_exists:
# - etc/libmamba/unwanted.txt
# checks for the existence of `mamba/api/__init__.py` inside of the
# Python site-packages directory (note: also see Python import checks)
site_packages:
- mamba.api
# looks in $PREFIX/bin/mamba for unix and %PREFIX%\Library\bin\mamba.exe on Windows
# note: also check the `commands` and execute something like `mamba --help` to make
# sure things work fine
bin:
- mamba
# enable strict mode: error if any file in the package is not matched by one of the globs
# (default: false)
strict: true
# searches for `$PREFIX/lib/libmamba.so` or `$PREFIX/lib/libmamba.dylib` on Linux or macOS,
# on Windows for %PREFIX%\Library\lib\mamba.dll & %PREFIX%\Library\bin\mamba.bin
lib:
- mamba
# searches for `$PREFIX/include/libmamba/mamba.hpp` on unix, and
# on Windows for `%PREFIX%\Library\include\libmamba\mamba.hpp`
include:
- libmamba/mamba.hpp
Downstream tests#
A downstream test can mention a single package that has a dependency on the package being built. The test will install the package and run the tests of the downstream package with our current package as a dependency.
Sometimes downstream packages do not resolve. In this case, the test is ignored.
Outputs section#
Tip
For a complete guide including staging outputs and examples, see Multi-Output Recipes.
Explicitly specifies packaging steps. This section supports multiple outputs, as well as different package output types. The format is a list of mappings.
When using multiple outputs, certain top-level keys are "forbidden": package
and requirements. Instead of package, a top-level recipe key can be
defined. The recipe.name is ignored but the recipe.version key is used as
default version for each output. Other "top-level" keys are merged into each
output (e.g. the about section) to avoid repetition. Each output is a
complete recipe, and can have its own build, requirements, and test
sections.
recipe:
# the recipe name is ignored
name: some
version: 1.0
outputs:
- package:
# version is taken from recipe.version (1.0)
name: some-subpackage
- package:
name: some-other-subpackage
version: 2.0
Each output acts like an independent recipe and can have their own script,
build_number, and so on.
If script lacks a file extension,
the appropriate extension for the platform will be appended,
e.g. the above will run install-subpackage.sh in bash on most platforms
and install-subpackage.bat in cmd.exe on Windows.
Each output is built independently. You should take care of not packaging the same files twice.
Subpackage requirements#
Like a top-level recipe, a subpackage may have zero or more dependencies listed as build, host or run requirements.
The dependencies listed as subpackage build requirements are available only during the packaging phase of that subpackage.
You can also use the pin_subpackage function to pin another output from the
same recipe.
outputs:
- package:
name: libtest
- package:
name: test
requirements:
build:
- ${{ pin_subpackage('libtest', upper_bound='x.x') }}
The outputs are topologically sorted by the dependency graph which is taking the
pin_subpackage invocations into account. When using pin_subpackage(name,
exact=True) a special behavior is used where the name package is injected as
a "variant" and the variant matrix is expanded appropriately. For example, when
you have the following situation, with a variant_config.yaml file that
contains openssl: [1, 3]:
outputs:
- package:
name: libtest
requirements:
host:
- openssl
- package:
name: test
requirements:
build:
- ${{ pin_subpackage('libtest', exact=True) }}
Due to the variant config file, this will build two versions of libtest. We
will also build two versions of test, one that depends on libtest (openssl
1) and one that depends on libtest (openssl 3).
Staging outputs#
Note
See the staging outputs guide for a full walkthrough.
A staging output builds code once and caches the results. Other package outputs
can inherit from a staging cache to receive the built files directly in
their $PREFIX without rebuilding. Staging outputs do not produce package
artifacts themselves.
outputs:
- staging:
name: my-staging-cache # required, follows package name rules
source: # optional, additional sources
- url: https://example.com/src.tar.gz
sha256: abc123...
requirements:
build: # build-time dependencies
- ${{ compiler('c') }}
- cmake
host: # host dependencies
- zlib
ignore_run_exports: # optional, filter run exports at the staging level
from_package:
- zlib
build:
script: # build script (only field allowed under build)
- cmake -B build
- cmake --build build --target install
The staging: output supports:
staging.name— required, the cache name that inheriting packages referencesource— optional source sections (in addition to top-level sources)requirements—build,host, andignore_run_exports(norunrequirements)build.script— the build script to execute
Inheriting from staging#
Package outputs use the inherit: key to receive files from a staging cache.
Two forms are supported:
outputs:
- staging:
name: my-build
build:
script:
- make install
# Short form — inherits all files and run exports
- package:
name: mylib
inherit: my-build
build:
files:
- lib/**
# Extended form — control run exports inheritance
- package:
name: mylib-dev
inherit:
from: my-build
run_exports: false # do not inherit run exports from staging deps
build:
files:
- include/**
When a package inherits from staging:
- The staging cache's prefix files are copied into the package's
$PREFIX - The staging cache's work directory is restored (allowing incremental builds)
- Run exports from staging dependencies are added to the package's run
requirements (unless
run_exports: falseis set) - The
filesglobs select which subset of the inherited files end up in the final package
Top-level inheritance#
In recipes that have both a top-level build: section and staging outputs,
package outputs can choose to inherit from the top-level build instead of from
staging by setting inherit: null:
build:
script:
- echo "top-level" > $PREFIX/share/data.txt
outputs:
- staging:
name: compile-stage
build:
script:
- echo "compiled" > $PREFIX/lib/compiled.so
- package:
name: compiled-pkg
inherit: compile-stage # gets files from staging
build:
files:
- lib/**
- package:
name: data-pkg
inherit: null # gets files from top-level build
build:
files:
- share/**
About section#
Specifies identifying information about the package. The information displays in the package server.
about:
homepage: https://example.com/bsdiff4
license: BSD-3-Clause # (1)!
license_file: LICENSE
summary: binary diff and patch using the BSDIFF4-format
description: |
Long description of bsdiff4 ...
repository: https://github.com/ilanschnell/bsdiff4
documentation: https://docs.com
- Only the SPDX specifiers are allowed, more info here: SPDX
If you want another license type
LicenseRef-<YOUR-LICENSE>can be used, e.g.license: LicenseRef-Proprietary
The full list of accepted about keys:
homepage- Project homepage URL.repository- Source repository URL.documentation- Documentation URL.license- SPDX license expression (see note above).license_file- License file(s) to include in the package (see below).license_family- Coarse license family (e.g.MIT,Apache,GPL). Deprecated and kept only for compatibility with legacyconda-buildrecipes; prefer setting a precise SPDX expression inlicense.summary- One-line description of the package.description- Longer free-form description.
License file#
Adds a file containing the software license to the package metadata.
Many licenses require the license statement to be distributed with the package.
The filename is relative to the source or recipe directory. The value can be a
single filename or a YAML list for multiple license files. Values can also point
to directories with license information. Directory entries must end with a /
suffix (this is to lessen unintentional inclusion of non-license files; all the
directory's contents will be unconditionally and recursively added).
If a license file is found in both the source and recipe directories, the file from the recipe directory is used (you should see a warning about this in the build log).
License file entries may also refer to a restricted set of build-time directory variables that are only known once the build has finished. These are resolved during packaging:
${{ PREFIX }}– the host prefix${{ BUILD_PREFIX }}– the build prefix${{ SRC_DIR }}– the source working directory${{ RECIPE_DIR }}– the recipe directory${{ BUILD_DIR }}– the top-level build directory
This is useful for packages (such as R packages) that install their license
files into ${{ PREFIX }} during the build:
Entries that reference one of these variables may contain glob patterns
(e.g. ${{ PREFIX }}/share/licenses/*/LICENSE) and are always allowed — unlike
plain absolute paths they do not require --allow-absolute-license-paths.
Extra section#
A schema-free area for storing non-conda-specific metadata in standard YAML
form.
Templating with Jinja#
Rattler-Build supports a limited Jinja syntax for expressions and string
interpolation. Variables can be declared in context and referenced later:
Expressions use ${{ ... }}. Jinja control statements such as {% if ... %}
and {% set ... %} are not supported; use recipe selectors and the context
section instead.
See the Jinja reference for the supported functions, filters,
inline conditionals, and access to outer environment variables through the
env object.
Preprocessing selectors#
You can add selectors to any item, and the selector is evaluated in a
preprocessing stage. If a selector evaluates to true, the item is flattened
into the parent element. If a selector evaluates to false, the item is
removed.
Selectors can use if ... then ... else as follows:
source:
- if: not win
then:
- url: http://path/to/unix/source
else:
- url: http://path/to/windows/source
# or the equivalent with two if conditions:
source:
- if: unix
then:
- url: http://path/to/unix/source
- if: win
then:
- url: http://path/to/windows/source
A selector is a valid Python statement that is executed. You can read more about them in the "Selectors in recipes" chapter.
Note that conda-build's Python version selectors (py27, py34, etc.) are
not supported in rattler-build. Use the more general comparison operators
instead.
Because the selector is any valid Python expression, complicated logic is possible:
Lists are automatically "merged" upwards, so it is possible to group multiple items under a single selector:
tests:
- script:
- if: unix
then:
- test -d ${PREFIX}/include/xtensor
- test -f ${PREFIX}/lib/cmake/xtensor/xtensorConfigVersion.cmake
- if: win
then:
- if not exist %LIBRARY_PREFIX%\include\xtensor\xarray.hpp (exit 1)
- if not exist %LIBRARY_PREFIX%\lib\cmake\xtensor\xtensorConfigVersion.cmake (exit 1)
# On unix this is rendered to:
tests:
- script:
- test -d ${PREFIX}/include/xtensor
- test -f ${PREFIX}/lib/cmake/xtensor/xtensorConfigVersion.cmake
Experimental features#
Warning
These are experimental features of Rattler-Build and may change or go away completely.