aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Bracht Laumann Jespersen <t@laumann.xyz>2022-04-15 23:42:03 +0200
committerUlrich Müller <ulm@gentoo.org>2022-04-24 14:51:53 +0200
commitbe55691ed16c2ab4dd7c3d635fc2bd67ecd6b563 (patch)
treeabf26b272e6ae60cf535b8a5c41afcc6a29802d0 /eclass-writing
parentebuild-writing/patches: Add "Conditional patching" section (diff)
downloaddevmanual-be55691ed16c2ab4dd7c3d635fc2bd67ecd6b563.tar.gz
devmanual-be55691ed16c2ab4dd7c3d635fc2bd67ecd6b563.tar.bz2
devmanual-be55691ed16c2ab4dd7c3d635fc2bd67ecd6b563.zip
eclass-writing: doc inherit guards, EXPORT_FUNCTIONS warning
Add a section to explain what inherit guards are and their usage, and add a "rule of thumb" to put EXPORT_FUNCTIONS at the end of eclasses for max portability. This turned into a larger re-ordering of the sections so the full jmake example can showcase all the features discussed in the preceding sections, like EAPI guard, inherit guard, and EXPORT_FUNCTIONS at the very end. Signed-off-by: Thomas Bracht Laumann Jespersen <t@laumann.xyz> Signed-off-by: Ulrich Müller <ulm@gentoo.org>
Diffstat (limited to 'eclass-writing')
-rw-r--r--eclass-writing/text.xml156
1 files changed, 122 insertions, 34 deletions
diff --git a/eclass-writing/text.xml b/eclass-writing/text.xml
index f0f03c0..22b973f 100644
--- a/eclass-writing/text.xml
+++ b/eclass-writing/text.xml
@@ -638,11 +638,11 @@ eclass-defined defaults <d/> for example, say we had <c>fnord.eclass</c>:
</p>
<codesample lang="ebuild">
-EXPORT_FUNCTIONS src_compile
-
fnord_src_compile() {
do_stuff || die
}
+
+EXPORT_FUNCTIONS src_compile
</codesample>
<p>
@@ -659,6 +659,115 @@ src_compile() {
}
</codesample>
+<p>
+Eclasses may inherit other eclasses to make use of their functionality, and
+historically there have been instances of eclasses calling
+<c>EXPORT_FUNCTIONS</c> and then inheriting another eclass. As inherited
+eclasses may also execute <c>EXPORT_FUNCTIONS</c>, it was not fully defined
+which defaults should take effect. The general recommendation is now that
+eclasses should not inherit other eclasses <e>after</e> calling
+<c>EXPORT_FUNCTIONS</c>.
+</p>
+
+</body>
+</section>
+
+<section>
+<title>Inherit guards</title>
+<body>
+
+<p>
+It is common practice to surround the main contents of an eclass with an
+"inherit guard". Much like header guards known from C, inherit guards help
+ensure that an eclass can be inherited multiple times and have its functions and
+variables defined only once. An inherit guard is only needed for an eclass that
+can be inherited more than once.
+</p>
+
+<p>
+A typical inherit guard looks as follows (for a hypothetical <c>foo.eclass</c>):
+</p>
+
+<codesample lang="ebuild">
+if [[ -z ${_FOO_ECLASS} ]]; then
+_FOO_ECLASS=1
+
+# Variables and functions go here
+
+fi
+</codesample>
+
+<p>
+When it comes to <c>EXPORT_FUNCTIONS</c> and inherit guards, the call to
+<c>EXPORT_FUNCTIONS</c> must be placed at the very end of the eclass
+<e>outside</e> any inherit guards, like this:
+</p>
+
+<codesample lang="ebuild">
+if [[ -z ${_FOO_ECLASS} ]]; then
+_FOO_ECLASS=1
+
+foo_src_compile() {
+ ...
+}
+fi
+
+EXPORT_FUNCTIONS src_compile
+</codesample>
+
+<p>
+This helps to ensure that the last inherited eclass gets to define the default
+phase functions. Consider two eclasses <c>foo.eclass</c> and <c>bar.eclass</c>
+that define the same default phase function via <c>EXPORT_FUNCTIONS</c>. If an
+ebuild inherits both as <c>inherit foo bar</c>, then the default phases are
+defined by <c>bar.eclass</c>. If <c>foo.eclass</c> is then modified to inherit
+<c>bar</c> as well, then the ebuild's default functions could suddenly become
+those from <c>foo</c> if <c>EXPORT_FUNCTIONS</c> was placed inside the inherit
+guard.
+</p>
+
+<note>
+The rule of thumb here is: put the call (if any) to <c>EXPORT_FUNCTIONS</c> in
+the last line of an eclass, outside of any inherit guards.
+</note>
+
+<warning>
+Old eclasses may put <c>EXPORT_FUNCTIONS</c> in other places, even before
+<c>inherit</c>. They should <e>not</e> blindly be updated to follow the
+recommended pattern here, as it could result in significant breakage.
+</warning>
+
+</body>
+</section>
+
+<section>
+<title>Handling incorrect usage of an eclass</title>
+<body>
+
+<p>
+Sometimes an eclass is used incorrectly by an ebuild and the eclass
+knows it is being used incorrectly <d/> the common example is an
+eclass that only works with a specific set of EAPIs, but is being
+accessed (inherited) by an ebuild with a different EAPI.
+In those cases, used sparingly as a last resort, it is allowed
+for an eclass to invoke die from the global scope. For example:
+</p>
+
+<codesample lang="ebuild">
+# Copyright 1999-2022 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: eapi-die.eclass
+# @MAINTAINER:
+# Gentoo Devmanual Project &lt;devmanual@gentoo.org&gt;
+# @SUPPORTED_EAPIS: 7 8
+# @BLURB: Calls die when used with an invalid EAPI.
+
+case ${EAPI} in
+ 7|8) ;;
+ *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+</codesample>
</body>
</section>
@@ -674,7 +783,7 @@ functions.
</p>
<codesample lang="ebuild">
-# Copyright 1999-2021 Gentoo Authors
+# Copyright 1999-2022 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# @ECLASS: jmake.eclass
@@ -688,7 +797,13 @@ functions.
# (hypothetical) jmake build system along with default src_configure and
# src_compile phase functions
-EXPORT_FUNCTIONS src_configure src_compile
+case ${EAPI} in
+ 7|8) ;;
+ *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+if [[ -z ${_JMAKE_ECLASS} ]]; then
+_JMAKE_ECLASS=1
BDEPEND="&gt;=sys-devel/jmake-2"
@@ -725,40 +840,13 @@ jmake-build() {
jmake_src_compile() {
jmake-build || die "build failed"
}
+fi
+
+EXPORT_FUNCTIONS src_configure src_compile
</codesample>
</body>
</section>
-<section>
-<title>Handling incorrect usage of an eclass</title>
-<body>
-
-<p>
-Sometimes an eclass is used incorrectly by an ebuild and the eclass
-knows it is being used incorrectly <d/> the common example is an
-eclass that only works with a specific set of EAPIs, but is being
-accessed (inherited) by an ebuild with a different EAPI.
-In those cases, used sparingly as a last resort, it is allowed
-for an eclass to invoke die from the global scope. For example:
-</p>
-
-<codesample lang="ebuild">
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-# @ECLASS: eapi-die.eclass
-# @MAINTAINER:
-# Gentoo Devmanual Project &lt;devmanual@gentoo.org&gt;
-# @SUPPORTED_EAPIS: 7 8
-# @BLURB: Calls die when used with an invalid EAPI.
-
-case ${EAPI} in
- 7|8) ;;
- *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
-esac
-</codesample>
-</body>
-</section>
</chapter>
</guide>