My paludis hooks and addons
Short Intro
In my paludis-hooks repo I’m trying to accumulate everything
I’ve done to survive w/ for paludis – The Other Package Manager™.
Yep, initially there was only hooks, but later I’ve
added some other helpful things, I’m using for awhile… so probably the repo should be renamed.
Personally I like hooks, cuz that facility, out of the box, turns paludis
into a really flexible package manager
and thanks to them, feature like autopatch works much more better (and reliably) than the
same feature of
emerge
became available long time after.
To install all that stuff, here is a
ebuild
in my overlay. And yes, that scm
is the only version nowadays ;-) cuz I’m permanently doing some improvements
w/o any release plan.
NOTE: To use it w/ Python 3 as a default interpreter make sure you have an appropriate paludis version installed.
Things in Details
Autopatch Hook
One of my first hooks inspired by an already dead repo of paludis’ hooks, I’ve found soon after migrated to
paludis. That was one from a bunch of reasons to forget about emerge
– a really easy way to apply my patches
for broken packages w/o “writing” a my own ebuild and put it to my repo.
The idea is simple and straightforward: at any desired stage of ebuild processing apply some user provided patches
placed into a some special place (configurable via /etc/paludis/hooks/configs/auto-patch.conf
).
To apply a patch one have to put it into a directory under ${PATCH_DIR}/stage/category/pkgname-with-ver/
or to ${PATCH_DIR}/stage/category/pkgname/
, so you don’t need to create a new directory (or symlink a previous
pkg-spec-with-ver
) when package version has bumped. Where the stage
is one of the following:
ebuild_compile_post
, ebuild_compile_pre
, ebuild_configure_post
, ebuild_configure_pre
, ebuild_install_pre
or ebuild_unpack_post
.
Recently I’ve killed all out of date patches from my local vault and made it
public. For example w/o a patch cmake
won’t colorize its
output even if color explicitly requested when running w/ captured output. So to allow my
Pluggable Output Processor works w/o suppressing colors of CMake I have
/var/db/paludis/autopatches/ebuild_unpack_post/dev-utils/cmake/cmake-3.0.0-do-not-check-isatty.patch
.
Filesystem Hook
This plugin can be used to make some manipulations in a package’s image, right after make install
and before it will be actually merged into the system. Particularly I use it to make a permanent
symlinks to a documentation for some packages I use in my work or to prevent undesired files to be installed
(which is far better than ugly INSTALL_MASK
).
Every action to apply described in terms of XML items of the configuration file
/etc/paludis/hooks/configs/filesystem-manager.conf
, where the root element is commands
.
A commands container consists of package
elements which must have at least the spec
attribute of a package
to apply actions for. The other attributes are stop
, with boolean true
/false
value to disable/enable
further processing, if a given rule matched, and the descr
attribute with a human readable action description.
The package’s spec
attribute specify the order how actions are matched and applied:
priority | spec |
---|---|
16 | cat/package-ver-rv:slot::repo |
15 | cat/package-ver-rv:slot |
14 | cat/package-ver-rv::repo |
13 | cat/package-ver-rv |
12 | cat/package:slot::repo |
11 | cat/package:slot |
10 | cat/package::repo |
9 | cat/package |
priority | spec |
---|---|
8 | package-ver-rv:slot::repo |
7 | package-ver-rv:slot |
6 | package-ver-rv::repo |
5 | package-ver-rv |
4 | package:slot::repo |
3 | package:slot |
2 | package::repo |
1 | cat/* |
0 | */* |
There are few children tags possible under the package
element:
symlink
– used to create a symlink and has attributes:cd
– change to this directory before making a symlinksrc
– source for the symlinkdst
– destination of the symlink
mv
– used to move or rename something in the image.cd
– set a working directory to thissrc
– source file or directory namedst
– destination path/name
rm
– used to remove something from the image, so it will not be installed at all.dst
– what to removereverse
– optional attribute to specify that command should remove everything except selected target(s)
if
– used to check some (limited nowadays) constraints and execute nested actions if latter istrue
use
– the only mandatory attribute nowadays to check if givenUSE
flag is turned on for matched packagenegate
– boolean attribute to negate result of a use check
mkdir
– used to create a new directorycd
– change to this directory before doing anythingdst
– the name of the directory to create
Paths in a rule may refer to shell variables like P
, PN
, PF
, PV
, PVR
, as well as others,
declared by PMS.
Note, that all absolute paths are refer to the package’s image directory and not to the “real” filesystem.
Examples
Make permanent symlinks to documentation
This was an initial motivation to write this hook: I use the firefox
to view a documentation to various packages.
Documentation for =dev-lib/boost-1.54
, for example, will be installed to the /usr/share/doc/boost-1.54
.
Firefox will remember that location and next time shows me hints (in a popup) with the most visited pages, when I
type something in a location bar. Unfortunately after upgrade to =dev-libs/boost-1.55-r1
path to documentation
obviously will be changed and that hints will not work without fixing. The second problem with that:
I have to remember an exact package version with a ebuild’s revision number and should type it in a location bar a
long time until firefox realized that visits count of some 1.55-r1
page is greater than same, but with 1.54
in the path, and will offer it instead. Except boost
, I’ve got about 10 more packages w/ USE=doc
flag enabled
and I don’t want to remember all versions and revisions I currently have in my system… and bookmarks in
firefox can’t help much in this case!
The solution is to make a “permanent” symbolic link which will stay the same for any version installed.
Moreover it can be a little shorter :-) So instead of /usr/share/doc/boost-1.55.0-r1/html/index.html
I have
/usr/share/doc/boost/index.html
as a hint in a location bar and don’t care about particular version installed.
To achieve that I’ve added a simple rule to my config:
<package spec="dev-libs/boost">
<symlink cd="/usr/share/doc" src="${PF}/html" dst="${PN}" />
</package>
So, this rule will change current directory to /usr/share/doc
inside an image directory and create
a symbolic link boost
pointing to boost-1.55-r1/html/
.
Remove unused translations/locales
I have */* -nls
and LUNGUAS: -*
in my /etc/paludis/use.conf
, but some packages just don’t have that USE flag,
but install localizations anyway (yep, cuz ebuild authors just lazy ppl… most of the time).
So app-admin/localpurge
was “invented” to cleanup unused locales (all of them in my case). But localepurge
will remove *.mo
files after install, so when a package gets uninstalled, some files will be marked as gone.
One simple rule will do the job better:
<package spec="*/*" descr="locale-cleaner">
<rm cd="/usr/share/locale/" dst="*/LC_MESSAGES/*.mo" />
</package>
Because manipulations (deleting *.mo
files) will be done before merge, all that files even
won’t be counted by a package manager. And I’m not telling about that you don’t need to run any tool periodically
(or via cron
) – all your packages will be already clean w/o any manual actions required :)
Translations is a part of the “problem”: some packages (like alsa-utils
) want to install translated manual pages
as well. To remove them (everything except English) one may use the following rule:
<package spec="*/*" descr="man-pages-cleaner">
<rm cd="/usr/share/man/" dst="man{0p,1,1p,2,3,3p,4,5,6,7,8}" reverse="true" />
</package>
Note the attribute reverse
tells to the hook that everything except specified items (directories actually)
should be removed.
Other usage examples can be found
here.
They are mostly targeted to remove unused/redundant/useless files installed by various packages to
the /usr/share/doc
and some other places.
Even more extreme rule
Recently I’ve added one more element: if
– to check if a matched package has some desired USE
flag turned on.
Nowadays I have the following extreme rule in my config:
<package spec="*/*" descr="USE=-doc remover">
<if use="doc" negate="true">
<rm cd="/usr/share" dst="doc" />
</if>
</package>
Attention
This rule will prevent to install any files to the /usr/share/doc/
from all packages,
which do not have USE=doc
enabled!
Unfortunately some packages, I want docs for, do not have that USE
at all, so to stop this rule triggering,
I’ve got a bunch of stoppers like this:
<package spec="clang-docs" stop="true" />
<package spec="python-docs" stop="true" />
<package spec="valgrind" stop="true" />
Working Directory in a RAM
Some users have a paludis woking directory mounted to a tmpfs
. The big problem w/ this solution:
some packages are too fat to be build in a RAM. Then to build them one have to umount
selected location
temporarily to build that packages. workdir-tmpfs
hook is designed to solve that “problem”.
This hook record a disk space usage while a package gets build and the next time will try to move
the working directory to the /dev/shm
(providing a symbolic link to the original location) if there
is enough space. Disk usage stats will be recorded only if a package builds successful.
To move a working directory to a RAM disk it should have enough space: previously collected value plus
some reserved space. Basically amount of bytes to reserve is a 10% of the stored value.
Default configuration file location is /etc/paludis/hooks/configs/workdir-tmpfs.conf
.
The hook’s configuration has the following default values:
MIN_RESERVED_SPACE=$(( 1024 * 1024 * 10 ))
MAX_RESERVED_SPACE=$(( 1024 * 1024 * 100 ))
DISK_USAGE_STATS_CACHE="/var/cache/paludis/disk_usage_stats.cache"
MIN_RESERVED_SPACE
is a value to be used as an amount of a reserved space if 10% of a stored disk usage
counter is less than it. The MAX_RESERVED_SPACE
is an upper bound of that 10% – i.e. max reserved space
can not exceed it. Defaults are 10M and 100M correspondingly.
Note
If some package fails to build, its working directory will be moved back to its original location
from the RAM disk (i.e. /dev/shm
)…
Manage Build Environments
This feature is not a hook actually, but some add-on to be used from the /etc/paludis/bashrc
.
It allows to manage compiler flags (as well as any other environments variables) on a per package basis,
like it is possible in the portage via the package.env
file.
To use it, one have to add the following to the /etc/paludis/bashrc
somewhere after the CFLAGS
and/or other definitions.
[ -e /usr/libexec/paludis-hooks/setup_pkg_env.bash ] && . /usr/libexec/paludis-hooks/setup_pkg_env.bash
Now you can edit the /etc/paludis/package_env.conf
to specify how environment should be changed to compile
any particular package. For example, I have somethig like
this:
#
# My per package environment settings
#
sys-devel/binutils binutils-extras
dev-lang/python extra-optimize
dev-db/sqlite extra-optimize
sys-apps/paludis extra-optimize
sys-libs/db use-bfd-linker
app-emulation/virtualbox no-gc-sections use-bfd-linker
media-libs/alsa-lib no-gc-sections
sys-devel/glibc no-gc-sections
x11-libs/cairo no-gc-sections
net-libs/webkit-gtk no-debug
www-client/firefox no-debug
Every line has a package spec and a space separated list of environment modifiers. They would be applied in the same order
as specified in the config. Every modifier actually is a file from the /etc/paludis/env.conf.d/
.
In that file (an ordinal bash script actually to be sourced if a package name matched) defined some actions to modify
CFLAGS
, LDFLAGS
or anything else you want. For example in
/etc/paludis/bashrc
I have the following definition for LDFLAGS
:
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,--enable-new-dtags -Wl,--gc-sections -Wl,--hash-style=gnu"
Unfortunately, not all packages can link with --gc-sections
option. For example app-emulation/virtualbox
.
It is why this package have no-gc-sections
environment in my package_env.conf
. You may use all functions provided by
[flag-o-matic.eclass](https://devmanual.gentoo.org/eclass-reference/flag-o-matic.eclass/index.html) to manupulate
compiler/linker flags! Here is mine
/etc/paludis/env.conf.d/no-gc-sections.conf` for example:
einfo "Remove --gc-sections from linker flags"
filter-ldflags -Wl,--gc-sections
Yes, you can use logging functions as well ;-) The last command will remove undesired option from default
(“global”) LDFLAGS
. Unfortunately app-emulation/virtualbox
also fails to build if default linker is ld.gold
.
The second environment (use-bfd-linker
) tells to use ld.bfd
to link that package:
if [ "bfd" != "$(readlink -f `which ld` | sed 's,.*\.\(bfd$\),\1,')" ]; then
einfo "Use ld.bfd linker"
append-ldflags -Wl,-fuse-ld=bfd
fi
Also there is a buch of other helper functions provided – you may check
my paludis configuration
for inspiration. Being an ordinal bash script one may use any other programs, sed
for example, to modify environment
and/or build flags for particular package.
New cave
Subcommand
This package also add a “new” subcommand cave print-ebuild-path <spec>
which just prints a full path to the
ebuild according a given spec
.
zaufi@gentop〉~〉 cave print-ebuild-path firefox
/usr/portage/www-client/firefox/firefox-26.0.ebuild
zaufi@gentop〉~〉 cave print-ebuild-path '<www-client/firefox-26.0'
/usr/portage/www-client/firefox/firefox-24.2.0.ebuild
zaufi@gentop〉~〉 cave print-ebuild-path paludis-hooks
/var/db/paludis/repositories/zaufi-overlay/sys-apps/paludis-hooks/paludis-hooks-scm.ebuild
This command (mostly) introduced for further scripts.
Short Aliases and Some Other Helpers
I use the following short aliases for the cave
subcommands:
alias cs='cave search --index ${CAVE_SEARCH_INDEX}'
alias cm='cave manage-search-index --create ${CAVE_SEARCH_INDEX}'
alias cc='cave contents'
alias cr='cave resolve'
alias crz='cave resolve ${CAVE_RESUME_FILE_OPT}'
alias cw='cave show'
alias co='cave owner'
alias cu='cave uninstall'
alias cy='cave sync'
alias cz='cave resume -Cs ${CAVE_RESUME_FILE_OPT}'
alias world-up='cave resolve ${CAVE_RESUME_FILE_OPT} -c -km -Km -Cs -P "*/*" -Si -Rn world'
alias system-up='cave resolve ${CAVE_RESUME_FILE_OPT} -c -km -Km -Cs -P "*/*" -Si -Rn system'
Variables CAVE_SEARCH_INDEX
and CAVE_RESUME_FILE_OPT
are defined in /etc/env.d/90cave
file.
Also here some trick used to reintroduce bash completions for all that commands, so even if alias is used
completions are still available.
Note that -km
and -Km
options are used. So when gentoo team adds
some changes to ebuild w/o version bump, that options will add a target to rebuild. To show differences
between ebuilds of installed package and just changed (and added as a target to rebuild on world-up
“command”) one may use pkg_meta_diff <pkg-name>
command.
To show differences between installed and the next best available ebuilds use pkg_ebuild_diff <pkg-name>
.
Also here is a couple of functions to use: ebuild_for
– to get a path of the ebuild according a
given spec and show_ebuild_for
to less
it…
See Also
- repository w/ my paludis configuration. Note, that it has various branches for my hardware.