Context bundles#
A “context bundle” is a directory containing a context (an rxt file), and a package repository. All packages in the context are stored in the repository, making the bundle relocatable and standalone. You can copy a bundle onto a server for example, or into a container, and there are no external references to shared package repositories. This is in contrast to a typical context, which contains absolute references to one or more package repositories that are typically on shared disk storage.
To create a bundle via command line:
$ rez-env foo -o foo.rxt
$ rez-bundle foo.rxt ./mybundle
$ # example of running a command from the bundled context
$ rez-env -i ./mybundle/context.rxt -- foo-tool
To create a bundle via API:
from rez.bundle_context import bundle_context
from rez.resolved_context import ResolvedContext
c = ResolvedContext(["python-3+", "foo-1.2+<2"])
bundle_context(c, "./mybundle")
Structure#
A bundle directory looks like this:
.../mybundle/
./context.rxt
./packages/
<standard package repo structure>
Package references in the rxt file are relative (unlike in a standard context, where they’re absolute), and this makes the bundle relocatable.
Patching Libraries#
Depending on how compiled libraries and executables within a rez package were
built, it’s possible that the dynamic linker will attempt to resolve them to
libraries found outside of the bundle. For example, this is possible in linux
if an elf (.so
)
contains an absolute search-path in its rpath/runpath header to a library in another package.
Rez bundling performs a library patching step that applies various fixes to
solve this issue (use --no-lib-patch
if you want to skip this step). This step
is platform-specific and is covered in the following sections.
Note
Note that in all cases, references to libraries outside of the bundle will remain intact, if there is no equivalent path found within the bundle (for example, if the reference is to a system library not provided by a rez package).
Linux#
On linux, rpath/runpath headers are altered if paths are found that map to a
subdirectory within another package in the bundle. To illustrate what happens,
consider the following example, where packages from /sw/packages
have been
bundled into the local directory ./mybundle
:
$ # a lib in an original non-bundled package
$ patchelf --print-rpath /sw/packages/foo/1.0.0/bin/foo
/sw/packages/bah/2.1.1/lib
$
$ # the same lib in our bundle. We assume that package 'bah' is in the bundle
$ # also, since foo links to one of its libs
$ patchelf --print-rpath ./mybundle/packages/foo/1.0.0/bin/foo
$ORIGIN/../../../bah/2.1.1/lib
Remapped rpaths make use of the special $ORIGIN
variable, which refers to
the directory containing the current file.