Eclass writing guide
This section provides a brief introduction to eclass authoring.
Purpose of eclasses
An eclass is a collection of code which can be used by more than one ebuild. At
the time of writing, all eclasses live in the eclass/
directory in the tree.
Roughly speaking, there are three kinds of eclass:
-
Those which provide common functions which are used by many ebuilds (for
example,
autotools
,bash-completion-r1
,flag-o-matic
,toolchain-funcs
) -
Those which provide a basic build system for many similar packages (for
example,
perl-module
,vim-plugin
) -
Those which handle one or a small number of packages with complex build
systems (for example,
kernel-2
,toolchain
)
Adding and updating eclasses
Before committing a new eclass to the tree, it must be emailed to the gentoo-dev mailing list with a justification and a proposed implementation. Do not skip this step — sometimes a better implementation or an alternative which does not require a new eclass will be suggested.
Before updating any eclass, email patches to the gentoo-dev list. It may be that your proposed change is broken in a way you had not anticipated, or that there is an existing function which performs the same purpose, or that your function may be better off in its own eclass. If you don't email gentoo-dev first, and end up breaking something, expect to be in a lot of trouble.
Note that you should also, when sending your patch, CC any maintainers of the
eclass listed in the @MAINTAINER
tag. You may want to contact them
ahead of time and get their opinions too.
The exceptions to this rule are updates to per-package eclasses. For example,
the apache-2
eclass is only used by the www-servers/apache
package, and thus does not typically require changes to be emailed for review.
When removing a function or changing the API of an eclass, make sure that
it doesn't break any ebuilds in the Gentoo repository. Optionally, you may wish
to do a survey of some (official) overlays like ::guru
, ::musl
, or
::science
in order to better understand how it is currently used and
— where possible — avoid breakage by pinging the maintainers directly.
If there is an existing maintainer for an eclass (this is usually the case), you must talk to the maintainer before committing any changes.
A simple way to verify syntax is bash -n foo.eclass
.
#gentoo-dev
on IRC or informally determine if there are other similar changes (mainly
documentation) which should be pushed at the same time in order to avoid
unnecessary cache regeneration within a few hours or days of each other.
The same applies to your own work — please prepare all of your commits and
batch push them at once where possible.
Removing eclasses
Eclasses that are no longer in use may be removed from the tree, but developers must adhere to the following process:
-
Make sure that no packages or other eclasses in the tree
inherit
the eclass. - Send a lastrite message to the gentoo-dev and gentoo-dev-announce mailing-lists, announcing that the not-used eclass will be removed in 30 days.
-
Add a one line comment to the eclass, saying exactly
# @DEAD
so that the eclass-manpages package will not attempt to document it. - Wait for the 30-day period to pass, then remove the eclass from the tree.
# @DEPRECATED:
to ensure consumers are warned if they are still using the eclass. Do this at
least 30 days before removing the eclass.
Documenting eclasses
Eclasses are documented with comment blocks that follow a special markup syntax. The comment blocks are separated by blank lines and each block documents an individual element of an eclass.
Documentation tags for various eclass elements are explained in their
respective sections below. Common to all the tags that accept multiline
freetext, the @CODE
tag should be used when necessary to create
unformatted code chunks (such as example code) by placing the tag at the
beginning and the end. The @SUBSECTION
tag inserts a subsection
heading; it is allowed only in the main @DESCRIPTION
.
Note that pkgcheck
can check for issues in eclass documentation.
You could run e.g. pkgcheck scan -s eclass
to check for issues
in the tree or pkgcheck scan --commits
to check for issues
in your staged git commits.
groff
to properly break lines when generating eclass manpages.
Basic eclass format
An eclass is a bash
script which is sourced within the ebuild environment.
Files should be a simple text file with a .eclass
extension. Allowed
characters in the filename are lowercase letters, the digits 0-9, hyphens,
underscores and dots. Eclasses are not intrinsically versioned.
Eclasses should start with the standard ebuild header, along with comments explaining the maintainer and purpose of the eclass, and any other relevant documentation. Eclass documentation block should be the first documentation block to appear in the eclass. The following table summarizes the available documentation tags:
tag | required? | arguments | description |
---|---|---|---|
@ECLASS: |
Yes | Name of the eclass being documented | Documents various information about the eclass. Must appear as the first tag in the comment block. |
@MAINTAINER: |
Yes | One or more name and email pairs | List of maintainers for the eclass to be contacted. One line per maintainer. Must start on a newline after the tag. |
@AUTHOR: |
No | One or more name and email pairs | List of authors for the eclass. One line per author. Must start on a newline after the tag. |
@BUGREPORTS: |
No | Multiline freetext | Describes how bugs related to this eclass should be reported |
@VCSURL: |
No | A URI string | Points to the URL of the VCS that contains the eclass source |
@SUPPORTED_EAPIS: |
No | Space-separated list of EAPIs | List of EAPIs supported by this eclass |
@PROVIDES: |
No | Space-separated list of eclass names | List of indirectly inherited eclasses whose functions and variables may be used by an ebuild inheriting this eclass |
@BLURB: |
Yes | Single line freetext | Contains a short description for the eclass. Must be on the same line with the tag. |
@DEPRECATED: |
No | Replacement (or "none") | Declares that this eclass should no longer be used |
@DEAD |
No | — | For an eclass that is slated for removal; prevents the eclass-manpages package from documenting the eclass. |
@DESCRIPTION: |
No | Multiline freetext | Long description for the eclass |
@EXAMPLE: |
No | Multiline freetext | Examples that illustrate various uses of this eclass |
Eclass variables
Top level variables may be defined as for ebuilds. If any USE flags are
used, IUSE
must be set. The KEYWORDS
variable must not be set in an
eclass.
You should document the meaning, usage, and default value of every variable in your eclass. The tags available for documenting eclass variables are as follows:
tag | required? | arguments | description |
---|---|---|---|
@ECLASS_VARIABLE: |
Yes | Name of the eclass variable to which the documentation applies | This tag applies to eclass specific variables that affect the default behavior of the eclass. Read-only variables, which are exported by the eclass for developer use, are also documented with this tag. Must appear as the first tag in the comment block. |
@PRE_INHERIT |
No | — | This tag describes whether the variable must be defined before the eclass is inherited. This is important if any e.g. dependencies are modified in global scope at the point of sourcing. |
@USER_VARIABLE |
No | — | This tag describes whether the variable is unsuitable for use in ebuilds, i.e. if it is solely for user consumption via e.g. make.conf or a similar mechanism |
@OUTPUT_VARIABLE |
No | — | This tag indicates that the variable's value (which will be set by the eclass) should be read within an ebuild |
@DEFAULT_UNSET |
No | — | Indicates that this variable is unset by default if not set by the developer |
@INTERNAL |
No | — | Indicates that the variable is internal to the eclass |
@REQUIRED |
No | — | Indicates that this variable must be set by the developer |
@DEPRECATED: |
No | Optionally, the name of any replacement variable | Declares that this variable should no longer be used in ebuilds |
@DESCRIPTION: |
Yes | Multiline freetext | Long description for the eclass variable |
Eclass functions
Eclasses may define functions. These functions will be visible to anything which inherits the eclass.
You should document the purpose, arguments, usage, and return value of every function in your eclass. The standard tags available for documentation are:
tag | required? | arguments | description |
---|---|---|---|
@FUNCTION: |
Yes | Name of the function to which the documentation block applies | Documents information about an eclass function such as its calling convention etc. Must appear as the first tag in the comment block |
@USAGE: |
No | List of required and optional arguments to the function |
List of arguments that the eclass function accepts, specified in
the following syntax: < Required arguments>
[ Optional arguments]
|
@RETURN: |
* | Return value of the function |
Description for the value returned by the function. *: Required for functions that return a value. |
@MAINTAINER: |
No | Multiline freetext | List of contacts for the eclass function. One line per maintainer. Must start on a newline after the tag. |
@INTERNAL |
No | — | Indicates that the function is internal to the eclass and should not be called from outside |
@DEPRECATED: |
No | Optionally, the name of a replacement function | Declares that this function should no longer be used in ebuilds |
@DESCRIPTION: |
* | Multiline freetext |
Long description for the eclass function. *: Required if |
Eclass function variables
Eclass functions may make use of variables just like any other bash function. Special function-specific variables should be documented using the following tags:
tag | required? | arguments | description |
---|---|---|---|
@VARIABLE: |
Yes | Name of the function-specific variable to which the documentation applies | This tag applies to variables consumed by specific functions of the eclass. They are in effect only when the specific function is called. |
@USER_VARIABLE |
No | — | This tag describes whether the variable is unsuitable for use in ebuilds, i.e. if it is solely for user consumption via e.g. make.conf or a similar mechanism |
@DEFAULT_UNSET |
No | — | Indicates that this variable is unset by default if not set by the developer |
@INTERNAL |
No | — | Indicates that the variable is internal to the eclass function |
@REQUIRED |
No | — | Indicates that this variable must be set by the developer |
@DEPRECATED: |
No | Optionally, the name of any replacement variable | Declares that this variable should no longer be used in ebuilds |
@DESCRIPTION: |
Yes | Multiline freetext | Long description for the function variable |
Simple common functions eclass example
As an example, the following eclass was written to illustrate a better way of
installing OSX application files during a discussion on this subject. It defines
a single function, domacosapp
.
# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# @ECLASS: macosapp.eclass
# @MAINTAINER:
# Ciaran McCreesh <ciaranm@gentoo.org>
# @BLURB: install macos .app files to the relevant location.
# @FUNCTION: domacosapp
# @USAGE: <app-file> [new-file]
# @DESCRIPTION:
# Install the given .app file into the appropriate location. If
# [new-file] is given, it will be used as the new (installed) name of
# the file. Otherwise <app-file> is installed as-is.
domacosapp() {
[[ -z "${1}" ]] && die "usage: domacosapp <file> [new file]"
if use ppc-macos ; then
insinto /Applications
newins "$1" "${2:-${1}}"
fi
}
Export functions
An eclass may provide default implementations for any of the ebuild phase
functions (src_unpack
, pkg_postinst
, etc). This can be done either as a
simple function definition (which is not multiple eclass friendly) or using
EXPORT_FUNCTIONS
. Functions given to EXPORT_FUNCTIONS
are implemented
as normal, but have their name prefixed ("namespaced") with ${ECLASS}_
.
EXPORT_FUNCTIONS
.
EXPORT_FUNCTIONS
is a function, not a variable.
If multiple eclasses export the same function, the latest (inherited last)
defined version wins. If an ebuild defines a function that is exported, this
gets priority over any eclass version. This can be used to override
eclass-defined defaults — for example, say we had fnord.eclass
:
fnord_src_compile() {
do_stuff || die
}
EXPORT_FUNCTIONS src_compile
Then an ebuild could do this:
inherit fnord
src_compile() {
do_pre_stuff || die
fnord_src_compile
do_post_stuff || die
}
Eclasses may inherit other eclasses to make use of their functionality, and
historically there have been instances of eclasses calling
EXPORT_FUNCTIONS
and then inheriting another eclass. As inherited
eclasses may also execute EXPORT_FUNCTIONS
, it was not fully defined
which defaults should take effect. The general recommendation is now that
eclasses should not inherit other eclasses after calling
EXPORT_FUNCTIONS
.
Inherit guards
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.
A typical inherit guard looks as follows (for a hypothetical foo.eclass
):
if [[ -z ${_FOO_ECLASS} ]]; then
_FOO_ECLASS=1
# Variables and functions go here
fi
When it comes to EXPORT_FUNCTIONS
and inherit guards, the call to
EXPORT_FUNCTIONS
must be placed at the very end of the eclass
outside any inherit guards, like this:
if [[ -z ${_FOO_ECLASS} ]]; then
_FOO_ECLASS=1
foo_src_compile() {
...
}
fi
EXPORT_FUNCTIONS src_compile
This helps to ensure that the last inherited eclass gets to define the default
phase functions. Consider two eclasses foo.eclass
and bar.eclass
that define the same default phase function via EXPORT_FUNCTIONS
. If an
ebuild inherits both as inherit foo bar
, then the default phases are
defined by bar.eclass
. If foo.eclass
is then modified to inherit
bar
as well, then the ebuild's default functions could suddenly become
those from foo
if EXPORT_FUNCTIONS
was placed inside the inherit
guard.
EXPORT_FUNCTIONS
in
the last line of an eclass, outside of any inherit guards.
EXPORT_FUNCTIONS
in other places, even before
inherit
. They should not blindly be updated to follow the
recommended pattern here, as it could result in significant breakage.
Handling incorrect usage of an eclass
Sometimes an eclass is used incorrectly by an ebuild and the eclass knows it is being used incorrectly — 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:
# Copyright 1999-2022 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# @ECLASS: eapi-die.eclass
# @MAINTAINER:
# Gentoo Devmanual Project <devmanual@gentoo.org>
# @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
Simple build system eclass example
Here is an example of how a simple eclass for a hypothetical jmake
build
system might look. The eclass defines a few functions, along with default
implementations for the src_configure
and src_compile
phase
functions.
# Copyright 1999-2022 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# @ECLASS: jmake.eclass
# @MAINTAINER:
# Gentoo Devmanual Project <devmanual@gentoo.org>
# @AUTHOR:
# Ciaran McCreesh <ciaranm@gentoo.org>
# @BLURB: Demonstrate a simple build system eclass.
# @DESCRIPTION:
# Demonstrates EXPORT_FUNCTIONS and defines simple wrappers for the
# (hypothetical) jmake build system along with default src_configure and
# src_compile phase functions.
case ${EAPI} in
7|8) ;;
*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
esac
if [[ -z ${_JMAKE_ECLASS} ]]; then
_JMAKE_ECLASS=1
BDEPEND=">=sys-devel/jmake-2"
# @FUNCTION: jmake-configure
# @USAGE: [additional-args]
# @DESCRIPTION:
# Passes all arguments through to the appropriate "jmake configure"
# command.
jmake_configure() {
jmake configure --prefix=/usr "$@"
}
# @FUNCTION: jmake_src_configure
# @USAGE: [additional-args]
# @DESCRIPTION:
# Calls jmake_configure() to configure a jmake project. Passes all
# arguments through to the appropriate "jmake configure" command.
jmake_src_configure() {
jmake_configure "$@" || die "configure failed"
}
# @FUNCTION: jmake_build
# @USAGE: [additional-args]
# @DESCRIPTION:
# First builds all dependencies, and then passes through its arguments
# to the appropriate "jmake build" command.
jmake_build() {
jmake dep && jmake build "$@"
}
# @FUNCTION: jmake_src_compile
# @DESCRIPTION:
# Calls jmake_build() to compile a jmake project.
jmake_src_compile() {
jmake_build || die "build failed"
}
fi
EXPORT_FUNCTIONS src_configure src_compile