Reference
Recipe formats#
The recipes are found in the a separate repository. The repository can be
specified via the -c
option and defaults to alidist.
The recipes themselves are called <package>.sh
where <package>
is the name
of the package whose build recipe is described. Please note that all recipe
filenames are lowercase: e.g. the recipe for ROOT
will be in root.sh
.
The recipe itself is made up of two parts: an header, and the actual build
script, separated by three dashes (---
) standalone.
The header is in YAML format and contains metadata about the package, like its name, version and where to find the sources.
The build script is a standard build script which is invoked by the tool to perform the build itself. A few environment variable can be expected to be defined when the script is invoked.
An example recipe for zlib
is the following:
package: zlib
version: v1.2.8
source: https://github.com/star-externals/zlib
tag: v1.2.8
---
#!/bin/bash -ex
./configure --prefix=$INSTALLROOT
make ${JOBS+-j $JOBS}
make install
The header#
The following entries are mandatory in the header:
package
: the name of the package-
version
: a mnemonic for the version which will be used in the name of the package. Notice you can actually use some special formatting substitutions which will be replaced with the associated value on build. Valid substitutions are:%(branch_basename)s
: the name of the current alidist branch, without the leadingrefs/heads/
.%(branch_stream)s
: in case the alidist branch ends in-patches
, the name of branch without-patches
. If the branch does not end in-patches
, thetag
field of the recipe is used.%(commit_hash)s
: if thetag
field is a git tag, then the tag name. If it is a branch or raw git commit hash instead, then the raw git commit hash pointing to theHEAD
of that branch, or said commit hash.%(short_hash)s
: like%(commit_hash)s
, but cut off after 10 characters.%(tag)s
: thetag
key specified in the recipe.%(tag_basename)s
if thetag
resembles a path, e.g.refs/tags/a/b/c
, returns the last part of the path,c
in this case.%(defaults_upper)s
: if building withrelease
defaults, this is the empty string; else, this is an underscore and then the name defaults, uppercased, with-
replaced by_
. For example, if building witho2-dataflow
defaults,%(default_upper)s
would be_O2_DATAFLOW
.%(year)s
%(month)s
%(day)s
%(hour)s
Month, day and hour are zero-padded to two digits.
The following entries are optional in the header:
source
: URL of a Git repository from which the source is downloaded. It's good practice to make sure that they are already patched, so that you can easily point to the actual sources used by the software.write_repo
: in case the repository URL to be used for developing is different from thesource
, set this key. It is used byaliBuild init
, which will initialise your local repository with theupstream
remote pointing at this URL instead of the one insource
.tag
: git reference in the above mentioned repository which points to the software to be built. This can be a tag name, a branch name or a commit hash.-
env
: dictionary whose key-value pairs are environment variables to be set after the recipe is built. The values are interpreted as the contents of a double-quoted shell string, so you can reference other environment variables as$VARIABLE
, which will be substituted each time another recipe is built. For example:These variables will not be available in the recipe itself, as they are intended to be used to point to build products of the current recipe. If you need to set an environment variable for use in the recipe, use
export VARIABLE=value
in the recipe body. -prepend_path
: dictionary whose key-value pairs are an environment variable name and a path to be prepended to it, as it happens inLD_LIBRARY_PATH
. This happens only after the package declaring theprepend_path
in question is built, so it is not available in the same recipe (just like variables declared usingenv
). You can append multiple paths to a single variable by specifying a list too, e.g.:prepend_path: "PATH": "$FOO_ROOT/binexec/foobar" "LD_LIBRARY_PATH": [ "$FOO_ROOT/sub/lib", "$FOO_ROOT/sub/lib64" ]
will result in prepending
$FOO_ROOT/binexec/foobar
to$PATH
, and both$FOO_ROOT/sub/lib
andlib64
toLD_LIBRARY_PATH
. -append_path
: same asprepend_path
but paths are appended rather than prepended. Likeappend_path
andenv
, this does not affect the environment of the current recipe. -requires
: a list of run-time dependencies for the package, e.g.:The specified dependencies will be built before building the given package. You can specify platform-specific dependencies by appending
:<regexp>
to the dependency name. Such a regular expression will be matched against the architecture provided via--architecture
, and if it does not match, the requirement will not be included. For instance:will make sure that
IgProf
is only built on platforms whose name does not begin withosx
. -build_requires
: a list of build-time dependencies for the package. Likerequires
, these packages will be built before the current package is built.Packages in this list are marked specially in the dependency graph produced by
aliDeps
. Other tools treat these packages differently fromrequires
: for instance, RPMs produced for a package won't depend on itsbuild_requires
, andalibuild-generate-module
won't pull in build requirements' modulefiles. -force_rebuild
: set it totrue
to force re-running the build recipe every time you invoke alibuild on it. -prefer_system_check
: a script which is used to determine whether or not the system equivalent of the package can be used. See alsoprefer_system
. If the--no-system
option is specified, this key is not checked. The shell exit code is used to steer the build: if the check returns 0, the system package is used and the recipe is not run. If it returns non-zero, our own version of the package is built through the recipe. -prefer_system
: a regular expression for architectures which should use theprefer_system_check
by default to determine if the system version of the tool can be used. When the rule matches, the result ofprefer_system_check
determines whether to build the recipe. When the rule does not match, the check is skipped and the recipe is run. Using the switch--always-prefer-system
runs the check always (even when the regular expression for the architecture does not match). -relocate_paths
: a list of toplevel paths scanned recursively to perform relocation of executables and dynamic libraries on macOS only. If not specified, defaults tobin
,lib
andlib64
.
The body#
This is the build script executed to effectively build and install your software. Being a shell script you can be as flexible as you want in its definition.
Some environment variables are made available to the script.
INSTALLROOT
: the installation prefix. This is commonly passed in the form./configure --prefix=$INSTALLROOT
orcmake -DCMAKE_INSTALL_PREFIX=$INSTALLROOT
. The build tool will create an archive based on the sole content of this directory.PKGNAME
: name of the current package.PKGVERSION
: package version, as defined in the recipe'sversion:
field.PKGREVISION
: the "build iteration", automatically incremented by the build script.PKGHASH
: SHA1 checksum of the recipe.ARCHITECTURE
: an arbitrary string summarizing the current build platform. This is passed using the--architecture
(or-a
) argument to the build script.SOURCE0
: URL of the source code. Note: ifsource:
is not provided in the recipe, the variable will be empty.GIT_TAG
: the Git reference to checkout.JOBS
: number of parallel jobs to use during compilation. This is passed on the command line to the build script, and should be used in a context likemake -j$JOBS
.BUILDDIR
: the working directory. This is, e.g., the "build directory" for CMake, i.e. the directory from where you invokecmake
. You should not write files outside this directory.BUILDROOT
: it containsBUILDDIR
and the log file for the build.SOURCEDIR
: where the sources are cloned.REQUIRES
: space-separated list of all dependencies, both runtime and build only.BUILD_REQUIRES
: space-separated list of all build dependencies, not needed at runtime.RUNTIME_REQUIRES
: space-separated list of all runtime dependencies only.
For each dependency already built, the corresponding environment file is loaded.
This will include, apart from custom variables and the usual PATH
and library
paths, the following specific variables (<PACKAGE>
is the package name,
uppercased):
<PACKAGE>_ROOT
: package installation directory.<PACKAGE>_VERSION
: package version.<PACKAGE>_REVISION
: package build number.<PACKAGE>_HASH
: hash of the recipe used to build the package.
Defaults#
aliBuild uses a special file, called defaults-release.sh
which will be
included as a build requires of any recipe. This is in general handy to
specify common options like CXXFLAGS
or dependencies. It's up to the
recipe handle correctly the presence of these options.
It is also possible to specify on the command line a different set of
defaults, for example if you want to include code coverage. This is
done via the --defaults <default-name>
option which will change the
defaults included to be defaults-<default-name>.sh
.
An extra variable %(defaults_upper)s
can be used to form the version
string accordingly. For example you could trigger a debug build by
adding --defaults debug
, which will pick up defaults-debug.sh
, and
then have:
in one of your recipes, which will expand to:
If you want to add your own default, you should at least provide:
CXXFLAGS
: theCXXFLAGS
to useCFLAGS
: theCFLAGS
to useLDFLAGS
: theLDFLAGS
to useCMAKE_BUILD_TYPE
: the build type which needs to be used by cmake projects
Besides specifying extra global variables, starting from aliBuild
1.4.0, it's also possible to use defaults to override metadata of other
packages . This is done by specifying the overrides
dictionary in the
metadata of your defaults file. For example to switch between ROOT6 and
ROOT5 you should do something like:
this will replace the version
and tag
metadata of root.sh
with the
one specified in the override. Notice that is also possible to override
completely a recipe, picking it up from a given commit hash, branch or
tag in alidist. You can do so by adding such git reference after the name
of the external to override. For example:
will pick root.sh
as found in the commit abcedf123456
.
For a more complete example see defaults-o2.sh.
You can limit which defaults can be applied to a given package by using the
valid_defaults
key.
Architecture defaults#
Architecture defaults are similar to normal defaults but they are always sourced, if available in alidist, and should never be provided on the command line.
Their filename is always:
defaults-<arch>.sh
where <arch>
is the current architecture. They have precedence over normal
defaults.
Relocation#
aliBuild supports relocating binary packages so that the scratch space used for
builds (e.g. /build
) and the actual installation folder (i.e.
/cvmfs/alice.cern.ch
) do not need to be the same. By design this is done
automatically, and the user should not have to care about it. The procedure
takes care of relocating scripts and, on macOS, to embed the correct paths for
the dynamic libraries dependencies, so that SIP does not need to be disabled.
The internal procedure is roughly as follows:
- The build happens in
BUILD/<package>-latest/<package>
and installs byproducts inINSTALLROOT=<work-dir>/INSTALLROOT/<package-hash>/<architecture>/<package>/<version>-<revisions>
. This way we know that every file which contains<package-hash>
needs to be relocated. - Once the build is completed, aliBuild looks for the above mentioned
<package-hash>
and generates a script in the$INSTALLROOT/relocate-me.sh
which can be used to relocate the binary installation, once it has been unpacked. - The path under
<work-dir>/INSTALLROOT/<package-hash>
is tarred up in a binary tarball.
When a tarball is installed, either because it was downloaded by aliBuild or by some other script (e.g. the CVMFS publisher, the following happens:
- The tarball is expanded.
- The relocation script
relocate-me.sh
is executed with something similar to:
which will take the path up to the <package-hash>
and re-map it to the newly
specified WORK_DIR
.
Notice that the special variable @@PKGREVISION@$PKGHASH@@
can be used to have
the actual revision of the package in the relocated file.
Build environment#
Before each package is built, aliBuild will populate the environment with build
related information. For a complete list of those see
the body section. After the build is done the user has access to
the environment of the build by sourcing the
<work-dir>/<architecture>/<package>/<version>/etc/profile.d/init.sh
file.
For example:
Notice that for development packages, we also generate a .envrc
file in
<work-dir>/BUILD/<package>-<version>/<package>/.envrc
which can be used to
load the build environment via direnv, e.g. for easy
IDE integration.
Runtime environment#
Runtime environment is usually provided via environment modules.
While the build environment is automatically generated, it is responsibility of
the recipe to create a module file in $INSTALLROOT/etc/modulefiles/$PKGNAME
.
For example:
# ModuleFile
mkdir -p etc/modulefiles
cat > etc/modulefiles/$PKGNAME <<EoF
#%Module1.0
proc ModulesHelp { } {
global version
puts stderr "ALICE Modulefile for $PKGNAME $PKGVERSION-@@PKGREVISION@$PKGHASH@@"
}
set version $PKGVERSION-@@PKGREVISION@$PKGHASH@@
module-whatis "ALICE Modulefile for $PKGNAME $PKGVERSION-@@PKGREVISION@$PKGHASH@@"
# Dependencies
module load BASE/1.0 \\
${BOOST_REVISION:+boost/$BOOST_VERSION-$BOOST_REVISION} \\
${FAIRLOGGER_REVISION:+FairLogger/$FAIRLOGGER_VERSION-$FAIRLOGGER_REVISION} \\
${ZEROMQ_REVISION:+ZeroMQ/$ZEROMQ_VERSION-$ZEROMQ_REVISION} \\
${ASIOFI_REVISION:+asiofi/$ASIOFI_VERSION-$ASIOFI_REVISION} \\
${DDS_REVISION:+DDS/$DDS_VERSION-$DDS_REVISION}
# Our environment
set FAIRMQ_ROOT \$::env(BASEDIR)/$PKGNAME/\$version
prepend-path PATH \$FAIRMQ_ROOT/bin
prepend-path LD_LIBRARY_PATH \$FAIRMQ_ROOT/lib
EoF
MODULEDIR="$INSTALLROOT/etc/modulefiles"
mkdir -p $MODULEDIR && rsync -a --delete etc/modulefiles/ $MODULEDIR
Please keep in mind the following recommendation when writing the modulefile:
- Do not use runtime environment variables which are usually not set by a given
tool. For example avoid exposing
<package>_ROOT
. This is because if we build in a mode where system dependencies are used, we cannot rely on their presence. - Use
<package>_REVISION
to guard inclusion of extra dependencies. This will make sure that only dependencies which were actually built viaaliBuild
will be included in the modulefile.
It's also now possible to generate automatically the initial part of the
modulefile, up to the # Our environment
line, by using the
alibuild-recipe-tools
helper scripts. In order to do this you need to add
alibuild-recipe-tools
as a build_requires
of your package and substitute the
module creation with:
#ModuleFile
mkdir -p etc/modulefiles
alibuild-generate-module > etc/modulefiles/$PKGNAME
mkdir -p $INSTALLROOT/etc/modulefiles && rsync -a --delete etc/modulefiles/ $INSTALLROOT/etc/modulefiles
One can also make sure that PATH
and LD_LIBRARY_PATH
are properly amended by
passing the option --bin
and --lib
(respectively). Or you can simply append
extra information via: