Jinja#
rattler-build
comes with a couple of useful Jinja
functions and filters that can be used in the recipe.
Functions#
The compiler function#
The compiler function can be used to put together a compiler that works for the
current platform and the compilation "target_platform
". The syntax looks like:
${{ compiler('c') }}
where 'c'
signifies the programming language that is
used.
This function evaluates to <compiler>_<target_platform> <compiler_version>
.
For example, when compiling on linux
and to linux-64
, this function
evaluates to gcc_linux-64
.
The values can be influenced by the variant_configuration
. The
<lang>_compiler
and <lang>_compiler_version
variables are the keys with
influence. See below for an example:
Usage in a recipe#
With a corresponding variant_configuration:
The variables shown above would select the clang
compiler in version 9.0
.
Note that the final output will still contain the target_platform
, so that the
full compiler will read clang_linux-64 9.0
when compiling with
--target-platform linux-64
.
rattler-build
defines some default compilers for the following languages
(inherited from conda-build
):
c
:gcc
on Linux,clang
onosx
andvs2017
on Windowscxx
:gxx
on Linux,clangxx
onosx
andvs2017
on Windowsfortran
:gfortran
on Linux,gfortran
onosx
andvs2017
on Windowsrust
:rust
The stdlib
function#
The stdlib
function closely mirrors the compiler function. It can be used to
put together a standard library that works for the current platform and the
compilation "target_platform
".
Usage: ${{ stdlib('c') }}
Results in <stdlib>_<target_platform> <stdlib_version>
. And uses the variant
variables <lang>_stdlib
and <lang>_stdlib_version
to influence the output.
Usage in a recipe:#
requirements:
build:
# these are usually paired!
- ${{ compiler('c') }}
- ${{ stdlib('c') }}
With a corresponding variant_configuration:
# these are the values `conda-forge` uses in their pinning file
# found at https://github.com/conda-forge/conda-forge-pinning-feedstock/blob/main/recipe/conda_build_config.yaml
c_stdlib:
- sysroot
c_stdlib_version:
- 2.17
The pin
functions#
A pin is created based on the version input (from a subpackage or a package resolution).
The pin functions take the following three arguments:
lower_bound
(default:"x.x.x.x.x.x"
): The lower bound pin expression to be used. When set toNone
, no lower bound is set.upper_bound
(default:"x"
): The maximum pin to be used. When set toNone
, no upper bound is set.
The lower bound and upper bound can either be a "pin expression" (only x
and
.
are allowed) or a hard-coded version string.
A "pin expression" is applied to the version input to create the lower and upper
bounds. For example, if the version is 3.10.5
with a lower_bound="x.x",
upper_bound="x.x.x"
, the lower bound will be 3.10
and the upper bound will be
3.10.6.0a0
. A pin expression for the upper_bound
will increment the last
selected segment of the version by 1
, and append .0a0
to the end to prevent
any alpha versions from being selected.
If the last segment of the version contains a letter (e.g. 9e
or 1.1.1j
),
then incrementing the version will set that letter to a
, e.g. 9e
will become
10a
, and 1.1.1j
will become 1.1.2a
. In this case, also no 0a0
is
appended to the end.
Sometimes you want to strongly connect your outputs. This can be achieved with the following input:
exact=True
(default:False
): This will pin the version exactly to the version of the output, incl. the build string.
To override the lower or upper bound with a hard-coded value, you can use the following input:
lower_bound
(default:None
): This will override the lower bound with the given value.upper_bound
(default:None
): This will override the upper bound with the given value.
Both lower_bound
and upper_bound
expect a valid version string (e.g.
1.2.3
).
To add an build-string matching expression, you can use the build
argument:
build
(default:None
): This will add a build string matching expression to the pin. The build string matching expression is a string that is used to match the build string with the match spec. For example, if the build string ispy38_0
, the build string matching expression could bepy38*
or to match exactlypy38_0
. Thebuild
andexact
options are mutually exclusive.
The pin_subpackage
function#
${{ pin_subpackage("mypkg", lower_bound="x.x", upper_bound="x.x") }}
creates a pin to another output in the recipe. With an input of3.1.5
, this would create a pin ofmypkg >=3.1,<3.2.0a0
.${{ pin_subpackage("other_output", exact=True) }}
creates a pin to another output in the recipe with an exact version.${{ pin_subpackage("other_output", lower_bound="1.2.3", upper_bound="1.2.4") }}
creates a pin to another output in the recipe with a lower bound of1.2.3
and an upper bound of1.2.4
. This is equivalent to writingother_output >=1.2.3,<1.2.4
.${{ pin_subpackage("foo", build="py38*") }}
creates a matchspec likefoo >=3.1,<3.2.0a0 py38*
.
The pin_compatible
function#
The pin compatible function works exactly as the pin_subpackage
function, but
it pins the package in the run requirements based on the resolved package of the
host
or build
section.
pin_compatible
pins a package in the run requirements based on the resolved package of thehost
orbuild
section.
The cdt
function#
${{ cdt("mypkg") }}
creates a cross-dependency to another output in the recipe.
This function helps add Core Dependency Tree packages as dependencies by converting packages as required according to hard-coded logic. See below for an example of how this function can be used:
# on x86_64 system
cdt('package-name') # outputs: package-name-cos6-x86_64
# on aarch64 system
cdt('package-name') # outputs: package-name-cos6-aarch64
The hash
variable#
${{ hash }}
is the variant hash and is useful in the build string computation.
The version_to_buildstring
function#
${{ python | version_to_buildstring }}
converts a version from the variant to a build string (it removes the.
character and takes only the first two elements of the version).
The env
object#
You can use the env
object to retrieve environment variables and forward them
to your build script. ${{ env.get("MY_ENV_VAR") }}
will return the value of
the environment variable MY_ENV_VAR
or throw an error if it is not set.
To supply a default value when the environment variable is not set, you can use
${{ env.get("MY_ENV_VAR", default="default_value") }}
. In this case, if
MY_ENV_VAR
is not set, the value default_value
will be returned (and no
error is thrown).
You can also check for the existence of an environment variable:
${{ env.exists("MY_ENV_VAR") }}
will returntrue
if the environment variableMY_ENV_VAR
is set andfalse
otherwise.
Filters#
A feature of jinja
is called "filters". Filters are functions that can be
applied to variables in a template expression.
The syntax for a filter is {{ variable | filter_name }}
. A filter can also
take arguments, such as ... | replace('foo', 'bar')
.
The following Jinja filters are available, taken from the upstream minijinja
library:
replace
: replace a string with another string (e.g."{{ 'foo' | replace('oo', 'aa') }}"
will return"faa"
)lower
: convert a string to lowercase (e.g."{{ 'FOO' | lower }}"
will return"foo"
)upper
: convert a string to uppercase (e.g."{{ 'foo' | upper }}"
will return"FOO"
) -int
: convert a string to an integer (e.g."{{ '42' | int }}"
will return42
)abs
: return the absolute value of a number (e.g."{{ -42 | abs }}"
will return42
)bool
: convert a value to a boolean (e.g."{{ 'foo' | bool }}"
will returntrue
)default
: return a default value if the value is falsy (e.g."{{ '' | default('foo') }}"
will return"foo"
)first
: return the first element of a list (e.g."{{ [1, 2, 3] | first }}"
will return1
) -last
: return the last element of a list (e.g."{{ [1, 2, 3] | last }}"
will return3
)length
: return the length of a list (e.g."{{ [1, 2, 3] | length }}"
will return3
)list
: convert a string to a list (e.g."{{ 'foo' | list }}"
will return['f', 'o', 'o']
)join
: join a list with a separator (e.g."{{ [1, 2, 3] | join('.') }}"
will return"1.2.3"
)min
: return the minimum value of a list (e.g."{{ [1, 2, 3] | min }}"
will return1
)max
: return the maximum value of a list (e.g."{{ [1, 2, 3] | max }}"
will return3
)reverse
: reverse a list (e.g."{{ [1, 2, 3] | reverse }}"
will return[3, 2, 1]
)slice
: slice a list (e.g."{{ [1, 2, 3] | slice(1, 2) }}"
will return[2]
)batch
: This filter works pretty much likeslice
just the other way round. It returns a list of lists with the given number of items. If you provide a second parameter this is used to fill up missing items.sort
: sort a list (e.g."{{ [3, 1, 2] | sort }}"
will return[1, 2, 3]
)trim
: remove leading and trailing whitespace from a string (e.g."{{ ' foo ' | trim }}"
will return"foo"
)unique
: remove duplicates from a list (e.g."{{ [1, 2, 1, 3] | unique }}"
will return[1, 2, 3]
)split
: split a string into a list (e.g."{{ '1.2.3' | split('.') | list }}"
will return['1', '2', '3']
). By default, splits on whitespace.
Removed filters
The following filters are removed from the builtins:
attr
indent
select
selectattr
dictsort
reject
rejectattr
round
map
title
capitalize
urlencode
escape
pprint
safe
items
float
tojson
Extra filters for recipes#
The version_to_buildstring
filter#
${{ python | version_to_buildstring }}
converts a version from the variant to a build string (it removes the.
character and takes only the first two elements of the version).
For example the following:
Would evaluate to a abc123_cuda112
(assuming the hash was abc123
).
Various remarks#
Inline conditionals with Jinja#
The new recipe format allows for inline conditionals with Jinja. If they are
falsey, and no else
branch exists, they will render to an empty string (which
is, for example in a list or dictionary, equivalent to a YAML null
).
When a recipe is rendered, all values that are null
must be filtered from the
resulting YAML.
If cuda
is not equal to yes, the first item of the host requirements will be
empty (null) and thus filtered from the final list.
This must also work for dictionary values. For example: