Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
316 changes: 316 additions & 0 deletions ebuild-writing/eapi/text.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1428,6 +1428,322 @@ $(usev foo --enable-foo)
</dd>
</dl>

</body>
</subsection>
</section>

<section>
<title>EAPI 9</title>
<body>

<note>
This section is based on the
<uri link="https://https://projects.gentoo.org/pms/9/eapi-cheatsheet.pdf">
EAPI Cheat Sheet</uri>.
</note>
</body>

<subsection>
<title>EAPI 9 profiles</title>
<body>

<dl>
<dt>Default EAPI for profiles</dt>
<dd>
Profile directories that don't contain an own <c>eapi</c> file no longer
default to EAPI 0, but to the EAPI specified in the top-level
<c>profiles</c> directory.
</dd>

<dt><c>use.stable</c> and <c>package.use.stable</c></dt>
<dd>
Profile dirs may contain two new files <c>use.stable</c> and
<c>package.use.stable</c>. They can be used to override the USE flags
specified by <c>make.defaults</c>, but act only on packages that would be
merged due to a stable keyword.

The format of the <c>use.stable</c> file is simple: Each line contains a
USE flag to enable; a minus sign before the flag indicates that the flag
should be disabled instead.

The <c>package.use.stable</c> file has the same format as <c>package.use</c>
(see <uri link="::eclass-reference/make.conf/">make.conf(5)</uri>).

<c>USE_EXPAND</c> values may be enabled or disabled by using
<c>expand_name_value</c>.

Flags listed in <c>package.use.stable</c> take precedence over these listed
in <c>package.use</c>, which in turn take precedence over <c>use.stable</c>.
</dd>
</dl>

</body>
</subsection>

<subsection>
<title>EAPI 9 ebuild format</title>
<body>

<dl>
<dt>Bash version is now 5.3</dt>
<dd>
<p>
Ebuilds can use Bash version 5.3 (was 5.0 before).
Some notable new features are:
</p>

<ul>
<li>
<p>
<c>declare</c> and <c>local</c> now have a <c>-I</c> option that
inherits the attributes and value from of any existing variable with
the same name at a surrounding scope. For example, an ebuild could do
</p>
<codesample lang="ebuild">
local -Ix ROOT
</codesample>
<p>
to export the <c>ROOT</c> variable to the environment, from where an
external could get its value.
</p>
</li>

<li>
<p>
There is a new form of command substitution: <c>${ command; }</c> or
<c>${|command;}</c> to capture the output of <c>command</c> without
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just learned about both of these. What's the point of ${|command;}? The example from the manpage doesn't seem very helpful to me: https://www.gnu.org/software/bash/manual/bash.html#:~:text=while%20this%20construct%20does%20not%20require%20any%20output%20to%20expand%20to

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If commandis a shell function, then this avoids the overhead of forking.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Flowdalic you mean for the ${ command; } form, what about the second one, the one that "expands to the value of the REPLY shell variable after command executes"?

Copy link
Member Author

@ulm ulm Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have expanded the section quite a bit (with some bits and pieces from the Bash manual), but I would be grateful if someone could come up with a real example that could be used in an ebuild.

The ${| REPLY=12345; } example in the Bash manual is indeed pointless because it is equivalent to writing 12345 as a constant.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Flowdalic you mean for the ${ command; } form, what about the second one, the one that "expands to the value of the REPLY shell variable after command executes"?

Right, I missed that this is about the piped variant. Sorry.

I assume one use case of {| command } is command also being required to print some status output. But that's just an educated guess.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume one use case of {| command } is command also being required to print some status output. But that's just an educated guess.

Yes. However, in ebuild context one would use einfo or elog for status output, which don't use stdout but stderr. So I still don't see where it could be useful for us.

