exheres-0 is an experimental, fluid EAPI and tree layout (in theory, the two concepts are independent, but the only place using one without the other is the Paludis test suite). When we stop breaking things we’ll make an EAPI exheres-1 and carry on using exheres-0 for experiments.
metadata/
about.conf (mandatory)
accounts/
groups/
*.conf
users/
*.conf
categories.conf (mandatory)
layout.conf (mandatory)
options/
descriptions/
options.conf
*.conf
repository_mask.conf
licences/
BSD-3
GPL-2
GPL-3
profiles/
repo_name (mandatory)
packages/
cat-foo/
exlibs/
per-category.exlib
pkg-foo/
pkg-foo-1.23.exheres-0
per-package.exlib
exlibs/
foo.exlib
sets/
stages.conf
A self-contained repository (a repository that doesn’t have any masters) must define a set of profiles. The tree layout for those profiles looks like this:
profiles/
system.conf
options.conf
amd64/
parents.conf
make.defaults
options.conf
desktop/
parents.conf
desktop/
options.conf
The special system
set is defined by these top-level files. An exheres repository cannot have a different system
set depending upon which profile is selected.
system.conf
: A list of packages that are in the special system
set.For any particular profiles directory the following files are all optional.
parents.conf
: Each line contains a relative path to another profile. Settings from each parent profile are inherited by this profile, and can be overridden by it. All valid profiles must inherit the top level profiles/ dir because its options.conf
defines valid suboptions.
make.defaults
: Defines default environment variables for this profile. Simple key=“value” format. The value of variables specified in parent profiles are available through ${key} syntax, but can be overridden. A quoted string can span over multiple lines by either a simple newline or a baskslash-escaped newline.
options.conf
: Defines default options for this profile. Inherits default options from parent profiles but may override them. Comments are allowed on separate lines beginning with a #
. Backslash-escaped newlines are supported. Example syntax with comments explaining it below:
# Define all valid suboption prefixes (this belongs strictly in the top-level options.conf):
*/* SUBOPTIONS: PLATFORM AMD64_CPU_FEATURES INPUT_DRIVERS VIDEO_DRIVERS
# Define hidden suboptions:
*/* HIDDEN_SUBOPTIONS: PLATFORM AMD64_CPU_FEATURES
# Mask all platform and cpu features suboptions:
*/* PLATFORM: (-amd64) (-x86)
*/* AMD64_CPU_FEATURES: (-3dnow) (-sse2) (-sse3)
# Global default options:
*/* INPUT_DRIVERS: keyboard mouse
*/* VIDEO_DRIVERS: vesa
*/* bash-completion ncurses openssl zlib
# Per package defaults:
dev-scm/git curl
cat/foo bar
# Mask an option:
cat/foo (-baz)
To override some of the above in a child profile:
# Force the x86_64/amd64 platform on:
*/* PLATFORM: (amd64)
# Unhide the AMD64_CPU_FEATURES suboptions:
*/* HIDDEN_SUBOPTIONS: -AMD64_CPU_FEATURES
# Unmask amd64 cpu features:
*/* AMD64_CPU_FEATURES: -3dnow -sse2 -sse3
# Enable more global options:
*/* VIDEO_DRIVERS: intel nv radeon
app-emulation/wine win64
# Disable an option that was enabled in a parent profile:
cat/foo -bar
# Mask more options:
media/vlc (-win32codecs)
# Force an option on:
dev-libs/openssl (sse2)
# Unmask or unforce an option that was masked in a parent profile:
cat foo -baz
Repositories expose optional and required metadata to package managers. The metadata is stored in the metadata
sub-directory.
about.conf
: Provide basic information to the package manager. (key = value)
summary
: A short summary.
description
: A longer description. (optional)
homepage
: The home page.
owner
: The owner: Real Name <valid email address>
.
status
: One of the following values:
core
: Official topic repository.experimental
: Official topic repository which is considered experimental.dev
: Official repository from an exherbo developer.third-party
: Unofficial third-party repository.Additionally, the name of the repository needs to be included in the profiles
sub-directory. The profiles
sub-directory also contains other information relating to the repository. This information must either be provided explicitly here or by specifying a master repository that does provide this information, such as ::arbor
.
profiles/repo_name
: Contains a single line with the name of the respository. Repository name must be unique. Every repository must contain this file.Some packages need to depend on a specific group or user. This can be achieved by adding group/<group's
name>
or user/<user's name>
to DEPENDENCIES (Note: in “build:” or “build+run:” if it’s needed by the exheres!). For both groups and users, a corresponding config file needs to be added, <group's
name>.conf
or <user's name>.conf
respectively.
accounts/groups/*.conf
: Installable groups. (key = value)
preferred_gid
: Preferred group ID. (optional)accounts/users/*.conf
: Installable users. (key = value)
gecos
: Information about the user. (required field, see passwd(5))preferred_uid
: Preferred user ID. (optional)shell
: Path to the login shell. (optional)home
: Path to the home directory. (optional)extra_groups
: List of extra groups. (optional)primary_group
: The primary group. (optional)If the primary_group
contains a group which is also tracked via accounts, user/<user's name>
will have a dependency on that group.
categories.conf
: Lists categories which are provided by your repository regardless of existence in master repositories. This will be obsolete in the future, as we want to remove categories.
category1
category2
...
layout.conf
: Provide extended information to the package manager. (key = value)
masters
: A list of master repositories (see Repository Masters).options/descriptions/
options.conf
: Describes global options for installable packages. For local options refer to Annotations in MYOPTIONS.
*.conf
: Describes sub-options (e.g. descriptions for the linguas suboption are in linguas.conf) for installable packages.
option - description
...
repository_mask.conf
: Lists masked packages with mask reasons using annotations:
app-admin/eclectic[~scm] [[
author = [ Mike Kelly <pioto@exherbo.org> ]
date = [ 08 Sep 2009 ]
token = scm
description = [ Mask scm version ]
]]
To mask more than one package use *annotations
:
(
sys-devel/gcc[~scm]
sys-devel/gcc[~4.5-scm]
) [[
*author = [ Ingmar Vanhassel <ingmar@exherbo.org> ]
*date = [ 02 Oct 2009 ]
*token = scm
*description = [ Mask live GCC versions ]
]]
The token key can contain any of the following values:
There is also a second category of tokens; these are allocated for groups where packages are tightly coupled. Or, in other words, where unmasking one package in the group typically means having to unmask all the others.
testing
but for toolchain componentstesting
but specific to the GNOME platformOther values can be added to these lists if needed. The user
token is reserved for user masks.
A master repository which is listed in metadata/layout.conf
in your repository allows you to:
masters
.Master repositories are not inherited from masters. So if you need an exlib from ::foo which needs another exlib from ::bar then you need to list both foo and bar in masters. Since foo needs bar as a master, bar needs to be listed before foo.
Keep in mind that you should not specify masters if you just depend on a package in that repository. The unavailable
repositories track that and will tell users to add the repository if they need the package.
What Gentoo calls use
flags we call options
. We may support non-Boolean options at some point if there are good use cases demonstrated. USE_EXPAND
is called SUBOPTIONS
, and uses a colon (e.g. video_drivers:intel
).
Keywords have become platforms. We’re still using arch
and ~arch
, for now. We don’t automatically inject PLATFORM
into MYOPTIONS
; platforms are regular SUBOPTIONS
and should be managed as such.
Various things that were merely QA notices for ebuilds are strict errors.
Sometimes packages install to invalid directories. To prevent this exheres-0
comes with a whitelist of directories legal to install to. The default whitelisted directories are:
/etc
/usr
/var
Additionally the following directories are explicitly forbidden to install to:
/run
/run/lock
/var/run
/var/lock
To add additional directories to these lists use exdirectory
.
Exheres packages may use all features of GNU bash 4.0, and may assume that the extglob
and the globstar
shell options are set. The locale is preset to C
.
Packages should assume the existence of GNU sed 4.0, GNU grep, coreutils, or a highly compatible implementation of sed, grep, and coreutils that supports many extensions that the GNU implementations support.
Users should avoid adding workarounds for certain implementations, and instead add a dependency on the GNU implementation of the tool if it is required.
If the logic that requires GNU coreutils is part of the exheres/exlib, consider doing it in a more compatible way, but don’t bend over backwards for it; If it can be done portably with a single change in arguments used, or it can be done in an extra line or so, that’s fine, but if it requires recreating the intended functionality entirely, that’s when you need to add a dependency on GNU coreutils.
SLOT
, mandatoryDOWNLOADS
(like SRC_URI
; see below)RESTRICT
(for now)HOMEPAGE
, mandatoryLICENCES
(like LICENSES
), mandatorySUMMARY
(short, like DESCRIPTION
in 0-based EAPIs), mandatoryDESCRIPTION
(long, optional, wrapped at ~100 characters)PLATFORMS
(like KEYWORDS
), mandatoryDEPENDENCIES
(see below, also see incremental metadata variables), mandatoryMYOPTIONS
(like IUSE
, but much more useful, see below, also see incremental metadata variables), mandatoryREMOTE_IDS
(see below)UPSTREAM_CHANGELOG
, UPSTREAM_RELEASE_NOTES
, UPSTREAM_DOCUMENTATION
(see below)All metadata variables must be defined independently of any system, profile or tree dependent data, and must not vary depending upon exheres phase. Metadata may be generated on a different system from that upon which the exheres will be used, and the exheres must generate identical metadata every time it is used.
EAPI
: The exheres format in use, (comes from the file extension, don’t change it yourself).REPODIR
: The path to the repository, (like PORTDIR
).FETCHEDDIR
: The path to where fetched files, enabled things in DOWNLOADS, get installed, (like DISTDIR
).FILES
: Path to the files/ dir for patches and small files used by the exheres, (like FILESDIR
).ARCHIVES
: Names of the fetched archives in FETCHEDDIR, (like A
).WORKBASE
: Path to the base work dir, (like WORKDIR
).WORK
: Path to the work dir in which most src_*
phases will be run, (like S
). This is preset to the path where the primary archive is expected to be unpacked, but it may be altered in the exheres. src_*
phases after src_unpack
start in this directory if it exists. src_prepare
, src_compile
and src_install
die if they’re defined and this dir does not exist.IMAGE
: Path to the image dir where files get installed before merge, (like D
). The contents of this dir gets merged to ROOT
during the merge phase.TEMP
: Path to a temporary directory, (like T
).BANNEDDIR
: Gets prepended to PATH
, contains wrappers for executables that are not allowed in exheres. (See dobanned
)EXJOBS
: Integer specifying how many jobs a user wishes to run simultaneously. May be empty if the user did not configure jobs. Must not be altered by an exheres. emake
automatically respects EXJOBS
.AA
, ARCH
, KV
PROVIDE
(and no old style virtuals)REPLACING_IDS
(see below)REPLACED_BY_ID
(see below)ROOT
: The absolute path to the root directory in which the package is to be merged. pkg_*
phases must not try to touch anything outside this directory. ROOT
is invalid outside pkg_*
phases.EXHERES_PHASE
: The name of the current phase with the leading pkg_
or src_
stripped, e.g.: pretend
, setup
, compile
or install
. Additionally set to metadata
during metadata generation.OPTIONS
: List of all the enabled options seprarated by whitespaces, including suboptions, e.g. normaloption anotheroption suboption:one suboption:two
.SUBOPTION="one two"
. If the suboption is not in MYOPTIONS
or if there are no suboptions enabled the value will be an empty string.PNV
replaces P
, package name and version, e.g. foo-1
.PNVR
replaces PF
, package name, version and revision, e.g. foo-1-r3
.PN
, package name, e.g. foo
.PV
, package version, e.g. 1
.PVR
, package version and revision, e.g. 1-r3
.PR
, package revision, e.g. r3
. A package named cat/foo-1
will have PR be r0
.CATEGORY
(for now)Look like this.
DEPENDENCIES="
build+run:
foo/bar
run:
foo/baz
post:
foo/monkey
"
Labels affect all following atoms inside the current ( ) block, but not any higher level blocks. The default is build+run
but you should always specify it. So:
DEPENDENCIES="
blah? ( cat/build-and-run )
foo? (
cat/build-and-run
build:
cat/build-only
run:
cat/run-only
bar? (
cat/run-only
post:
cat/post-only
)
cat/run-only-again
)
cat/build-and-run
"
The full list of labels is:
build
: Dependency during build for the unpack
, prepare
, configure
, compile
, test
, test-expensive
and install
phases.built-against
: Dependency for things that need to build against me (has a build
dependency on me).fetch
: Dependency for fetching listed DOWNLOADs and/or for the src_fetch_extra
phase.install
: Dependency during install for the setup
, preinst
and postinst
phases.post
: Like run except may be installed after me to break a cycle.recommendation
: Optional run-time dependency which is taken by default.run
: Run-time dependency.suggestion
: Optional run-time dependency which is not taken by default.test
: Dependency for the test
phase.test-expensive
: Dependency for the test-expensive
phase.Not all labels are fully implemented. For example install
is currently identical to build
. Optional dependencies (recommendations and suggestions) should always be accompanied by a description annotation that explains why you would want to take or ignore them.
category/package_name:slot[version][option]
Above is the basic syntax of a package dependency for easy reference. Note that a package dependency can be as simple as foo/bar
, however most packages require specific versions.
Slot dependencies:
foo/bar:2
or foo/bar:2[>=2.1]
foo/bar:=
or foo/bar:=[>=2.1]
. Means “any matching version, but at runtime I need the slot against which I was compiled.” (Strictly, I need the slot of the best matching version that was installed at compile time.)foo/bar:*
or foo/bar:*[>=2.1]
. Means “any matching version, and I don’t mind if you change the slots available later on.Version dependencies:
foo/bar[>=1.2&<2]
or foo/bar[=1.1|=1.2|=1.3]
. Do not mix with prefix-suffix requirements. Using only a single requirement is OK. Mixing |
and &
is forbidden. (Version requirements go before option deps, so foo/bar[>=1.0][baz]
).Option dependencies:
Option deps: foo/bar[opt]
and foo/bar[-opt]
. A dependency on several options: foo/bar[baz][quux]
. We found that we had lots of code like opt? ( foo/bar[opt] ) !opt? (
foo/bar[-opt] )
, so there are shortcuts:
foo/bar[opt]
Enabledfoo/bar[opt=]
Equal to my valuefoo/bar[opt!=]
Not equal to my valuefoo/bar[opt?]
Enabled if I’m enabledfoo/bar[opt!?]
Enabled if I’m disabledfoo/bar[-opt]
Disabledfoo/bar[-opt?]
Disabled if I’m enabledfoo/bar[-opt!?]
Disabled if I’m disabledfoo/bar[?opt]
Explicitly state that the presumed option opt is not required on foo/bar. Note that this is only needed if the option isn’t explicitly mentioned in the dependency anyway, e.g. foo/bar[opt?]
.In any of the variants, opt
may optionally end in a (+)
, a (-)
or (if the option includes a suboption prefix) a (?)
to specify the behaviour when matching the spec against a package that does not have the flag. If none is specified, it is illegal for the remainder of the spec to match any such package. The (+)
and (-)
forms indicate that the option should be assumed to be enabled or disabled respectively. The (?)
indicates that this option requirement should be ignored if the target package has no options at all under the suboption in question. The (+)
, (-)
or (?)
goes before the =
, !=
, ?
or !?
, if both are present.
If opt
consists of a suboption prefix followed by :*
, it is a shortcut for specifying all the options under the specified suboption that exist in the package containing the dependency.
Operators:
~>
means the same as it does for Gems. For example [~>1.2.3]
is equivalent to [>=1.2.3&<1.3]
.=...*
is a component-wise prefix comparison, not stringwise.~
means equal to for package version and greater than or equal to the specified package revision.Additionally there are =
, >
, >=
, <
and <=
operators.
Blockers:
Adding a blocker to a package will prevent that the package and the blocked package are installed together. The reason for blockers must be explained using a description annotation
so that users can find out easily why they block. Sometimes it is useful to specify a resolution annotation
as well.
For further documentation of annotations for blockers see Annotations.
DEPENDENCIES="
build+run:
!foo/bar [[
description = [ foo/bar and this package both install /usr/bin/quux ]
resolution = uninstall-blocked-after
]]
"
In general, blockers should be used sparsely because they’re annoying for users to deal with. For example, instead of making all packages that install /usr/bin/sendmail block, we handle these using alternatives.
Do not use blockers for package moves / renaming a package either. See how to rename a package
DOWNLOADS
has two new things. First, labels:
DOWNLOADS="
like-primaryuri.tar.bz2
manual: fetch-restricted-stuff.tar.bz2
listed-only: will-not-look-on-mirrors.tar.bz2
local-only: only-on-local-mirrors.tar.bz2
"
Supported values are:
mirrors-first
mirrors-only
listed-only
listed-first
local-only
manual
Second, arrows:
DOWNLOADS="http://sucky-upstream/download/foo/1.2/foo.tar.bz2 -> foo-1.2.tar.bz2"
When consulting the listed URI
(which can be a mirror://
) the filename is used. When consulting mirrors and for the saved download location, the value on the right of the arrow is used.
Options can be used to make a download conditional:
DOWNLOADS="platform:amd64? ( amd64-only.tar.xz )"
Annotations are another new dep-like toy. They don’t convey any critical information for DEPENDENCIES
(as in, a compliant package manager need do nothing more than parse the contents, and an annotation-using package manager can ignore any particular key it wants). They look like this:
DEPENDENCIES="
build+run:
zoo/monkey [[
description = [ it needs a monkey ]
url = [ http://explain.exherbo.org/?zoo-monkey ]
]]
!zoo/clown [[
description = [ clowns will murder us in our sleep ]
url = [ http://explain.exherbo.org/?clowns-are-evil ]
resolution = uninstall-blocked-after
]]
suggestion:
zoo/snake [[
description = [ otherwise we can't strangle things ]
]]
"
Annotations start with [[
and end with ]]
. Inside, they’re key = value
or key = [ value that can
contain spaces ]
. Note that whitespace is mandatory everywhere. Also note that currently the only ‘quote’ we allow is [ ]
and you can’t use things that look like use?
flags, ( dependencies ) etc., but if this proves too restrictive we might change it.
Annotation keys we recognise currently are:
description
, which we might show to an end user in cave resolve
.
url
, for more information for an end user in cave resolve
.
note
, for more developer-oriented information. Shows up in cave show -c
, but not cave resolve
.
resolution
, for blockers only:
manual
uninstall-blocked-after
suggests uninstalling the blocked package after we are merged (you’re allowed to file collide if you do this).uninstall-blocked-before
suggests uninstalling the blocked package before we are merged (only use if you really really have to, and most definitely not just for collisions).upgrade-blocked-before
suggests upgrading the blocked package before we are mergedAnnotations are not limited to package and block dep specs. You can put them after other things too:
DEPENDENCIES="
build+run: [[ here = [ would apply to the labels ] ]]
foo? (
(
cat/one
cat/two
) [[ here = [ would apply to the () block ] ]]
cat/three
) [[ here = [ would apply to the foo? block ] ]]
"
DOWNLOADS="
mirror://foo/${PNV}.tar.bz2 [[ here = [ would apply to the URI ] ]]
"
If you need an annotation to apply to each leaf element in a ( )
block you can prefix it with an *
. The following two snippets are equivalent:
DEPENDENCIES="
build+run:
(
cat/one
cat/two
) [[
foo = [ would apply just to the block ]
*bar = [ would apply to each leaf node in this block ]
]]
"
DEPENDENCIES="
build+run:
(
cat/one [[ bar = [ would apply to each leaf node in this block ] ]]
cat/two [[ bar = [ would apply to each leaf node in this block ] ]]
) [[ foo = [ would apply just to the block ] ]]
"
Sometimes one feature causes multiple dependencies to be suggestions. Providing group-name
annotations
allows the feature to be taken with e.g. --take git-svn
rather than having to list each dependency separately.
DEPENDENCIES="
suggestion:
(
dev-scm/subversion[perl]
dev-perl/libwww-perl
dev-perl/TermReadKey
) [[ *description = [ Dependency for 'git svn' ] *group-name = [ git-svn ] ]]
dev-perl/TermReadKey [[ description = [ Dependency for 'git add --interactive' ] ]]
"
Don’t overdo annotations. Blockers almost always benefit from having them. So do suggestions and recommendations. Normal deps, not so much, although sometimes a little [[ note = [ configure.ac says
2.0, but we get runtime terminal corruption unless we use at least 2.3 ] ]]
might not go amiss.
LICENCES
supports annotations, too, as shown in the following example:
LICENCES="
GPL-3 [[ note = [ readline module ] ]]
LGPL-3
"
The only recognized annotation key for a licence is note
. Blocks of licences can also be annotated with the last-checked
key.
LICENCES="( GPL-3 LGPL-3 ) [[ last-checked = 3.1.4 ]]"
The purpose of LICENCES is to determine what type of licence you have to accept in order to install a package, not to show exactly which attributions you might need to use or other details. For this reason there are a number of generic licences available with placeholders for the attribution. If the licence of the software you are packaging matches one of these you should use it. The definition of a match is not set in stone so apply common sense and as always ask if you are in doubt.
Every licence of an exheres has to match a file in the licences
directory of the repository or one of its masters.
For packages that have different parts under different licences, list each one separated by a whitespace:
LICENCES="
GPL-3 [[ note = [ readline module ] ]]
LGPL-3
"
For packages with a dual licensing, use the syntax below:
LICENCES="|| (
GPL-3 [[ note = [ readline module ] ]]
LGPL-3
)"
MYOPTIONS
is a bit like IUSE
, except more powerful. All flags have to be listed in MYOPTIONS
, even SUBOPTIONS
flags, and there is no special ARCH
handling. Labels are used to select the active suboption. For example:
MYOPTIONS="
foo
bar
baz
linguas:
en
fr
platform:
x86
"
You need to list any platforms that will be used in dependencies or queried in any way; there is no need to list a platform simply because a package is keyworded on that platform.
Local flag descriptions, and more detailed descriptions for flags with a global meaning, are specified via annotations:
MYOPTIONS="imlib2 [[ description = [ Use imlib2 to render icons ] ]]"
Do not start your description with “enables support for”. This is superfluous. Do not describe foo
as “Support for foo” unless even Wulf’s dead grandmother knows what foo is; you can at least manage “Support for the foo image format”.
Flags can also have requirements:
MYOPTIONS="
foo
bar
baz [[ requires = [ foo -bar ] ]]
linguas:
en
en_GB [[ requires = [ linguas: en ] ]]
"
These are checked just before pkg_pretend
is called (and even if they fail, pkg_pretend
will still be called). Theoretically you can override pkg_bad_options
(being sure to call default
to get the standard description displayed) to get improved error messages, but this may not be a good idea.
To have a requires
annotation applied to an all-of block you can use *requires
. This is a shortcut for applying the requirement to each child:
MYOPTIONS="
X
python
(
gtk [[ requires = python ]]
qt
motif
) [[ *requires = X ]]
"
Here, gtk
requires both X
and python
(but we discourage this style – see below).
All-of blocks also support a number-selected
annotation, which can have the value at-least-one
, at-most-one
or exactly-one
:
MYOPTIONS="
X
python
(
gtk [[ requires = python ]]
qt
motif
) [[
number-selected = at-most-one
*requires = X
]]
"
Since number-selected
is always applied to a group of options it should never be prefixed with an *
. ( gtk qt motif ) [[ *number-selected = at-least-one ]]
is wrong and would be equivalent to:
MYOPTIONS="
gtk [[ number-selected = at-least-one ]]
qt [[ number-selected = at-least-one ]]
motif [[ number-selected = at-least-one ]]
"
which does not make any sense.
MYOPTIONS
annotations can be done conditionally. Make sure you apply the annotations to an all-of block, not the conditional block. Any requirements inside a conditional block are tested only if the condition is met; any flags listed inside a conditional block are always considered part of MYOPTIONS
, but the conditional flag itself must be explicitly listed beforehand.
MYOPTIONS="
X
python
(
gtk [[ requires = python ]]
qt
motif
) [[ *requires = X ]]
X? ( ( gtk qt motif ) [[ number-selected = exactly-one ]] )
"
Negative flags are allowed, both as a requires
value and inside an all-of block. Use sparingly.
In terms of style, it’s clearest to list all relevant flags first, along with any descriptions, and then go through and apply any requirements, avoiding grouping requirements together. So:
MYOPTIONS="
X [[ description = [ Build a graphical user interface ] ]]
python [[ description = [ Generate bindings for the Python programming language ] ]]
gtk
qt
motif
gtk [[ requires = python ]]
( gtk qt motif ) [[ *requires = X ]]
X? ( ( gtk qt motif ) [[ number-selected = exactly-one ]] )
"
Presumed options are required by default. Any package that depends on this package without explicitly saying something about this option will require this option enabled.
MYOPTIONS="
X [[ presumed = true ]]
"
If any package does not need the option enabled they need to state so explicitly using a cat/foo[?X]
dependency or any other form that mentions X
in the dependency.
The REMOTE_IDS
function provides a pointer to this package in a remote database. It is specified as a list of database:index
tokens:
REMOTE_IDS="freecode:blah vim:1234"
A non-definitive list of remote databases:
cpan
: the index is the project’s CPAN project name.debian
: the index is the project’s Debian package name.gnome
: the index is the project’s GNOME project name.freecode
: the index is the project’s Freecode project name.freshcode
: the index is the project’s Freshcode project name.github
: the index is the project’s GitHub ${user}/${project}
.launchpad
: the index is the project’s Launchpad ${project}/${branch}
.pypi
: the index is the project’s Python Package Index project name.rubygems
: the index is the project’s RubyGems project name.sourceforge
: the index is the project’s Sourceforge project name.xfce
: the index is the project’s Xfce ${module}/${project}
.vim
: the index is the project’s Vim Scripts script ID (number).When adding new remote databases, it is important that given the database name and index, a client can find the information being pointed to without any searching.
UPSTREAM_CHANGELOG
contains URLs for upstream changelogs:
UPSTREAM_CHANGELOG="http://blah/changelog.txt [[ lang = en ]]"
UPSTREAM_DOCUMENTATION="
${HOMEPAGE}/doc/admin/ [[ lang = en description = [ Administration guide ] ]]
${HOMEPAGE}/doc/user/ [[ lang = en description = [ User manual ] ]]
"
Likewise, UPSTREAM_DOCUMENTATION
contains documentation URLs and UPSTREAM_RELEASE_NOTES
contains release notes (e.g. NEWS
files). These are all for user use.
REPLACING_IDS
is a whitespace-separated list of ids (e.g. cat/pkg-1:0::installed) that are being replaced (uninstalled or overwritten) as a result of this install. REPLACING_IDS
is defined in pkg_preinst
and pkg_postinst
. In addition it may be defined in pkg_pretend
and pkg_setup
, but you should take care to handle binary package creation and installation correctly if you need to use it in these phases.
REPLACED_BY_ID
is a single id that is replacing this package, if it is being replaced as part of an install, or empty otherwise. REPLACED_BY_ID
is defined in pkg_prerm
and pkg_postrm
.
The default phase functions are named default_src_blah
, and you’re allowed to (and encouraged to) call them if you’re just adding functionality. But rather than calling default_src_blah
, you can just call the special default
function that’ll look at what phase we’re in and act accordingly.
Do not use the default functions if it involves doing something weird. Especially do not use the default functions if it means screwing around with the DEFAULT_
variables. If you are not simply setting the DEFAULT_
variables statically in global scope, you should write your own functions instead.
Phases are listed in running order. The pkg_config
and pkg_info
phases are separate user invoked phases.
Upgrade/reinstall/downgrade of a package:
New
refers to the newly installed exheres. Old
refers to the one that’s being replaced.
pkg_preinst()
merge phase
pkg_prerm()
unmerge phase
pkg_postrm()
pkg_postinst()
Run in the sandbox
and with userpriv
. Called for every package after a cave resolve
or cave resolve -x
(but not currently for binaries – not sure how we’ll handle those yet). You can die
in here to tell the user to change config things etc. (but use option deps and the like if possible instead).
pkg_pretend
is not part of the normal call sequence. Variables set in this phase will not be available in other phases. pkg_pretend
must not alter the file system.
default_pkg_pretend()
{
:
}
Run in the sandbox
and with userpriv
if RESTRICT=fetch is enabled.
default_pkg_nofetch()
{
[[ -z "${ARCHIVES}" ]] && return
local f g=
for f in ${ARCHIVES} ; do
[[ -f "${FETCHEDDIR}/${ARCHIVES}" ]] && continue
if [[ -z "${g}" ]] ; then
echo "The following files could not be fetched automatically for ${PN}:"
g=no
fi
echo "* ${f}"
done
}
Run in the sandbox
and with userpriv
.
default_src_fetch_extra()
{
:
}
Run in the sandbox
.
default_pkg_setup()
{
:
}
Run in the sandbox
and with userpriv
.
default_src_unpack()
{
[[ -n "${ARCHIVES}" ]] && unpack --if-compressed ${ARCHIVES}
}
Run in the sandbox
and with userpriv
. The DEFAULT_SRC_PREPARE_PATCHES
array, if set, should be set in global scope and mustn’t be set dynamically. If you’re doing anything complicated, write your own src_prepare
. The variable is just for the easy cases.
default_src_prepare()
{
if [[ -n "${DEFAULT_SRC_PREPARE_PATCHES[@]}" ]]; then
expatch "${DEFAULT_SRC_PREPARE_PATCHES[@]}"
fi
}
Run in the sandbox
and with userpriv
. Again, DEFAULT_SRC_CONFIGURE_*
is just for the easy cases.
default_src_configure()
{
if [[ -x ${ECONF_SOURCE:-.}/configure ]] ; then
econf \
"${DEFAULT_SRC_CONFIGURE_PARAMS[@]}" \
$(for s in "${DEFAULT_SRC_CONFIGURE_OPTIONS[@]}" ; do \
option ${s} ; \
done ) \
$(for s in "${DEFAULT_SRC_CONFIGURE_OPTION_ENABLES[@]}" ; do \
option_enable ${s} ; \
done ) \
$(for s in "${DEFAULT_SRC_CONFIGURE_OPTION_WITHS[@]}" ; do \
option_with ${s} ; \
done ) \
$(for s in "${DEFAULT_SRC_CONFIGURE_TESTS[@]}" ; do \
expecting_tests ${s} ; \
done )
fi
}
Run in the sandbox
and with userpriv
. DEFAULT_SRC_COMPILE_PARAMS
is passed on to emake.
default_src_compile()
{
if [[ -f Makefile ]] || [[ -f makefile ]] || [[ -f GNUmakefile ]] ; then
emake "${DEFAULT_SRC_COMPILE_PARAMS[@]}"
fi
}
Run in the sandbox
and with userpriv
. Should be considered mandatory.
default_src_test()
{
if [[ -f Makefile ]] || [[ -f GNUmakefile ]] || [[ -f makefile ]] ; then
echo "Makefile found, looking for potential test targets"
if make -j1 -n "${DEFAULT_SRC_TEST_PARAMS[@]}" check ; then
echo "Found check target"
emake "${DEFAULT_SRC_TEST_PARAMS[@]}" check
elif make -j1 -n "${DEFAULT_SRC_TEST_PARAMS[@]}" test ; then
echo "Found test target"
emake "${DEFAULT_SRC_TEST_PARAMS[@]}" test
else
echo "No check or test target, skipping tests"
fi
else
echo "No Makefile, skipping tests"
fi
}
Run in the sandbox
and with userpriv
. Used to run testsuites that take a very long time or are otherwise expensive using a huge amount of diskspace, memory or other resource.
default_src_test_expensive()
{
:
}
Run in the sandbox
.
This default function is fairly complex so it deserves a longer explanation. The first part simply looks for a Makefile
and, if one is found, uses the install target with DESTDIR="${IMAGE}
. It dies if an existing Makefile
is missing an install target and it supports one variable for adding extra parameters for emake install
. The emagicdocs
function, however, tries to identify (case-insensitively) documents that are common in lots of packages and installs them by means of dodoc. It supports three variables for adding extra docs and one variable for excluding undesired docs.
DEFAULT_SRC_INSTALL_PARAMS
Extra parameters for emake -j1 DESTDIR="${IMAGE}" install
.
DEFAULT_SRC_INSTALL_EXTRA_DOCS
File names listed here get added to the list of default doc targets. Any documents named exactly like these (still case-insensitive), prefixed by digits and/or starting with these followed by a dot, a dash or an underscore get installed.
DEFAULT_SRC_INSTALL_EXTRA_SUBDIRS
Useful when installing files with the same name (e.g. README
) from multiple directories is desired. All identified targets inside these sub-directories are installed to the destination keeping the original directory structure.
DEFAULT_SRC_INSTALL_EXTRA_PREFIXES
Look for each target with this prefix too. This can also be used to install each match from any sub-directory directly to the top-level documentation directory, discarding the original directory structure.
DEFAULT_SRC_INSTALL_EXCLUDE
List of exceptions that shouldn’t be installed.
default_src_install()
{
if [[ -f Makefile ]] || [[ -f makefile ]] || [[ -f GNUmakefile ]] ; then
if make -j1 -n "${DEFAULT_SRC_INSTALL_PARAMS[@]}" install ; then
echo "Found a makefile, using the install target"
emake -j1 DESTDIR="${IMAGE}" "${DEFAULT_SRC_INSTALL_PARAMS[@]}" install
else
die "default emake install located a makefile but no install target"
fi
else
echo "No makefile found, not using emake install"
fi
emagicdocs
}
The code for emagicdocs
is listed under Helper functions.
Run in the sandbox
.
default_pkg_preinst()
{
:
}
Run in the sandbox
.
default_pkg_prerm()
{
:
}
Run in the sandbox
.
default_pkg_postrm()
{
:
}
Run in the sandbox
.
default_pkg_postinst()
{
:
}
Run in the sandbox
.
default_pkg_config()
{
eerror "No configuration function is defined"
}
Run in the sandbox
and with userpriv
. Can be run for both installed and uninstalled packages.
default_pkg_info()
{
:
}
Organised by where they’re implemented in Paludis, to make it easy to keep this up to date.
We have the nonfatal
function which modifies how a function that usually dies on its own works: If a function, e.g. emake
, dies on its own, it means that any code beyond that function (e.g. a || die "blah"
) won’t ever be reached and, thus, a default error message is displayed. If you want to display a custom error message, you can add the prefix nonfatal
to the function call, e.g. nonfatal emake blah
. This will cause emake
to just emit a non-zero return code which you can use with a regular || die "blah"
function, i.e. emake
will signal things went wrong but won’t die by itself.
die
: Die unconditionally with its argument as a failure message and with a backtrace.assert
: Checks the shell’s pipe status variable and if any component is non-zero (indicating failure) calls die
with its argument as a failure message. See above.einfo
elog
ewarn
eerror
ebegin
eend
einfon
ewend
Some commands optionally take a version argument – this is indicated as ever command [version]
. Whenever a version is optional and omitted, ever functions default to the PV for the current id, unless stated otherwise.
Rather than being a number, the index parameter can be a separator character such as ‘-’, ‘.’ or ‘_’. In this case, the first separator of this kind is selected.
ever split [version]
: Returns the version with all version separators replaced by whitespace.
ever split 1.2.3
1 2 3
ever split_all [version]
: Returns the version, including version separators, separated by whitespace.
ever split_all 1.2.3
1 . 2 . 3
ever major [version]
: Returns the major version of version
.
ever major 1.2.3
1
ever range <range> [version]
: Returns the given range for a given version. Ranges can be either…
A single number: Returns the version component at the given index
ever range 2 1.2.3
2
Two numbers separated by a dash: Returns the range of version components, defined by the two given indexes, separated by the dash.
ever range 1-2 1.2.3
1.2
A number preceded or followed by a dash: Returns an open range, defined by one given index, and either the start or the end of the version.
ever range 2- 1.2.3.4
2.3.4
ever range -3 1.2.3.4
1.2.3
ever remainder [version]
: Returns the remaining part of <version>
after the major version.
ever remainder 1.2.3
2.3
ever at_least <versionA> [versionB]
: True when <versionB>
is equal or newer than <versionA>
, otherwise false. When versionB is omitted, PVR is used instead.
ever at_least 1.2.3 1.3.5 && echo Yes
Yes
ever at_least 1.2.3 1.0.0 || echo No
No
ever delete <index> [version]
: Delete the version separator in position <index>
.
ever delete 2 1.2.3
1.23
ever delete_all [version]
: Delete all version separators in <version>
.
ever delete_all 1.2.3
123
ever replace <index> <replacement> [version]
: Replace the version separator in position <index>
with <replacement>
.
ever replace 2 - 1.2_rc1
1.2-rc1
ever replace_all <replacement> [version]
: Replace all version separators with <replacement>
.
ever replace_all - 1.2.3
1-2-3
ever is_scm [version]
: True when <version>
is an scm version, otherwise false.
ever is_scm scm && echo Yes
Yes
ever is_scm 1.0-scm && echo Yes
Yes
ever is_scm 1.0 || echo No
No
Note that ever is_scm
is not a replacement for ever at_least scm
.
keepdir
: Dies on failure or when an argument begins with ${IMAGE} unless called via nonfatal.into
: Install into given directoryinsinto
: Install into given directory when using doins/newinsexeinto
: Install into given directory when using doexe/newexedocinto
: Install into given directory when using dodoc/newdocinsopts
: Set the permissions of installed files, e.g. -m755 -o user -g groupdiropts
: Set the permissions of installed directories, e.g. -m755 -o user -g groupexeopts
: Set the permissions of installed executables, e.g. -m755 -o user -g grouplibopts
: Set the permissions of installed libraries, e.g. -m755 -o user -g groupWe probably want to ban these at some point.
KV_major
KV_minor
KV_micro
KV_to_int
get_KV
See Magic Commands under Sandboxing.
die_unless_nonfatal
: By default die with the provided error message. If called via nonfatal
this function just prints the provided error message and emits a non-zero return value. Note that it is your job to make sure that this non-zero return value gets passed on to the callee of the function that uses this. E.g.:
ecmake() {
[...]
echo cmake ${cmakeargs} "$@" ${EXTRA_ECONF} "${WORK}"
cmake ${cmakeargs} "$@" ${EXTRA_ECONF} "${WORK}" || \
die_unless_nonfatal "Cmake failed" || return 1
[...]
}
is_nonfatal
: Returns true when the current function was called via nonfatal
, this can be used to make exlib functions behave differently depending on whether they’re called via nonfatal
.
assert_unless_nonfatal
: Like assert
but calls die_unless_nonfatal
rather than die
on failure.
nonfatal
: Make expatch
, econf
, keepdir
and anything that calls die_unless_nonfatal
emit a non-zero return value instead of dying upon failure.
expatch
: Applies patches. Only allowed in the prepare phase. No patch level guessing is done. expatch can take five kinds of arguments:
--recognised-suffixes
: Mostly for internal use. Makes expatch only apply patches that end in a recognised file extension (bz2
, gz
, Z
, z
, zip
, ZIP
, jar
, diff
and patch
). If required those get uncompressed by bzip2
, gzip
or unzip
.
-p[0-9]*
: Set patch level for all following patches. This can be changed as often as needed between applying patches. It defaults to -p1
.
-*
: All other arguments that begin with a dash are passed directly to patch for all subsequent patches.
[patch]
: If patch is a directory, recursively look for patches in that directory with a recognised file extension, uncompress them if needed and apply them. If it is not a directory uncompress if needed but apply regardless of file extension.
econf
: Calls a standard autoconf configure
script in ECONF_SOURCE
or in the current directory with the following standard configure arguments followed by arguments supplied to econf
(the variable ${prefix}
is set to /usr/$(exhost --target)
).
--build=$(exhost --build)
--host=$(exhost --target)
--prefix=${prefix}
--bindir=${prefix}/bin
--sbindir=${prefix}/bin
--libdir=${prefix}/lib
--datadir=/usr/share
--datarootdir=/usr/share
--docdir=/usr/share/doc/${PNVR}
--infodir=/usr/share/info
--mandir=/usr/share/man
--sysconfdir=/etc
--localstatedir=/var/lib
--disable-dependency-tracking
--disable-silent-rules
--enable-fast-install
econf --hates=arg
tells econf
not to supply the standard argument --arg
to the configure
script. E.g. econf --hates=docdir
. Use --hates
if a standard autoconf configure script aborts on a standard configure argument.
Don’t use econf
for custom configure scripts that don’t accept most of the standard configure arguments.
econf
automatically calls die
on failure unless called via nonfatal
.
einstall
is banned
emagicdocs
: Called by default_src_install
to install documentation. Packages that don’t use Makefiles to build can use this function to just install documentation instead of calling default_src_install
. See src_install for further documentation of the variables used below. The function looks like this:
emagicdocs() {
local done_docs old_set f d p doc e
done_docs=
old_set=$(shopt | grep 'nocaseglob[[:space:]]*on')
shopt -s nocaseglob
for d in '' "${DEFAULT_SRC_INSTALL_EXTRA_SUBDIRS[@]}" ; do
if [[ -n ${d} ]]; then
[[ -d ${d} ]] || die "${d} is not a dir"
pushd "${d}" > /dev/null || die "Failed to enter ${d}"
local docdesttree="${DOCDESTTREE}"
docinto "${d}"
fi
for f in README Change{,s,Log} AUTHORS NEWS TODO ABOUT THANKS {KNOWN_,}BUGS SUBMITTING \
HACKING FAQ CREDITS PKG-INFO HISTORY PACKAGING MAINTAINER{,S} CONTRIBUT{E,OR,ORS} RELEASE \
ANNOUNCE PORTING NOTES PROBLEMS NOTICE "${DEFAULT_SRC_INSTALL_EXTRA_DOCS[@]}"; do
for p in "${DEFAULT_SRC_INSTALL_EXTRA_PREFIXES[@]}" '' ; do
for doc in "${p}"*([[:digit:]])"${f}"{,+([._-])*} ; do
if [[ -s "${doc}" && ! -d "${doc}" ]] ; then
for e in "${DEFAULT_SRC_INSTALL_EXCLUDE[@]}" ; do
[[ ${doc} == ${e} ]] && continue 2
done
done_docs="${done_docs} ${d%/}${d:+/}${doc}"
dodoc "${doc}"
fi
done
done
done
if [[ -n ${d} ]]; then
docinto "${docdesttree}"
popd > /dev/null || die "Failed to leave ${d}"
fi
done
if [[ -n "${done_docs}" ]] ; then
echo "Installed docs ${done_docs# }"
else
echo "Didn't find any docs to install"
fi
[[ -n ${old_set} ]] || shopt -u nocaseglob
}
edo
: Convenience function to echo a command, run it, and die_unless_nonfatal
if it fails
edo()
{
echo "$@" 1>&2
"$@" || paludis_die_unless_nonfatal "$* failed" || return 247
}
exhost
: provides a querying interface for cross-compiling support
The primary use of the exhost function is intrinsically tied to the concepts involved in cross-compiling. The concepts are simplified as the mechanism does not support Canadian cross-compiled images. The --build
argument identifies the build triple, which is the host where the build is being performed. The --target
argument identifies the target triple, which is where the binaries that are generated would run. The --host
argument is provided for completeness, but is banned; the only place that the --host
argument would be useful is for canadian cross compilation.
The --tool-prefix
argument provides the prefix that should be used for tools that are being used on target specific binaries. As an example, because there may be multiple targets on the host, objdump
is ambiguous. In order to select the correct tool, you should use $(exhost --tool-prefix)objdump
.
The --is-native
argument has a second parameter of -q
or --quiet
that indicates that no output should be emitted by the invocation of this function. It is a utility argument that identifies if the target that the package is being built for is the same as the build host type.
exhost()
{
case "${1}" in
--build)
echo ${CHOST}
;;
--host)
die "${1} is banned in EAPI"
;;
--is-native)
local native=$([[ $(exhost --build) == $(exhost --target) ]] ; echo ${?})
[[ ${2} == -q || ${2} == --quiet ]] || echo ${native}
return ${native}
;;
--target)
echo ${PALUDIS_CROSS_COMPILE_HOST:-${CHOST}}
;;
--tool-prefix)
echo ${PALUDIS_CROSS_COMPILE_TOOL_PREFIX:-}
;;
*)
die "exhost subcommand ${1} unrecognised"
;;
esac
}
The --build
subcommand is useful for cases where the package being built requires building tools to run on the build host. As an example, the PAM package will build tools that will only be run during the build and not installed. In such a case, you may have to specify the compiler explicitly as: BUILD_CC=$(exhost --build)-cc
.
The --is-native
subcommand is similarly useful. Certain operations may only be necessary when building for the build host target. As an example, during the migration process, we needed to create supplementary symlinks. In such a scenario, this subcommand lets you check if you need to perform the action. if exhost --is-native -q ; then ... ; fi
.
The --target
subcommand is the most useful one. It is used to query the target that the package is currently being built for. This can be important for determining the correct location for a file or the tool use. CC=$(exhost --target)-cc
can set the compiler to use. The prefix can be calculated with this command as /usr/$(exhost --target)
.
In certain cases, a specific tool must be manually invoked. One such tool is pkg-config
. The tool prefix identifies the prefix that should be used to select the correct tool. This is important as the tool may not support working with binaries that are not built for the same target. The correct (pkg-config) tool can be invoked as $(exhost --tool-prefix)pkg-config
. The same applies to any of the tools that are used for building purposes. Note that in the case of pkg-config
, there is the alternative environment variable of ${PKG_CONFIG}
that can also be used.
use_with
is banned
use_enable
is banned
option_enable
:
option_enable()
{
if optionq "${1}" ; then
echo "--enable-${2:-$(optionfmt ${1} )}${3+=${3}}"
else
echo "--disable-${2:-$(optionfmt ${1} )}"
fi
}
For option_enable foo bar
it echoes --enable-bar
if foo
is enabled and --disable-bar
if foo
is disabled
For option_enable suboption:foo
it echoes --enable-foo
if suboption:foo
is enabled and --disable-foo
if suboption:foo
is disabled, so the suboption:
string gets cut off
For option_enable foo bar zonk
it echoes --enable-bar=zonk
if foo is enabled and --disable-bar
if foo is disabled
option_with
. Similar to option_enable
but using --with
and --without
.
export_exlib_phases
(EXPORT_FUNCTIONS
for exlibs)require
(inherit
for exlibs
). Can take parameters for each exlib enclosed in [ ]
(see exlib parameters)myexparam
, declare exlib parameterexparam
, query exlib parameterdefault
(see phases)use
is banned
usev
is banned
useq
is banned
optionfmt
: Probably not directly useful, echoes the name of the option without the foo:
for suboptions.
option
: Like optionq but additionally takes two optional arguments.
If the relevant option is enabled the first of those arguments will be printed if non-empty. Otherwise the second of those arguments will be printed if non-empty.
optionv
: Like optionq but also echo the name of the option as reported by optionfmt
if the option is enabled.
optionq
: Returns true if the option is enabled and false otherwise.
has
: Alias for hasq
.
hasv
: Like hasq but also echo the name of the first argument if found.
hasq
: Returns true if the first argument is found in the list of subsequent arguments and false otherwise.
expecting_tests
: Query whether test phases are expected to be run. This allows you to tell a configure script whether a test dependency is needed, or to disable building of tests in the compile phase if they aren’t going to run later. Takes one of the following three arguments:
--any
: Returns true if any test phase is expected to be run and false otherwise.--recommended
: Returns true if the src_test
phase is expected to be run and false otherwise.--expensive
: Returns true if the src_test_expensive
phase is expected to be run and false otherwise.--any
is the default if no arguments are specified.
Additionally takes two optional arguments. If the relevant test phase is expected to be run the first of those arguments will be printed if non-empty. Otherwise the second of those arguments will be printed if non-empty.
exdirectory
: Allow or forbid that a package installs anything in a specified directory. Must be called in pkg_setup
. Takes two arguments. exdirectory --allow /dir
allows installing in /dir
. exdirectory --forbid /dir
forbids installing in /dir
.
exlogfailure
: Tell the package manager not to remove the current build log. This is useful in the pkg_prerm
, pkg_postrm
and pkg_postinst
phases, where using die
to make an error fatal will mess up things. Use this in combination with eerror
.
expart
: Mark a file or directory as belonging to a part.
Parts must be declared in MYOPTIONS
under the special parts:
suboption. expart binaries
/usr/bin
marks everything under /usr/bin
as belonging to the binaries part. Files belonging to parts:
suboptions are only merged into the filesystem if the suboption is enabled.
expart
takes two or three arguments, and must be called in the src_install
phase. To remove a file from a part, one can exclude it by invoking expart
with the --exclude
switch (e.g. expart --exclude libraries /usr/${LIBDIR}/library.so
). Ordering of expart
invocations is important. If a file is marked as belonging to multiple parts, the last part specified takes precedence.
At this point, it is not possible to uninstall a part without reinstalling the package in question. File parts can be examined with the cave contents
command.
exsetscmrevision
: Tell the package manager the upstream scm revision of an scm package.
exvolatile
: Mark a file or symlink as volatile.
A volatile file is a generated file. Typically it is generated during pkg_postinst
, but it may change at any time. The checksum of a volatile file is irrelevant. Unless it is under config protect, it will always be removed during uninstalls to avoid leaving orphaned files. The point of marking a file as volatile is to clearly mark what package generated the file.
exvolatile
takes one or more files as arguments, and must be called during pkg_setup
. The volatile file must be created during src_install
, even if it is empty at that point. If a volatile file is a symlink, the regular file it points at must also exist during merge. A volatile symlink cannot point at an absolute path to a file.
has_version
: has_version --root
returns true if a package matching the provided dependency specification is installed in ROOT
and false otherwise. has_version --slash
looks if the package is installed in /
instead. --root
is the default but should always be specified explicitly when desired.portageq
is bannedbest_version
: Like has_version
but also prints the category, package name and version of the highest installed match.vdb_path
is bannedcheck_KV
is banneddebug-print
is banneddebug-print-function
is banneddebug-print-section
is bannedcanonicalise
: Converts argument to an absolute path without symlinks.All of the following scripts die by default upon failure. If this isn’t desired call them via nonfatal
:
dobin
: Install an executable into /usr/${CTARGET}/bindoconfd
: Install a conf.d file into /etc/conf.ddodir
: Create a given directory in ${IMAGE}dodoc
: Install documentation into /usr/share/doc/${PNVR} or a custom directory set by docinto. Dies on non-existent or empty files. -r installs recursively.doenvd
: Install env.d files into /etc/env.ddoexe
: Install executables into a custom directory set by exeintodoinfo
: Install .info filesdoinitd
: Install init.d files into /etc/init.ddoins
: Install given files into a custom directory set by insinto, -r installs recursivelydolib
: Install given libraries into /usr/${CTARGET}/libdolib.a
: Install given static libraries into /usr/${CTARGET}/libdolib.so
: Install given dynamic libraries into /usr/${CTARGET}/libdoman
: Install manual files into /usr/share/man, dies on non-existent or empty files.domo
: Install locale (.mo) files into /usr/share/localedosbin
: Banned, use dobin insteaddosym
: Create a symlink, dies if the target directory does not exist.emake
: Run make, respects MAKEOPTS
and EXJOBS
.newbin
: Install an executable under a new name into /usr/${CTARGET}/binnewconfd
: Install a conf.d file under a new name into /etc/conf.dnewdoc
: Install documentation under a new name into /usr/share/doc/${PNV}newenvd
: Install an env.d file under a new name into /etc/env.dnewexe
: Install an executable under a new name into a custom directory set by exeintonewinitd
: Install an init.d file under a new name into /etc/init.dnewins
: Install a file under a new name into a custom directory set by insintonewlib.a
: Install a static library under a new name into /usr/${CTARGET}/libnewlib.so
: Install a dynamic binary under a new name into /usr/${CTARGET}/libnewman
: Install manual files under a new name into /usr/share/mannewsbin
: Banned, use newbin insteadunpack
: Unpack archives, barfs on uncompressed unless --if-compressed
. Doesn’t fix permissions.nonfatal
, use this to make functions or scripts that die on failure by default nonfatal.
dobanned
, install a wrapper for the specified command name to BANNEDDIR
. This wrapper always exits non-zero and prints an error, thus banning the command globally from the exheres environment. Intended for packages that install ${target}
prefixed tools for exheres as well as unprefixed tools for users. E.g.: dobanned pkg-config
Note: If the command is provided by an alternative, the provider-specific name should be given to dobanned
and ${BANNEDDIR}/<alternative name>
should be added to the alternatives. E.g. dobanned pkg-config.pkgconf
and alternatives_for ... ${BANNEDDIR}/pkg-config pkg-config.pkgconf
respectively
The following here*
functions each take exactly one argument (the file name) and the contents of the file as a here document. They then use their do*
counterpart to install the file. E.g.:
src_install() {
[...]
hereenvd 44qt4 <<EOF
LDPATH=${qt4_libdirs}
EOF
[...]
}
herebin
: Installs into /usr/${CTARGET}/bin
hereconfd
: Installs into /etc/conf.d
hereenvd
: Installs into /etc/env.d
hereinitd
: Installs into /etc/init.d
hereins
: Installs into a custom directory set by insinto
heresbin
: Banned, use herebin instead
All of the following scripts are banned:
prep*
dohard
donewins
dosed
, Use edo sed
directly instead.
dohtml
ecompress*
fowners
, Use edo chown
directly instead.
fperms
, Use edo chmod
directly instead.
Not that different to eclasses yet. Can be per-category and per-package rather than global. Loaded using require
.
Functions are exported using export_exlib_phases
. It can be called more than once; a phase is exported if it is given as an argument to export_exlib_phases
at least once. If it is called, it must be after any exlib that exports the same phases is included with require
.
The metadata variables DEPENDENCIES
and MYOPTIONS
are incremental across exlibs. The values set in all required exlibs and the value set in the exheres get encapsulated in parentheses and concatenated by the package manager. The encapsulation is necessary to ensure labels in one exlib do not affect what labels apply in another exlib or the exheres.
Exlibs can take parameters.
require foo [ bar=baz blah=bleh ] monkey [ in=space ]
This requires foo.exlib
with bar=baz
and blah=bleh
parameters, and monkey.exlib
with the in=space
parameter. Exlib parameters need to be declared as early as possible in the exlib using the myexparam
function. The following three examples declare the bar
variable as a required parameter, blah
as an optional parameter that is set to bloh
if not provided and baz
as an optional parameter that is set to an empty string if not provided:
myexparam bar
myexparam blah=bloh
myexparam baz=
To access the value of an exlib parameter use the exparam
function. This takes one argument, the name of the exlib parameter, and outputs the value. It must be used only in the exlib that declares the parameter and only after it has been declared.
exparam bar
Unfortunately due to a limitation in bash and the way this functionality is implemented, using exparam in a subshell from a function that is called outside global scope will not work. So for instance this code will result in the error message “exparam is banned outside exlibs”:
foo_pkg_setup() {
var=$(exparam bar)
}
Therefore exparam has optional support for specifying a variable name to assign the value of the exlib parameter to:
foo_pkg_setup() {
exparam -v var bar
}
Exlib parameters can also be arrays. The following two examples are equivalent:
require foo [ bar=[ 1 2 "3 3" ] ]
require foo [[ bar=[[ 1 2 "3 3" ]] ]]
Allowing the latter notation makes it possible to have a regular variable with the value “[
”:
require foo [[ bar=[ ]]
Arrays must be declared via myexparam
. The following three examples declare an exlib array as required, optional with an empty default value and optional with three default elements respectively:
myexparam bar[]
myexparam bar=[ ]
myexparam bar=[ 1 2 "3 3" ]
To empty an array with a non-empty default value:
require foo [ bar=[ ] ]
With exparam you can access either the number of elements, any individual element using an index or the full array:
exparam bar[#]
exparam bar[0]
exparam bar[1]
exparam bar[*]
exparam bar[@]
exparam bar
is equivalent to exparam bar[0]
. And again the value of the array can be assigned to a new array with exparam -v array bar[@]
or of any individual element with e.g. exparam -v v3
bar[3]
.
For exlib parameters that specify a Boolean option, the standard convention is to use the values true
and false
. To support this, myexparam
takes a -b
option to specify that only those two values are permitted, and exparam
takes a -b
option to return a true or false exit status instead of outputting to stdout. exparam -b
is only permitted for parameters that were declared with myexparam -b
. For example:
myexparam -b foo
myexparam -b bar=true
if exparam -b foo; then
DEPENDENCIES+=" dev-libs/libfoo"
fi
There are three types of sandboxing:
execve()
sandboxingexecve()
calls are sandboxed only in metadata
phase. In this phase no external calls are allowed.
Path sandboxing and network sandboxing are enabled in the phases listed below:
Here’s a list of path prefixes that are allowed by default: Note: Environment variables are expanded.
prefix.write:
${CCACHE_DIR}
${PALUDIS_TMPDIR}
/var/cache
/var/tmp
/tmp
/proc/self/task
/proc/self/attr
/selinux/context
/dev/shm
/dev/pts
/dev/ptmx
/dev/tts
/dev/pty
/dev/tty
/dev/random
/dev/console
/dev/full
/dev/null
/dev/zero
/dev/stderr
/dev/stdout
/proc/self/fd
/dev/fd
Network sandboxing has two whitelists, one for bind
and one for connect
, sendto
etc. By default network sandboxing allows bind
to address 127.0.0.1/8
on ports 0 and 1024-65535. If a bind
call is successful the address is automatically added to the connect
whitelist.
The behaviour of sandboxing may be altered by using magic commands. These commands provide a simple way to interact with sydbox
. Check sydbox
manual page for the list of magic commands. Previously we used a simple wrapper function called sydboxcmd
around sydbox’ magic stat()
function. This function is now deprecated in favour of the higher level wrapper esandbox
.
Here’s a list of esandbox
commands:
esandbox check
: Check whether the program is being executed under sandboxing.esandbox enabled
or esandbox enabled_path
: Check whether path sandboxing is enabled.esandbox enabled_exec
: Check whether exec sandboxing is enabled.esandbox enable
or esandbox enable_path
: Enable path sandboxing.esandbox disable
or esandbox disable_path
: Disable path sandboxing.esandbox enable_exec
: Enable exec sandboxing.esandbox disable_exec
: Disable exec sandboxing.esandbox enable_net
: Enable network sandboxing.esandbox disable_net
: Disable network sandboxing.esandbox allow
or esandbox allow_path
: Whitelist a path for path sandboxing. Takes one extra argument which must be an absolute path.esandbox disallow
or esandbox disallow_path
: Removes a path from the path sandboxing whitelist. Takes one extra argument which must be an absolute path.esandbox allow_exec
: Whitelist a path for execve()
sandboxing. Takes one extra argument which must be an absolute path.esandbox disallow_exec
: Removes a path from the execve()
sandboxing whitelist. Takes one extra argument which must be an absolute path.esandbox allow_net
: Whitelist a network address for bind()
whitelist - or for connect()
whitelist if –connect option is given.esandbox disallow_net
: Removes a network address from the bind()
whitelist - or from connect()
whitelist if –connect option is given.esandbox addfilter
or esandbox addfilter_path
: Add a pattern as a path sandboxing filter. Takes one extra argument which is a fnmatch()
pattern.esandbox rmfilter
or esandbox rmfilter_path
: Removes a pattern from the path sandboxing filter list. Takes one extra argument which is a fnmatch()
pattern.esandbox addfilter_exec
: Add a pattern as a execve()
sandboxing filter. Takes one extra argument which is a fnmatch()
pattern.esandbox rmfilter_exec
: Removes a pattern from the execve()
sandboxing filter list. Takes one extra argument which is a fnmatch()
pattern.esandbox addfilter_net
: Add a network address as a network sandboxing filter. Takes one extra argument which is a network address.esandbox rmfilter_net
: Removes a pattern from the network sandboxing filter list. Takes one extra argument which is a network address.esandbox lock
: Lock magic commands. After calling this none of the esandbox
commands will work. You don’t need to call this, see exec_lock
.esandbox exec_lock
: Lock magic commands upon execve()
. This is the default for phases other than metadata
thus you don’t need to call this command from exhereses.esandbox wait_eldest
: By default, sydbox waits for all traced processes to exit before exiting. However, this isn’t desired in some cases. For example when a daemon, like udev, is restarted from within an exheres which will go on its execution after installation. This command makes sydbox resume all processes and exit after the eldest process has exited.esandbox wait_all
: Wait for all processes before exiting. This is the default.esandbox nohack_toolong
: Sydbox tries hard to workaround problems regarding too long paths. However, this isn’t desired in some cases where these hacks increase the execution time considerably. This command disables sydbox’ hacks for too long paths.esandbox hack_toolong
: This enables sydbox’ hacks for too long paths.Network addresses may be specified in the following forms:
where /NETMASK can be omitted and PORT_RANGE can either be a number or two numbers in the form BEGIN-END. In addition, there are a few network aliases that are expanded to network addresses. They are listed below:
So you may use LOOPBACK@0 instead of inet:127.0.0.0/8@0
sydboxcmd
: Use the appropriate esandbox
command insteadsydboxcheck
: Use esandbox check
insteadaddwrite
: Use esandbox allow
insteadrmwrite
: Use esandbox disallow
insteadaddfilter
: Use esandbox addfilter
insteadrmfilter
: Use esandbox rmfilter
insteadInstall and use editor plugins for exhereses, as they will apply most formatting rules
Use four spaces for indents, no tabs.
DEPENDENCIES should be sorted as follows:
dependency label
hard dependencies before optional dependencies
alphabetically
optional dependencies alphabetically based on the option name
DEPENDENCIES="
build:
dev-util/pkg-config
test:
dev-libs/testit
test-expensive:
dev-libs/testitevenmore
build+run:
dev-libs/foolib
sys-libs/zlib
alsa? ( sys-sound/alsa-utils )
pcre? ( dev-libs/pcre )
run:
sys-apps/eject
post:
sys-apps/frozbinizer
recommendation:
net-apps/quuxifyer
suggestion:
net-apps/bar
"
This makes it easier on human eyes to check a certain dependency.
Exhereses and exlibs must end with a single blank line.
Copyright goes to you, but you need to GPL v2 it if it goes in the tree. For stuff you wrote from scratch:
# Copyright 2008 Ciaran McCreesh
# Distributed under the terms of the GNU General Public License v2
If you make large changes to an exheres:
# Copyright 2007, 2008 Ciaran McCreesh
# Copyright 2008 Ivan Toby Rich
# Distributed under the terms of the GNU General Public License v2
If you rip off another non-trivial exheres:
# Copyright 2008 Ivan Toby Rich
# Distributed under the terms of the GNU General Public License v2
# Based in part upon 'foo-1.23.exheres-0', which is:
# Copyright 2008 Ciaran McCreesh
Basing your work upon ebuilds
is fine, but if you did, make sure you include the Gentoo copyright notice. This applies even if you read the ebuilds for inspiration – unless you have a lawyer handy to tell you exactly what does or does not count as a derived work, it’s easiest to assume that if you looked at the ebuilds then it’s derived (not because it necessarily is, but because doing so imposes no additional restrictions, whereas not doing so gives certain Gentoo people with nothing better to do an opportunity to make nuisances of themselves). So then you need do this:
# Copyright 2008 Ciaran McCreesh
# Distributed under the terms of the GNU General Public License v2
# Based in part upon 'foo-1.23.ebuild' from Gentoo, which is:
# Copyright 1999-2007 Gentoo Foundation
All attempts should be made to keep the package as close to the upstream version as possible. In general, patches for compilation and runtime errors are okay. However, patches that introduce new features are discouraged, unless they are part of the upstream release cycle. Patches that alter external interfaces are particularly problematic. It is unacceptable to believe that it is sufficient to patch packages in our repository for such a change as this makes life harder for users who want to use packages that are not in our repositories. In the case that a patch is needed it must contain a header with the following information:
Source: written by, from distribution, etc
Upstream: patch status, bug number, etc
Reason: reason for the patch
This allows for others (or yourself), who may work with the package in the future, to be able to determine why a specific patch was applied. In the case that a patch no longer applies, the header aids in determining what to do with the patch (port it, discard it, etc.).
If there is active upstream development, it is highly recommended that patches be passed along to them so that they may incorporate the fix in the next release. This is beneficial for both parties. Bugs in the upstream project are caught and fixed, and it reduces the effort required downstream to track and fix the bug with every release. Note: Contributed patches are often rejected if they are not reported upstream for that reason. Please note in the upstream line if the patch is applied by upstream. In the case of several branches it could also be helpful to note the branch in which the patch is applied.
In the case of git format-patch
-style patches, the Source:
and Reason:
lines may be left out if the commit message is expressive enough and if it is obvious where the patch originated. If that is not the case, the relevant parts have to be included in the patch header.
Packages should provide user options where reasonable and useful, but it is not necessary to spend excessive effort to support every obscure little tweak. Users can write their own custom exheres if they want these, although this should not require them to alter packages other than the ones they want to customise. In other words, if you make a definite decision instead of providing an option, avoid making other packages rely on that decision whenever reasonably possible.
providers
is a suboption for the specific case when the same feature is provided by two or more similar packages.
<topic> provider
is a nice default)[[ number-selected = at-least-one ]]
Here is a example package (dvd+rw-tools) using providers:
# Copyright 2008 Ingmar Vanhassel <ingmar@exherbo.org>
# Distributed under the terms of the GNU General Public License v2
SUMMARY="A frontend to mkisofs to facilitate mastering Blu-ray Disc and DVD media, both +RW/+R and -R[W]"
HOMEPAGE="http://fy.chalmers.se/~appro/linux/DVD+RW/"
DOWNLOADS="${HOMEPAGE}/tools/${PNV}.tar.gz"
LICENCES="GPL-2"
SLOT="0"
PLATFORMS="~amd64 ~x86"
MYOPTIONS="
( providers:
cdrtools
cdrkit
) [[
*description = [ ISOfs manipulation tools provider ]
number-selected = at-least-one
]]
"
DEPENDENCIES="
build:
sys-devel/m4
run:
providers:cdrtools? ( app-cdr/cdrtools )
providers:cdrkit? ( app-cdr/cdrkit )
"
[...]
More in-depth documentation on providers, their relationship with virtuals, and criteria for what constitutes a package being virtual can be found on the Providers and Virtuals doc.
Virtuals are packages without contents. Their sole purpose is to list providers of the exact same feature to ease specifying dependencies in packages requiring said feature. They rely entirely on the providers
suboption.
Organisational rules for adding new virtuals:
Some specific packaging rules apply to virtuals:
DOWNLOADS
should not be specifiedHOMEPAGE
should point to a document describing the provided feature or be emptySUMMARY
should be of the form Virtual: <topic> providers
build+run
dependencies labelHere is an example virtual (notification-daemon) for Freedesktop notifications providers:
# Copyright 2009 Mike Kelly
# Copyright 2014 Quentin "Sardem FF7" Glidic <sardemff7@exherbo.org>
# Distributed under the terms of the GNU General Public License v2
SUMMARY="Virtual: Freedesktop notifications providers"
HOMEPAGE=""
SLOT="0"
PLATFORMS="~amd64 ~x86"
MYOPTIONS="
( providers:
notification-daemon
notify-osd
dunst
eventd
awesome
notification-daemon-xfce
gnome-shell
kde-runtime
) [[
*description = [ Freedesktop notifications provider ]
number-selected = at-least-one
]]
"
DEPENDENCIES="
providers:notification-daemon? ( x11-apps/notification-daemon )
providers:notify-osd? ( x11-apps/notify-osd )
providers:dunst? ( x11-apps/dunst )
providers:eventd? ( net/eventd[dbus] )
providers:awesome? ( x11-wm/awesome[>=3.1] [[ description = [ with the naughty library ] ]] )
providers:notification-daemon-xfce? ( xfce-extra/notification-daemon-xfce )
providers:gnome-shell? ( gnome-desktop/gnome-shell )
providers:kde-runtime? ( kde/kde-runtime [[ description = [ with knotify ] ]] )
"
Organisational rules for adding new alternatives:
Sometimes, a package needs to be renamed (most likely because upstream changed its name). Here is what you should do:
Add the package with the new name and bump its version if needed in the same commit. Do not use blockers for this purpose.
Look if this package has any dependents and update them to use the new package. To do so, you can either search through SUMMER or setup a cave environment. The latter is more accurate and recommended if your package has a lot of dependents.
Write a news item to let users know about the change. A skeleton for such purpose is available here
You can now bury the old package
If a package should be moved from one repository to another, it’s important to also import any prior package related git actions (history) of that package. This is because commit messages often explain why certain changes have been made. Also, the history itself is of interest. To do this you have to first extract the history in patch format and import those patches via the usual procedure by using git-am.
cd /path/to/current_repository
git log --pretty=email --patch-with-stat --reverse -- path/to/package | (cd /path/to/new_repository && git am)
If you want to mantain a previously buried package you should in order:
Import the exheres and all its history by following the guide to move a package from one repository to another.
Make a merge request to the graveyard repository in which you remove the lines relevant to the package you want to revive in the respective .graveyard file. See previous commits in the graveyard repo for examples.
Copyright 2008, 2009 Ciaran McCreesh
Copyright 2008-2015 Bo Ørsted Andresen
Copyright 2011 Ali Polatel
Copyright 2015 Saleem Abdulrasool