| git.druid.rocks | index | druid520 | mp | docs/ | reference/ | mp-conf-example.btft |
docs/reference/mp-conf-example.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]mp.conf.example[e]
[quote class="note"]
generated from mp.conf.example -- do not edit this page directly, edit that file and regenerate ("mk . d" / "sh mk/d.sh") instead. see [see name="reference/config"]reference/config[e] for the narrative tour this page doesn't replace.
[e]
system-wide mp config, read from /etc/mp.conf, then layered with ~/.mp.conf on top if present. unknown keys are ignored, so this file (and any frontend reading it) can grow new keys without needing to change mp itself. a handful of location/path settings (WD, PORTS_DIR, REPO_<name>, CUSTOM_PORTS_DIR, MP_BACKEND, MP_PREFIX, SHELL, HOOKS_DIR) are also overridable by a same-named env var -- everything else documented below (GLOBAL_DEPS, TARGET_*/TAG_*, ACCEPT_KEYWORDS, ARCH/ MICROARCH, RUN_TESTS, HOLD*, MASK, USE, DEPS*, PROFILE, ...) is read only from this file/overlay chain, with no env var equivalent.
[h2]working dir[e]
working dir: staged builds, install db, file manifests.
[code]
WD=/usr/mp
[e]
root all configured ports repos live under (see REPO_<name>= below). defaults to $WD/repos (so a completely unconfigured system keeps everything mp manages under one root, WD, instead of spreading across WD and a separately-rooted /usr/ports) -- set explicitly here mainly to make that default visible, not because it needs to differ from it.
[code]
PORTS_DIR=/usr/mp/repos
[e]
[h2]repos[e]
repos: one or more independently configured, git-backed ports trees, searched IN PRIORITY ORDER for every port/class/profile/sysroot-overlay lookup -- first match wins, exactly like CUSTOM_PORTS below already won over a single ports tree. REPO_<name>=<git-url> declares one (<name> is yours to pick: letters/digits/underscore); REPO_<name>_BRANCH=<branch> (optional, defaults to the remote's own default branch) and REPO_<name>_PRIORITY=<n> (optional, default 50 -- LOWER wins, same "lower is more preferred" convention as a port's own pkg_pref, ties broken by name) are its optional per-repo metadata:
[code]
REPO_main=git://git.druid.rocks/druid520/ports.git
REPO_main_PRIORITY=10
[e]
[code]
REPO_extra=git://example.com/my-extra-ports.git
REPO_extra_BRANCH=stable
REPO_extra_PRIORITY=50
[e]
a name/category/port that exists in more than one repo resolves to whichever repo has the lower priority number -- REPO_main above always wins a collision with REPO_extra. declare zero REPO_* keys at all and mp falls back to a single repo (named "main", at the URL above) so an unconfigured system still bootstraps with no config file. a lone configured repo (the common case) clones directly to PORTS_DIR, exactly as a single PORTS_REPO always did; a SECOND (or further) repo clones to its own PORTS_DIR/repos/<name> instead, so nothing under PORTS_DIR itself is ever a merge of two repos' files on disk.
"mp sync" pulls every configured repo (see "sync / update" below); "mp" clones whatever repo directory doesn't exist yet, the first time any command needs it.
local overrides, checked BEFORE every configured repo (highest priority of all) for every port lookup (same category/name layout as a repo's own ports/ subdir). lets you keep hand-edited ports here without them being touched by "mp sync"/"mp update", which only ever pull the configured REPO_* repos.
[code]
CUSTOM_PORTS_DIR=/usr/local/ports
[e]
the compiled backend binary.
[code]
MP_BACKEND=/usr/local/libexec/mp/mpx
[e]
install prefix that add.sh/del.sh scripts target, and that manifests are tracked relative to.
[code]
MP_PREFIX=/usr/local
[e]
shell used to run add.sh/del.sh and user hooks.
[code]
SHELL=/bin/sh
[e]
append these deps to every package's dependency list (useful to force a tag or tool on without editing every port). if unset, mp defaults to "%libc %shell %coreutils", so ports need not declare them themselves. a port providing any of these tags is a bootstrap provider and is exempt from the whole line, so libc/shell/coreutils never depend on each other. git/curl/wget/patch are deliberately NOT here, for two different reasons: git specifically cannot be, since it has a real (non-optional) dependency of its own (zlib) that is not itself a bootstrap provider -- forcing %git onto every package would force it onto zlib too, and zlib's own fetch needing git right back would be a genuine, unbreakable cycle (git -> zlib -> %git -> git), not a bootstrap-ordering quirk like libc/shell/coreutils avoid via their own bare pkg_deps. git is still a normal, fully tracked port (pkg_tags="git", HOLD/MASK-able, shows in "mp list") -- every port's own fetch just still relies on a host-provided git the same way it always has, same as shell/coreutils relying on the host to run anything before mp's own bootstrap begins. curl/wget/patch have the simpler reason: only some ports need them (curl/wget for a pkg_fetch="tar:..." source, patch for a patches/ dir), so those are declared per-port instead of forced onto every package.
[code]
GLOBAL_DEPS="%libc %shell %coreutils"
[e]
global (unindented) ENV=: exports the given NAME=VAL pairs as env vars to every port's add.sh/del.sh, the same way a per-package section's own
[code]
ENV= does for just that one port (see that section further down) --
[e]
useful for a standing, system-wide build policy (a target CFLAGS/ LDFLAGS convention, say) you don't want retyped by hand before every invocation. a per-package section's own key of the same name still wins over this (global entries are applied first, so a later, more specific one simply overrides it). /etc/mpx.env (see src/runsh.c's own comment) is the lower-level, always-sourced-first counterpart to this -- arbitrary POSIX sh, no mp.conf parsing involved at all, and no per- package awareness -- prefer it for something that truly applies to every single build unconditionally; prefer this ENV= when you want it to compose with PROFILE=/OVERLAYS=/per-package precedence like any other mp.conf key.
[code]
ENV=CFLAGS=-O2 LDFLAGS=-s
[e]
[h2]config overlays[e]
config overlays. files listed here are parsed on top of this one and may chain their own OVERLAYS; later files (and later entries) win. --config= on the command line is the highest-precedence overlay of all. this is mp.conf's own "pull in other files" mechanism -- mpx.conf.example's sibling IMPORT= key exists because mpx.conf is a separate, simpler C-side parser with no equivalent of this already; there's no reason for a second, parallel "IMPORT=" here too, since OVERLAYS= already covers everything IMPORT= does (splicing another file's keys in) and more (chains through a whole list, cycle/diamond-safe, at a well-defined precedence relative to --config= and PROFILE=).
[code]
OVERLAYS=/etc/mp-overrides.conf /usr/local/mp.conf
[e]
TARGET_<tag>=<port> (also accepted: TAG_<tag>) pins a %tag dependency to a specific port, bypassing pkg_pref entirely. useful to force a choice among several providers:
[code]
TARGET_cc=gcc
[e]
or to tell mp a tag is already satisfied by the base system and it should install nothing at all for it (see ports/meta/null). libc, the shell, and the basic core utilities are all part of the base system on most hosts, so pin all three to nothing by default:
[code]
TARGET_libc=meta/null
TARGET_shell=meta/null
TARGET_coreutils=meta/null
[e]
a pin can also carry a version constraint, same "name=version" (exact) / "name>=version" grammar as any dep token or CLI "mp install name=X" -- useful when a %tag has one port that can build several versions (its fetch/build phase keying off its own pkg_ver):
[code]
TARGET_ssl=openssl=1.1.1
[e]
already installed at a version that doesn't satisfy the pin fails loudly rather than silently keeping the mismatched version -- remove/ reinstall it at a satisfying version first. for a %tag with SEPARATE port directories per version instead (the gcc-12/gcc-13 static-slot pattern, each declaring the same pkg_name with a different pkg_slot), pin by slot instead of version: TARGET_ssl=openssl:1.1.1.
[h2]per-package sections[e]
per-package sections. a "<name>:" header scopes the keys that follow to that one port's build, overriding the global defaults for just that port. indentation matters: a key on an indented line belongs to the section; an unindented key=value line returns to global scope (and closes the section). so a section runs from its "<name>:" header to the next "<name>:" header or the next unindented key=value line. # inline comments are fine.
[code]
examplepkg:
TARGET_libc=musl # only examplepkg resolves %libc to musl
CC=clang # exported as env to examplepkg add.sh/del.sh
CFLAGS=-O2
ENV=FOO=1 BAR=2 # shorthand: export several NAME=VAL vars
# unindented -> back to global; anything below is global again
[e]
TARGET_*/TAG_* keys are tag pins used only while resolving that port's deps; every other key is exported as an environment variable to that port's add.sh and del.sh when mp installs/removes it. sections can be in /etc/mp.conf, ~/.mp.conf, or any overlay (layered, later wins). a per-package section (TARGET_*/DEPS* included) is looked up under the port's full canon first, falling back to its bare name -- the same fallback the SLOT section below documents for USE=: a pkg_slot_use- composed canon (e.g. "combodep:foo") doesn't exist yet at the moment you'd write a section for it, so the bare name is the only key you could plausibly use, and it applies to every slot of that name alike unless a specific "name:slot" section overrides it for just one.
this is also how to pass extra flags into a port's own build system without editing the port: the autotools/configure-make/bootstrap-make classes' ./configure line, meson's "meson setup" line, and cmake's "cmake" line each end with $CONFIGURE_FLAGS / $MESON_FLAGS / $CMAKE_FLAGS respectively (empty unless set), so setting one of these in a per-package section reaches straight into that one build:
[code]
somepkg:
CONFIGURE_FLAGS="--enable-foo --without-bar"
othermesonpkg:
MESON_FLAGS="-Dfeature=enabled"
[e]
a port's own hand-written build: phase can reference the same env vars the same way, and meson-class ports work identically whether meson or muon (its lighter, api-compatible %meson alternative) actually wins the %meson pick -- muon accepts the same "meson setup ..." invocation.
advanced per-package features.
dep modification inside a "<name>:" section:
[code]
DEPS='p1 p2' replaces pkg_deps entirely
DEPS+='p3' appends extra deps
DEPS-='p4' drops a dep (by name or %tag)
[e]
global GLOBAL_DEPS= is appended to every package (see above).
[code]
examplepkg:
DEPS-=kbd # drop kbd from examplepkg
DEPS+=libxcb # add libxcb
[e]
[h2]useflags[e]
useflags. a port declares optional features in its pkg_use, e.g.
[code]
pkg_use="ssl:%openssl x11:libxcb,libx11 examples"
[e]
(each token is 'flag:dep1,dep2'; a bare flag is a boolean feature bit). enabling a flag adds its deps and exports USE= and USE_<flag>=1 to the port's add.sh/del.sh. enable flags globally via USE=, or per-package inside a "<name>:" section:
[code]
USE="ssl x11"
examplepkg:
USE=ssl # only examplepkg gets the ssl feature deps
[e]
"mp use examplepkg" lists a port's declared flags and current state without editing config by hand; "mp use examplepkg +ssl -x11" toggles flags and persists the result (see "mp-managed config" below).
hold (inside a "<name>:" section): block changes to a package.
[code]
HOLD=yes # no install/remove/reinstall/update
HOLD_VERSION=1.2 # only allow exactly version 1.2
meta/world:
HOLD=yes
[e]
"mp hold examplepkg" / "mp unhold examplepkg" toggle plain HOLD=yes without hand-editing config (HOLD_VERSION stays config-only -- pinning an exact version is deliberate enough to just write directly).
conflict priority (inside a "<name>:" section): decides automatically who wins when two installed packages' files genuinely collide, instead of the plain hard failure ("X conflicts with Y on installed files, use --force to override") every install otherwise gets. a plain integer, HIGHER wins:
[code]
busybox:
CONFLICT_PRIORITY=100
gnu-patch:
CONFLICT_PRIORITY=10
[e]
(busybox's own "patch" applet would now silently win over gnu-patch's dedicated binary if both ever collide on /usr/bin/patch -- gnu-patch's own manifest is updated to stop claiming that one path, so its own tracking doesn't drift from reality; nothing else about either package changes.) checked at TWO points: a fast pre-flight pass (before a conflicting package's own build even starts, using its LAST-KNOWN manifest -- catches an already-known, priority-decided rejection without wasting a rebuild) and the real, authoritative check once a fresh install's true new file set is known. only meaningful once BOTH sides of a real conflict are identified -- it's not a general ordering/preference mechanism, just the tiebreak for when two packages' files genuinely land on the same path. leave both sides unset (the default) to keep today's behavior exactly: a real conflict always hard-fails at a non-interactive terminal (or with --yes), and prompts once, interactively, at a real one ("X wants to overwrite N file(s) Y currently owns -- let X win? [y/N]") -- a plain 'y' there only ever affects that one install, never persisted here automatically.
[h2]hooks[e]
hooks. global keys run for every package; the same keys inside a "<name>:" section run only for that package, and are run with the package's per-pkg env vars set. every phase gets a pre_/post_ pair -- pre_fetch/post_fetch, pre_patch/post_patch, pre_build/post_build, pre_check/post_check (RUN_TESTS=yes only), pre_install/post_install (once per whole install, not per phase), pre_remove/post_remove, and pre_sync/post_sync (mp sync/update, no $MP_PKG -- there's no package). on_fail (best-effort -- its own failure never masks the real error) runs when an install is rejected for conflicting with another installed package's files, a notification/monitoring integration point for a failure mode that otherwise has no hook of its own:
[code]
hook_pre_install='logger installing $MP_PKG'
hook_post_remove='cleanup-cache'
[e]
(a per-pkg example:)
[code]
examplepkg:
hook_post_install='mp providers cc'
hook_post_build='logger built examplepkg'
[e]
$MP_PKG (and the "<name>:" section a hook/per-pkg env var is read from) is the package's full, possibly slot-qualified canon, e.g. "curl:ssl" -- falling back to the bare name ("curl") if there's no section for that exact slot. write a "<name>:" section under the bare name for something that should apply to every slot of that name alike (the common case, and what "examplepkg:" above does); write it under the full "name:slot" canon instead for a hook/override that should fire for just one specific coexisting slot. one repo split further via git submodules (distinct from the REPO_<name>=/REPO_extra= multi-repo mechanism above, which mp already clones/pulls on its own) needs nothing sync-specific built in -- just, for a single-repo setup where that repo clones directly to PORTS_DIR:
[code]
hook_post_sync='git -C $PORTS_DIR submodule update --init --recursive'
[e]
(a repo cloned to its own PORTS_DIR/repos/<name>, once a second repo is configured, takes the same hook pointed at that path instead.)
custom hook points: a phase script isn't limited to the fixed pre_/ post_<phase> set above -- $MP_HOOK (exported to every phase script) is the path to a small helper that fires any event name the port author picks, e.g. from a build phase:
[code]
$MP_HOOK post-configure
[e]
and it runs through the exact same machinery as any built-in phase: hook_post-configure= in mp.conf, HOOKS_DIR/post-configure/*, all of it.
hooks.conf: HOOKS_DIR/<phase>/*'s several-independent-files group (both built-in phases and a custom $MP_HOOK-triggered one) can optionally take a sibling HOOKS_DIR/<phase>/hooks.conf, same "<file>:" section grammar as this file itself and as a port's own patches/patches.conf -- see hooks.conf.example (this file's sibling) for the full IF_USE/AFTER grammar; a quick taste:
[code]
HOOKS_DIR/post_install/hooks.conf:
20-notify:
AFTER=10-logger # ordering, not just filename sort
30-extra-check:
IF_USE=debug # only runs if USE=debug is enabled
[e]
absent entirely, every executable file in the directory just runs in filename order, exactly as without this section at all.
HOOKS_<phase>=: an OPTIONAL manual override on top of hooks.conf's own IF_USE-computed set, same +/- delta convention "mp use" uses for USE= (global, or per-package -- same "<name>:" fallback as hook_<phase> above). a bare list is the complete, explicit set of filenames to run, regardless of IF_USE; a +file/-file delta is applied atop the IF_USE-computed baseline instead:
[code]
HOOKS_post_install=-20-notify # disable one hook file by name,
# without deleting it or touching
# hooks.conf
examplepkg:
HOOKS_post_install=+30-extra-check # force it on for this pkg
# despite its own IF_USE
[e]
no dedicated command persists this -- hand-edit mp.conf directly.
the format is exactly ~/example.conf's (note JOBS=1 below is unindented, so it is global even though it follows the examplepkg2: section):
[code]
TARGET_libc=meta/null # global
examplepkg:
TARGET_libc=musl # this pkg uses musl but pkg2 doesn't
examplepkg2:
TARGET_libc=glibc
JOBS=2
JOBS=1
[e]
sync / update.
"mp sync" pulls every configured repo (git pull on each REPO_<name>'s own directory). "mp update" syncs first, then rebuilds the requested already-installed packages. update rebuilds in dependency order: for every package being updated it rebuilds that package's dependencies first (regardless of category), one package at a time. rebuilds are serial because each reinstall learns what files it owns by snapshotting MP_PREFIX before and after its build; two concurrent builds would write into each other's snapshots, making packages claim foreign files and report false "conflicts with X on installed files". the install db write itself is flock-guarded (WD/db.lock) and merges concurrent changes, so overlapping mp invocations stay consistent.
[h2]build vs runtime deps[e]
build vs runtime deps: pkg_bdepend (build-only, e.g. cmake/autoconf) vs pkg_rdepend (needed at runtime too); pkg_deps stays as legacy shorthand for "both", so simple ports never need the split. a pkg_use flag's deps default to runtime; "flag:b:dep1,dep2" marks them build-only. "mp prune" considers dropping bdepend-only packages nothing needs at runtime.
[h2]soft deps[e]
soft deps: pkg_deps_soft="foo" participates in resolution/ordering but never blocks -- if foo has no port, or would cycle, it is silently skipped instead of failing the whole install. generalizes what used to be a hardcoded exemption for the libc/shell/coreutils bootstrap triangle.
[h2]masking[e]
masking: MASK=yes inside a "<name>:" section hides that port from auto-pick and blocks an explicit install without deleting it.
[code]
examplepkg:
MASK=yes
[e]
"mp install --unmask examplepkg" overrides a mask (and a keyword block, below) for one invocation. "mp mask examplepkg" / "mp unmask examplepkg" instead toggle a PERSISTENT mask -- the two are independent: a persistent mask still requires --unmask on any install meant to override it for that one run, and --unmask never touches the persisted setting itself.
[h2]mp-managed config[e]
mp-managed config: "mp hold"/"mp unhold", "mp mask"/"mp unmask", and "mp use +flag/-flag" all persist by writing WD/pkgconf.conf -- a file mp itself fully owns (never hand-edit it; anything in it is regenerated wholesale on every sugar-command run). it loads as the highest-precedence overlay of all, so it's never silently shadowed by /etc/mp.conf, ~/.mp.conf, --config= overlays, or PROFILE=. a --sysroot=<name> invocation (or a per-package SYSROOT=, below) gets its own independent pkgconf.conf, exactly like its own db.
[h2]keywords[e]
keywords: pkg_keywords="amd64 arm64 ~riscv" per port (bare = stable, ~arch = testing, absent = unsupported there). ACCEPT_KEYWORDS gates this; unset (the default) turns the whole check off, so ports that declare no pkg_keywords (nearly all of them) are never affected.
[code]
ACCEPT_KEYWORDS=amd64
[e]
[h2]arch / microarch[e]
arch / microarch: exported to add.sh/build phases as MP_ARCH/MP_MICROARCH and MICROARCH is appended to CFLAGS as -march=MICROARCH.
[code]
ARCH=amd64
MICROARCH=x86-64-v3
[e]
[h2]profiles[e]
profiles: PROFILE=<name> pulls in profiles/<name>/mp.conf -- searched across every configured repo in priority order, same as any port/class lookup -- as the LOWEST-precedence overlay (only fills in keys nothing else set) -- a shippable base config you can still override locally. a profile can itself set PROFILE=<other> to chain to a further base profile (e.g. a "server" profile filling in from "minimal" below it) -- a cycle in the chain is a hard error.
[code]
PROFILE=minimal
[e]
[h2]sysroots[e]
sysroots: a NAMED alternate install root, wholly separate from the default one -- its own prefix, its own db/manifest, installed into via mp itself rather than by hand-copying files. define sysroots/<name>.conf (sibling to profiles/ and classes/, in any configured repo -- same priority search as everything else above), setting at minimum MP_PREFIX (and optionally its own TARGET_CC/ TARGET_HOST/ARCH/MICROARCH/etc, any key mplib::config already understands) -- e.g. sysroots/arm64-musl.conf:
[code]
MP_PREFIX="/var/mp-sysroots/arm64-musl"
TARGET_HOST="aarch64-linux-musl"
[e]
--sysroot=<name> on the CLI routes the WHOLE invocation there: loads that overlay as the highest-precedence config (wins over /etc/mp.conf, ~/.mp.conf, --config= overlays, and PROFILE=) and redirects db/manifest/ stage under WD/sysroots/<name> -- fully isolated from the default root's package tracking:
[code]
mp install --sysroot=arm64-musl musl somelib
[e]
a per-package SYSROOT=<name> section (same "<name>:" mechanism as HOLD/ MASK/USE) instead routes just ONE package -- and everything it recursively depends on -- into a named root within a single mixed invocation, so other packages named alongside it stay in the default root:
[code]
somepkg:
SYSROOT=arm64-musl
$ mp install somepkg otherpkg # somepkg -> arm64-musl, otherpkg -> default
[e]
either way, building AGAINST a populated sysroot needs no new mechanism: point a package's TARGET_SYSROOT (global or per-package, see the cross-compiling docs above) at that same sysroot's MP_PREFIX path, and its headers/libs are found automatically, same as any other TARGET_SYSROOT use.
[h2]package sets[e]
package sets: "@name" anywhere a package name is expected (CLI or a dep list) expands from WD/sets/name.set, one name/@nested-set/world/all per line, # comments allowed. no dedicated command needed to make one, it is just a text file.
[code]
$ cat /usr/mp/sets/toolchain.set
gcc
gnu-make
$ mp install @toolchain
[e]
hooks also fire per build phase now (pre_fetch/post_fetch/pre_build/ post_build/pre_check/post_check, alongside the existing pre_install/ post_install/pre_remove/post_remove), and HOOKS_DIR/<phase>/* runs every executable file found there (sorted), in addition to hook_<phase>=, so several independent hooks can share one phase instead of just one.
[code]
HOOKS_DIR=/usr/mp/hooks
$ mkdir -p /usr/mp/hooks/post_install
$ cat > /usr/mp/hooks/post_install/10-notify <<'EOF'
#!/bin/sh
echo "installed: $MP_PKG"
EOF
$ chmod +x /usr/mp/hooks/post_install/10-notify
[e]
[h2]a port's own check[e]
a port's own check: phase (new-format ports only, alongside fetch/patch/ build/install) only runs when RUN_TESTS is on -- off by default, since running a full test suite meaningfully slows down every install. a port with no check: phase is entirely unaffected either way.
[code]
RUN_TESTS="no"
[e]
[code]
SLOT: pkg_slot="12" lets several builds of the same pkg_name coexist
[e]
(e.g. gcc:12 and gcc:13), each installing into MP_PREFIX/<name>-<slot>; unset/"0" (the default, and every port that predates SLOT) installs flat as always. refer to one slot as name:slot (mp install gcc:12, mp remove gcc:12); a bare name with several slots installed picks by pkg_pref like a %tag would.
a slot string is an arbitrary compound identifier, so several independent axes coexist today with no extra code: a port declaring pkg_slot="12-glibc-znver3-O3" installs at MP_PREFIX/gcc-12-glibc-znver3-O3 and is referenced as gcc:12-glibc-znver3-O3 -- gcc versions, libcs, microarches, and optimization levels can all vary independently and coexist, each its own slot.
pkg_slot_use="flag1 flag2" additionally lets a single port's *USE flag* state drive its slot: each listed flag that's enabled contributes a "-flag" suffix (declared order), so e.g. curl declaring pkg_slot_use="ssl" and installed once with "curl: USE=ssl" and once with no USE at all gives you curl:ssl and curl (unslotted) side by side instead of one overwriting the other. set USE under the port's *bare* name (not the resulting slot, which doesn't exist yet when USE is read) -- mp.conf.example's own USE docs above apply unchanged.
whichever axis produced a slot, a dependent port referencing it explicitly -- pkg_deps="curl:ssl", same syntax as pkg_deps="gcc:12" -- gets that exact variant's private prefix automatically wired into its own CFLAGS/LDFLAGS/PKG_CONFIG_PATH at build time (a bare, unqualified pkg_deps="curl" is unaffected: resolved by pkg_pref among installed candidates like today, same as an unqualified gcc reference). this is what actually makes coexisting slots *usable* as build dependencies, not just non-colliding install paths -- e.g.:
[code]
networking/curl: pkg_slot_use="ssl" (curl and curl:ssl coexist)
somepkg depending on: pkg_deps="curl:ssl"
[e]
somepkg's build automatically receives -Icurl-ssl's-prefix/include, -Lcurl-ssl's-prefix/lib -Wl,-rpath,..., and curl-ssl's-prefix in PKG_CONFIG_PATH -- it links against curl:ssl specifically, never whichever curl (if any) happens to sit at the default prefix.
"mp slots gcc" lists every port declaring pkg_name=gcc: each one's effective slot, pkg_pref, whether it's installed, and which one is "auto-picked" by a bare "mp install gcc" (lowest pkg_pref, exactly matching find_portdir's own tie-break -- this command never disagrees with what an actual install would resolve to).
revdep safety net: removing a slot that something installed still links against (via the buildlink wiring above) is blocked by default --
[code]
err: curl:ssl cannot be removed: still linked against by: somepkg (--force to override)
[e]
"mp revdep curl:ssl" shows the same "who's linked against this" list without attempting a remove, so you can check first. "mp remove --force" still overrides, same as any other conflict this session's tree already blocks by default.
"mp fetch name" runs only a port's fetch: phase into its own cache dir (WD/fetch-cache/name), decoupled from the normal install lifecycle -- useful for warming a source cache/offline mirror; a legacy add.sh port has no separate fetch phase and is a no-op. "mp export setname" snapshots every currently-"requested" package (--all for everything installed) into WD/sets/setname.set, immediately usable as "mp install @setname" elsewhere -- the write side of the @name package-set mechanism above.
[h2]version constraints[e]
version constraints: a dep or CLI package name may carry one of >=1.2 <=1.2 >1.2 <1.2 =1.2.3 ~1.2 (any 1.2.x). "=X" pins the exact version to fetch/build (substituted into pkg_fetch's <VER_>, see ports/template/pkg.conf); the others only validate what is already resolved/installed -- mp does not search across versions for one that satisfies a >=/~ constraint, only pins an exact one with "=".
[h2]blockers[e]
blockers: a pkg_conflicts entry may be "pkg" or "!pkg" (soft: warns but does not block -- picking a conflict-free alternative among several %tag providers is handled automatically, see below) or "!!pkg" (hard: always blocks, e.g. two libc slots that truly cannot coexist). that field is a port author's OWN declaration -- CONFLICTS=<token> <token> ..., per-package only (no global form: a conflict is a relationship between two specific packages, not a system-wide toggle like a USE flag), is the user-facing override on top of it, same +/- delta convention as USE=/"mp use": a bare list replaces the port's declared conflicts outright, a +token/-token delta is applied atop them instead (the token after +/- carries pkg_conflicts' own '!'/'!!' markers verbatim, so lifting a declared soft entry needs the same leading '!' the declaration used):
[code]
examplepkg:
CONFLICTS=-otherpkg # lift a conflict examplepkg itself
# declares against otherpkg, no --force
# needed anymore
#CONFLICTS=+!!thirdpkg # or add a hard one it never declared
[e]
"mp conflicts examplepkg" lists what's currently effective; "mp conflicts examplepkg +token/-token" toggles and persists it, mirroring "mp use" exactly (including the empty-set round-trip).
%tag resolution backtracks: if the lowest-pkg_pref provider of a %tag would conflict with something already installed, mp tries the next provider instead of failing outright, and so on. if every provider conflicts, mp prompts interactively (pick one, or abort) when run at a terminal, or fails cleanly with no prompt otherwise.