forking a child process and using pipes.
</p>
<p>
<c>${ command; }</c> executes <c>command</c> in the current execution
environment and captures its output. Any side effects of <c>command</c>
take effect immediately in the current execution environment and
persist after the command completes. This type of command substitution
superficially resembles executing an unnamed shell function: local
variables are created as when a shell function is executing, and the
<c>return</c> builtin forces <c>command</c> to complete; however, the
rest of the execution environment is shared with the caller.
</p>
<p>
The <c>${|command;}</c> construct expands to the value of the
<c>REPLY</c> shell variable after <c>command</c> executes, without
removing any trailing newlines, and the standard output of
<c>command</c> remains the same as in the calling shell. Bash creates
<c>REPLY</c> as an initially-unset local variable when <c>command</c>
executes, and restores <c>REPLY</c> to its old value after
<c>command</c> completes, as with any local variable.
</p>
<p>
For example, this construct expands to <c>12345</c>, and leaves the
shell variable <c>X</c> unchanged in the current execution environment:
</p>
<codesample lang="ebuild">
${ local X=12345; echo $X; }
</codesample>
<p>
while the following construct does not require any output to expand to
<c>12345</c> and restores <c>REPLY</c> to the value it had before the
command substitution:
</p>
<codesample lang="ebuild">
${| REPLY=12345; }
</codesample>
</li>

<li>
<p>
Pattern substitution now duplicates a common <c>sed</c> idiom:
If the <c>patsub_replacement</c> shell option is enabled (which it is
by default), any unquoted <c>&amp;</c> in the replacement string is
replaced with the portion of the string that matched the pattern.
</p>
<p>
For instance:
</p>
<codesample lang="ebuild">
var="foobar"
echo "${var/foo/&amp;123}"
</codesample>
<p>
will print <c>foo123bar</c>, i.e. the <c>&amp;</c> in the replacement
string is replaced with the string <c>foo</c> that matched the pattern.
</p>
<p>
A backslash can be used to escape the <c>&amp;</c> and insert a literal
<c>&amp;</c> in the replacement string.
</p>
</li>
</ul>
</dd>
</dl>

</body>
</subsection>

<subsection>
<title>EAPI 9 variables</title>
<body>

<dl>
<dt>Variables are no longer exported</dt>
<dd>
<p>
The package manager no longer exports its defined shell variables to the
environment but keeps them as unexported shell variables, namely:
</p>
<ul>
<li>
<c>CATEGORY</c>, <c>P</c>, <c>PF</c>, <c>PN</c>, <c>PV</c>, <c>PR</c>,
<c>PVR</c>
</li>
<li><c>A</c></li>
<li>
<c>FILESDIR</c>, <c>DISTDIR</c>, <c>WORKDIR</c>, <c>S</c>, <c>ROOT</c>,
<c>EROOT</c>, <c>SYSROOT</c>, <c>ESYSROOT</c>, <c>BROOT</c>, <c>T</c>,
<c>EPREFIX</c>, <c>D</c>, <c>ED</c>
</li>
<li><c>USE</c></li>
<li><c>EBUILD_PHASE</c>, <c>EBUILD_PHASE_FUNC</c></li>
<li><c>MERGE_TYPE</c></li>
<li><c>REPLACING_VERSIONS</c>, <c>REPLACED_BY_VERSION</c></li>
<li><c>ECLASS</c>, <c>INHERITED</c>, <c>DEFINED_PHASES</c></li>
</ul>
<important>
Exceptions are <c>TMPDIR</c> and <c>HOME</c> which are always exported.
</important>
<p>
The same applies to variables set in <c>make.defaults</c> that have
specific meanings or special handling. These are no longer exported to the
environment of an EAPI 9 ebuild:
</p>
<ul>
<li><c>ARCH</c></li>
<li><c>CONFIG_PROTECT</c>, <c>CONFIG_PROTECT_MASK</c></li>
<li>
<c>USE</c>, <c>USE_EXPAND</c>, <c>USE_EXPAND_UNPREFIXED</c>,
<c>USE_EXPAND_HIDDEN</c>, <c>USE_EXPAND_IMPLICIT</c>,
<c>IUSE_IMPLICIT</c>
</li>
<li><c>ENV_UNSET</c></li>
<li>
All variables named in <c>USE_EXPAND</c> and
<c>USE_EXPAND_UNPREFIXED</c>
</li>
<li>
All <c>USE_EXPAND_VALUES_${v}</c> variables, where <c>${v}</c> is a
value in <c>USE_EXPAND_IMPLICIT</c>
</li>
</ul>
<p>
All other variables set in <c>make.defaults</c> will still be exported to
the environment.
</p>
<p>
As a consequence, external commands can no longer rely on the value of the
<c>ROOT</c> variable in the environment. For example, <c>eselect</c> must
be called with the <c>--root</c> option in EAPI 9:
</p>
<codesample lang="ebuild">
pkg_postinst() {
eselect --root="${ROOT}" emacs update ifunset
}
</codesample>
</dd>
</dl>

