commit: 00e18924303200d6e6fcbbeae3c8d385fd05f081 Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> AuthorDate: Sat Dec 20 12:11:56 2025 +0000 Commit: Ulrich Müller <ulm <AT> gentoo <DOT> org> CommitDate: Tue Dec 30 20:47:07 2025 +0000 URL: https://gitweb.gentoo.org/proj/devmanual.git/commit/?id=00e18924
general-concepts/dependencies: mention common pitfalls This commit copies from mgorny's blog posts about common pitfalls in writing dependencies, and adds them to the devmanual. Signed-off-by: Michał Górny <mgorny <AT> gentoo.org> Closes: https://bugs.gentoo.org/587526 Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> [Dropped bullet point for PDEPEND. Whitespace changes.] Signed-off-by: Ulrich Müller <ulm <AT> gentoo.org> general-concepts/dependencies/text.xml | 308 +++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) diff --git a/general-concepts/dependencies/text.xml b/general-concepts/dependencies/text.xml index e776150..d5c5407 100644 --- a/general-concepts/dependencies/text.xml +++ b/general-concepts/dependencies/text.xml @@ -850,5 +850,313 @@ USE flags. This would then break building your ebuild. </body> </section> + +<section> +<title>Common pitfalls</title> +<body> + +<p> +The following pitfalls occur frequently when dealing with slots, slot +operators, any-of dependencies, and blockers. They are easy to miss and can lead +to subtle resolver behaviour or rebuild issues. The guidance below is a brief +summary; see the linked references for deeper background. +</p> + +</body> + +<subsection> +<title>Separate dependency specifications are not combined into one slot</title> +<body> + +<p> +Multiple independent dependency specifications are not guaranteed to be +satisfied by the same slot of a slotted package. For example, a common version +range like the following can be satisfied by two different slots: +</p> + +<codesample lang="ebuild"> +# Bad (if sys-libs/db is slotted): +DEPEND=">=sys-libs/db-2 + <sys-libs/db-5" +</codesample> + +<p> +If <c>sys-libs/db</c> is slotted and two installed slots each satisfy one +side of the range, the resolver can legally use them separately. +</p> + +<p> +Likewise, independent USE requirements may be met by different slots with +different USE configurations. For packages that are not truly multi-slotted +(i.e. slots represent mutually incompatible ABIs), the safe fix is to state the +intended slot explicitly or to express the intent via any-of groups limited per +slot. +</p> + +<codesample lang="ebuild" + caption="Example of a bad USE dependency on a slotted package"> +# Bad: +RDEPEND="sys-libs/db[foo] + bar? ( sys-libs/db[baz] )" +</codesample> + +<codesample lang="ebuild" + caption="Example of a good version range across slots"> +DEPEND=" + || ( + =sys-libs/db-5*:5 + =sys-libs/db-4*:4 + ) +" +</codesample> + +<codesample lang="ebuild" + caption="Example of a good USE dependency on a slotted package"> +RDEPEND=" + || ( + ( sys-libs/db:5 tools? ( sys-libs/db:5[cxx] ) ) + ( sys-libs/db:4 tools? ( sys-libs/db:4[cxx] ) ) + ) +" +</codesample> + +</body> +</subsection> + +<subsection> +<title>The <c>:=</c> slot operator with multiple slots</title> +<body> + +<p> +The <c>:=</c> operator records the slot/sub-slot of the best matching +installed version for the given +<uri link="::general-concepts/dependencies/#Dependency syntax"> +dependency specification</uri>. If that +dependency specification can match slots newer than the versions you explicitly +allowed elsewhere, it may bind to the wrong slot (and even pull it in during +build). +</p> + +<p> +To prevent this, ensure the dependency specification carrying <c>:=</c> cannot +match slots newer than intended. One simple pattern is to cap it with an upper + +bound that excludes unwanted major versions while keeping <c>:=</c> on the same +package: +</p> + +<codesample lang="ebuild" + caption="Example of good use of := with version range"> +DEPEND=" + || ( + =sys-libs/db-5* + =sys-libs/db-4* + ) + <sys-libs/db-6:= +" +</codesample> + +<p> +This forces the slot-operator binding to a version in the requested range at +build time. Be cautious when combining multiple conditional USE sets with a +slot operator; keeping the <c>:=</c> dependency specification simple and +separately constrained is usually clearer. +</p> + +</body> +</subsection> + +<subsection> +<title>Understanding any-of dependencies</title> +<body> + +<p> +An any-of group (<c>|| ( ... )</c>) guarantees only that at least one +immediate child element is satisfied for the relevant dependency class. It +does not guarantee which element will be chosen, nor does it bind the choice +made at build time to the choice used later at runtime. Order can be used as +an implementation hint but is not a contract. +</p> + +<codesample lang="ebuild" caption="Example of an any-of dependency"> +DEPEND=" + || ( + dev-libs/A + dev-libs/B + dev-libs/C + ) +" +</codesample> + +<p> +If more than one alternative is installed, it is undefined which one is actually +going to be used. In fact, the package may even provide the user with explicit +run time choice of the dependency used, or use multiple of them. Replacing one +alternative with another later still satisfies the dependency and should not be +assumed to force rebuilds unless you have expressly tied the dependency via +slots/sub-slots (outside of any-of) or via other mechanisms. +</p> + +</body> +</subsection> + +<subsection> +<title>Do not use <c>:=</c> inside any-of groups</title> +<body> + +<warning> +Do not place <c>:=</c> dependency specifications inside <c>|| ( ... )</c> +groups. The semantics of the slot operator (binding to the slot/sub-slot of the +installed match) conflicts with the semantics of any-of (only one child needs to +match and may change later). As a result, the requirements cannot be satisfied +reliably and behaviour is undefined. pkgcheck will warn about this situation +with <uri link="https://pkgcore.github.io/pkgcheck/man/pkgcheck.html#baddependency"> +BadDependency</uri> results. +</warning> + +<p> +Instead, keep the any-of block free of slot operators and add a separate, +well-constrained dependency specification carrying <c>:=</c> if you need rebuild +tracking. +</p> + +<codesample lang="ebuild" + caption="Example of incorrect use of := inside any-of"> +# Bad: +RDEPEND=" + || ( + dev-libs/A:= + dev-libs/B:= + ) +" +</codesample> + +<codesample lang="ebuild" + caption="Example of correct use of := outside any-of"> +IUSE="a b" +REQUIRED_USE="^^ ( a b )" +RDEPEND=" + a? ( dev-libs/A:= ) + b? ( dev-libs/B:= ) +" +</codesample> + +<note> +The above is only an illustration of structure. Choose the package for the +slot-operator binding that truly determines ABI compatibility for your +package, and constrain its version range appropriately. +</note> + +</body> +</subsection> + +<subsection> +<title>Any-of and <c>:*</c> across classes</title> +<body> + +<p> +Any-of groups (<c>|| ( ... )</c>) and the <c>:*</c> slot operator are valid in +all dependency classes. However, there is no binding between occurrences in +different classes. An any-of in <c>DEPEND</c> guarantees only that at least one +alternative is installed before the build; an any-of in <c>RDEPEND</c> or +<c>PDEPEND</c> guarantees only that at least one is installed for runtime. +You should not assume the same alternative or slot will be used for both. +</p> + +</body> +</subsection> + +<subsection> +<title>The <c>:=</c> slot operator across classes</title> +<body> + +<p> +The <c>:=</c> operator is technically valid in all classes but is useful only +when the matching package is installed at the time metadata is recorded +(install from source or binary package creation). Practically, the dependency +specification using <c>:=</c> should be present in <c>RDEPEND</c> to express the +rebuild relationship, and <c>DEPEND</c> must guarantee that a matching package +is installed at the relevant time. +</p> + +<codesample lang="ebuild" +caption="Example of typical pattern: tie rebuilds to sub-slot changes"> +DEPEND="dev-libs/foo:=" +RDEPEND="${DEPEND}" +</codesample> + +<note> +The dependency specifications need not be textually identical as long as +<c>DEPEND</c> guarantees that some package matching the <c>RDEPEND</c> <c>:=</c> +dependency specification is installed when metadata are recorded. +</note> + +<codesample lang="ebuild"> +# Also valid: +RDEPEND="dev-libs/foo:=" +DEPEND="dev-libs/foo" +</codesample> + +</body> +</subsection> + +<subsection> +<title>Blockers across dependency classes</title> +<body> + +<p> +Blockers are valid in all classes but their usefulness differs: +</p> + +<ul> + <li> + Weak blockers (<c>!</c>) are primarily meaningful in <c>RDEPEND</c>, where + the uninstall of the blocked package may be delayed until after the new + package starts installing, allowing file collisions to be replaced. + Technically they are allowed in <c>DEPEND</c>, but they do not influence + the build environment and are not useful there on their own. + </li> + <li> + Strong blockers (<c>!!</c>) must be resolved before the dependency is + considered satisfied. They therefore make sense in both <c>DEPEND</c> + (before building) and <c>RDEPEND</c> (before installation). + </li> + <li> + Remember the general caveat from above: weak blockers should be included + in <c>RDEPEND</c> rather than used purely in <c>DEPEND</c>. + </li> +</ul> + +<codesample lang="ebuild"> +# Weak blocker: meaningful in RDEPEND +RDEPEND="!app-misc/foo" + +# Strong blocker: enforced pre-build or pre-install +DEPEND="!!sys-libs/bar" +</codesample> + +</body> +</subsection> + +<subsection> +<title>Further reading</title> +<body> + +<p> +For extended discussion with examples, see the +<uri link="https://blogs.gentoo.org/mgorny/2016/06/21/dependency-pitfalls-regarding-slots-slot-ops-and-any-of-deps/"> +blog post</uri> and its +<uri link="https://blogs.gentoo.org/mgorny/2016/06/22/dependency-classes-and-allowed-dependency-types/"> +follow-up</uri>, and the relevant sections of the Package Manager Specification +on +<uri link="https://pms.gentoo.org/9/pms.html#anyof-dependency-specifications"> +any-of dependency specifications</uri> and +<uri link="https://pms.gentoo.org/9/pms.html#slot-dependencies"> +slot dependencies</uri>. +</p> + +</body> +</subsection> +</section> </chapter> </devbook>
