do not edit — generated by btf.
git.druid.rocksindexdruid520mpdocs/guide/sysroots.btft

docs/guide/sysroots.btft


[table class="topnav"]
[tr]
[td class="logotab"]mp[e]
[td][see name="index"]index[e][e]
[td][see name="guide/index"]guide[e][e]
[td][see name="reference/index"]reference[e][e]
[e]
[e]
 
[h1]sysroots[e]
 
a sysroot is a named, wholly separate install root -- its own prefix, its own install db, its own file manifests, installed into via mp itself rather than by hand-copying files. this page is the practical walkthrough; reference/config.html covers where a sysroot's overlay sits in the config-precedence chain.
 
[h2]defining one[e]
 
drop a file at sysroots/<name>.conf in any configured repo (a plain mp.conf-format file, searched the same priority-ordered way as any port lookup), setting at minimum MP_PREFIX:
 
[code]
# sysroots/arm64-musl.conf
MP_PREFIX="/var/mp-sysroots/arm64-musl"
TARGET_HOST="aarch64-linux-musl"
TARGET_SYSROOT="/var/mp-sysroots/arm64-musl"
[e]
 
any key mplib::config already understands works here -- TARGET_CC/TARGET_AR/TARGET_RANLIB/TARGET_STRIP for a cross toolchain, ARCH/MICROARCH, RUN_TESTS, whatever the target build actually needs.
 
[h2]routing a whole invocation[e]
 
[code]
mp install --sysroot=arm64-musl musl somelib
[e]
 
--sysroot=<name> loads that overlay as the HIGHEST-precedence config for the whole command (winning over /etc/mp.conf, ~/.mp.conf, --config= overlays, and PROFILE= alike) and redirects db/manifest/staging under WD/sysroots/<name> -- fully isolated from the default root's own package tracking. every command works the same way under --sysroot=: mp list --sysroot=arm64-musl, mp remove --sysroot=arm64-musl somelib, and so on.
 
[h2]routing just one package[e]
 
a per-package SYSROOT=<name> section (same "<name>:" mechanism as HOLD/MASK/USE) routes just ONE package -- and everything it recursively depends on -- into a named root within a single, otherwise-default-root invocation:
 
[code]
somepkg:
	SYSROOT=arm64-musl
[e]
 
[code]
mp install somepkg otherpkg   # somepkg -> arm64-musl, otherpkg -> default root
[e]
 
this is what lets a single "mp update" (or any mixed command) maintain packages across several roots at once without needing several separate invocations.
 
[h2]building against a populated sysroot[e]
 
no new mechanism needed: point a package's TARGET_SYSROOT (global, or per-package) at that same sysroot's own MP_PREFIX, and its headers/libs are found automatically -- mpx's runsh appends --sysroot to CFLAGS/LDFLAGS and exports QEMU_LD_PREFIX for qemu-user, same as any other TARGET_SYSROOT use. this is genuinely the same mechanism whether "the sysroot" is a formally named mp sysroot or just some other prefix entirely outside mp's own tracking.
 
[h2]running cross-built tests[e]
 
a check: phase's test binaries, once cross-built, are for the TARGET architecture -- actually running them (RUN_TESTS=yes) needs qemu-user set up on the host to transparently emulate them (Debian/Alpine's qemu-user-binfmt package, or equivalent). mp does not register this itself, the same way a host-provided git/shell is already relied on rather than managed. QEMU_LD_PREFIX (set automatically from TARGET_SYSROOT) is what makes the emulated binary find its real target libraries instead of failing against the host's.
 
[h2]isolation, end to end[e]
 
everything a sysroot needs stays separate from the default root and every OTHER sysroot: db, manifest, staging area (reference/architecture.html's WD layout section), and its own hooks tree (a hook configured for the default root's HOOKS_DIR never fires for a sysroot-scoped install, and vice versa). removing a sysroot you no longer need is just removing its WD/sysroots/<name> directory -- there's no separate deregistration step, since nothing outside that directory ever referenced it.
 
[h2]folding a sysroot into the live root[e]
 
building a whole replacement environment (a new libc, say) in a sysroot and then wanting it to actually BECOME the live root is a different problem from anything above: the normal way to replace an installed package is remove-then-install, and removing something everything else on the system is dynamically linked against (musl, the shell/coreutils provider, the perl mp itself runs on) breaks the very tools that removal needs to finish -- see each of libcs/musl, coreutils/busybox and languages/perl5's own del.sh/pkg.conf comments for real incidents this caused.
 
[code]
mp sysroot install arm64-musl            # every package the sysroot has
mp sysroot install arm64-musl musl gcc   # just these two
[e]
 
this never removes anything first. for each package, it copies every file the sysroot's OWN manifest lists onto the live root, one file at a time, each replaced atomically (a rename() over the old copy, never a delete followed by a recreate) -- then copies that package's db/manifest/linkdeps entries over too. a live-root package the sysroot doesn't have is left completely alone; this overlays a built environment onto the running one, it does not try to make the two identical, and it does not consult HOLD on the live side (naming a sysroot here is itself the explicit, one-time action HOLD exists to guard against happening by accident).
 
[h2]reinstalling one package the same way[e]
 
the same problem shows up for a single package, without needing a whole named sysroot: [code]mp reinstall --inplace <pkg>[e] builds the new copy into an unnamed, throwaway prefix (auto-provisioned, cleaned up afterward), then folds just that one package's files onto the live root the same atomic way -- the old copy is never removed first, so a build failure leaves the live root exactly as it was, and a build success replaces it in one pass instead of a remove-then-install window where mp itself (or whatever else depends on the package being reinstalled) could end up with neither copy.
 
--inplace refuses a package with a slotted dependency (e.g. a dependency pinned to a specific gcc:12-style slot): resolving that dependency's private prefix from inside the ephemeral scratch prefix would point at the wrong place. that combination needs a real named sysroot (with its own full, self-contained dependency closure) instead -- --inplace is for the simple case its real motivating incidents (musl, busybox, perl5) all share: little or no slotted dependency wiring, just a package everything else on the system needs to keep working while it's being replaced.
powered by btf.