</body>
</subsection>

<subsection>
<title>EAPI 9 commands</title>
<body>

<dl>
<dt><c>assert</c> has been banned</dt>
<dd>
Our definition of <c>assert</c> deviated from the semantics of the command
in mainstream programming languages and was a source of confusion.
Therefore, use of the <c>assert</c> command in ebuilds is no longer
allowed. <c>pipestatus</c> (see below) should be used as replacement.
</dd>

<dt><c>domo</c> has been banned</dt>
<dd>
The operation of the <c>domo</c> command was unintuitive. It also hardcoded
<c>${PN}</c> as the gettext domain, which is often not what is wanted.
Therefore, the <c>domo</c> command has been banned. <c>insinto</c> plus
<c>newins</c> should be used as replacement.
</dd>

<dt><c>pipestatus</c></dt>
<dd>
Checks if all commands in the last executed pipeline have returned an exit
status of zero. When the <c>-v</c> option is specified, also prints the
shell's pipe status array.
<codesample lang="ebuild">
foo | bar | baz
pipestatus || die
</codesample>
</dd>

<dt><c>ver_replacing</c> <e>op v2</e></dt>
<dd>
<p>
Checks if the relation <e>v1 op v2</e> is true for at least one element
<e>v1</e> of <c>REPLACING_VERSIONS</c>. <e>op</e> can be any operator that
is accepted by <c>ver_test</c>. Returns shell true (0) if the specified
relation holds for at least one element, shell false (1) otherwise.
In particular, shell false is returned when <c>REPLACING_VERSIONS</c>
is empty.
</p>
<p>
Obviously, <c>ver_replacing</c> is only meaningful in phases where
<c>REPLACING_VERSIONS</c> is defined, i.e. in <c>pkg_preinst</c> and
<c>pkg_postinst</c>.
</p>
<codesample lang="ebuild">
pkg_postinst() {
if ver_replacing -lt 3; then
elog "This is a major upgrade and may break your existing setup!"
fi
}
</codesample>
</dd>

<dt><c>edo</c></dt>
<dd>
Outputs its entire argument list as an informational message, then executes
it as a simple shell command, with standard failure behaviour.
</dd>
</dl>

</body>
</subsection>

<subsection>
<title>EAPI 9 merging and unmerging</title>
<body>

<dl>
<dt>Merging of symlinks</dt>
<dd>
<p>
When merging <c>D</c> to <c>ROOT</c>, absolute symlinks are now merged
as-is. The package manager will no longer strip a leading <c>D</c> from
their link targets.
</p>
<p>
In previous EAPIs, any absolute symlink whose link target started with
<c>${D}</c> was rewritten with the leading <c>${D}</c> removed.
That behaviour was ill-defined because <c>D</c> is not guaranteed to have
the same value that it had in the <c>src_*</c> phases. For example, when
a binary package was merged on a target host with <c>PORTAGE_TMPDIR</c>
different from the build host's <c>PORTAGE_TMPDIR</c>, symlink rewriting
would have failed.
</p>
</dd>
</dl>

</body>
</subsection>
</section>
Expand Down
40 changes: 30 additions & 10 deletions xsl/lang.highlight.ebuild.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@

<xsl:variable name="pkg-mgr-keywords">
<!-- Package manager commands in EAPI 0 (excluding commands banned in later EAPIs) -->
assert best_version debug-print debug-print-function debug-print-section die diropts dobin docinto doconfd dodir
dodoc doenvd doexe doinfo doinitd doins dolib.a dolib.so doman domo dosbin dosym ebegin econf eend eerror einfo
einfon elog emake ewarn exeinto exeopts EXPORT_FUNCTIONS fowners fperms has has_version inherit insinto insopts into
keepdir newbin newconfd newdoc newenvd newexe newinitd newins newlib.a newlib.so newman newsbin unpack use usev
use_enable use_with
best_version debug-print debug-print-function debug-print-section die diropts dobin docinto doconfd dodir dodoc
doenvd doexe doinfo doinitd doins dolib.a dolib.so doman dosbin dosym ebegin econf eend eerror einfo einfon elog
emake ewarn exeinto exeopts EXPORT_FUNCTIONS fowners fperms has has_version inherit insinto insopts into keepdir
newbin newconfd newdoc newenvd newexe newinitd newins newlib.a newlib.so newman newsbin unpack use usev use_enable
use_with
<!-- EAPI 4 -->
docompress nonfatal
<!-- EAPI 5 -->
Expand All @@ -32,6 +32,8 @@
<!-- EAPI 7 -->
dostrip eqawarn ver_cut ver_rs ver_test
<!-- EAPI 8: no new commands -->
<!-- EAPI 9 -->
edo pipestatus ver_replacing
<!-- Sandbox -->
adddeny addpredict addread addwrite
<!-- Phase functions -->
Expand Down Expand Up @@ -113,11 +115,29 @@
</xsl:call-template>
<xsl:variable name="data-slack" select="substring-after($data, $lang.highlight.ebuild.variable-start)"/>
<xsl:variable name="variable-name" select="substring-before($data-slack, $lang.highlight.ebuild.variable-end)"/>
<span class="Identifier">${<xsl:value-of select="$variable-name"/>}</span>
<xsl:call-template name="lang.highlight.ebuild.subtokenate">
<xsl:with-param name="data" select="substring-after($data, $lang.highlight.ebuild.variable-end)"/>
<xsl:with-param name="nokeywords" select="$nokeywords"/>
</xsl:call-template>
<xsl:choose>
<!-- Bash 5.3 ${ command; } or ${| command; } -->
<xsl:when test="$data-slack = '' or $data-slack = '|'">
<span class="PreProc">${<xsl:value-of select="$data-slack"/></span>
</xsl:when>
<!-- ${variable} -->
<xsl:when test="contains($data-slack, '}')">
<span class="Identifier">${<xsl:value-of select="$variable-name"/>}</span>
<xsl:call-template name="lang.highlight.ebuild.subtokenate">
<xsl:with-param name="data" select="substring-after($data-slack, $lang.highlight.ebuild.variable-end)"/>
<xsl:with-param name="nokeywords" select="$nokeywords"/>
</xsl:call-template>
</xsl:when>
<!-- No closing brace found, something is wrong -->
<xsl:otherwise>
<xsl:message>Warning: No closing brace in <xsl:value-of select="$data"/></xsl:message>
<span class="PreProc">${</span>
<xsl:call-template name="lang.highlight.ebuild.subtokenate">
<xsl:with-param name="data" select="$data-slack"/>
<xsl:with-param name="nokeywords" select="$nokeywords"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>

<xsl:when test="contains($data, '$(')">
Expand Down