SliTaz receipts v2
Version 2 was developed as an extension of the receipts in order to facilitate the maintenance of packages by small forces. Back to the Cookutils documentation.
- Main and split packages
- Long descriptions
- Converting a v1 receipt: checklist
post_install()and friends- Function
copy() - Compiling sets
- Dependency tracking
Main and split packages
In order to switch to version 2, you must specify 'v2' in the first line of the receipt:
# SliTaz package receipt v2.
You can write a single receipt v2 to compile, for example the
attr sources and then make two packages: attr
and attr-dev using the compiled files. Next we will call
attr the main package, while attr-dev
the split package.
You must specify all the names of split packages that must be
created after the compilation in the SPLIT variable. Example for our
attr receipt:
SPLIT="attr-dev"
You must specify rules to generate each package inside genpkg_rules().
Example for package attr:
genpkg_rules() {
case $PACKAGE in
attr) copy @std ;;
attr-dev) copy @dev ;;
esac
}
Here, in every rule you can:
- use the
copy()function or other methods to copy specified files from$installto$fs. - define the DEPENDS variable for specified packages; you may omit
this definition, then it will mean the following:
- for the main package: it doesn't depend on any package;
- for a split package: it depends exclusively on the main package;
- for a
*-devsplit package: it depends on the main package and on all the other split packages.
DEPENDS=""in a split rule means "no dependencies" (cookutils >= 4.22; the oldDEPENDS=" "trick still works). - know that split packages do NOT inherit the root-level
DEPENDS,TAGS,CONFIG_FILES,PROVIDE,SUGGESTED,DATABASE_FILESandTAZPANEL_DAEMONof the receipt (cookutils >= 4.22): set them in the split rule when needed.CATEGORYandSHORT_DESCare inherited, override them (or useCAT) for-lang,-doc... packages. - define the two-in-one CAT variable for split packages.
Variable format:
CAT="category|addition"
Wherecategoryis just the chosen category for the specified split package. Andadditionyou will find in the brackets at the end of a short description of the specified split package. You may omit this definition for the "dev" packages. In this case it will be implicitly defined as:CAT="development|development files"
- define some other variables, like COOKOPTS.
Long descriptions
You may provide a description.txt for the main
package and/or description.package-name.txt for any of
the split packages.
Converting a v1 receipt: checklist
A v1 package with splits has one directory per package
(foo/, foo-dev/ with WANTED="foo"...).
Merging them into one v2 receipt went wrong in the same few ways many
times (September 2026), check each point:
- Line 1 is
# SliTaz package receipt v2.-- withoutv2, cook ignoresSPLITand only the main package is built (pan, sylpheed, gpxe). - Every split is listed in
SPLIT(not twice) and has its branch in thecase "$PACKAGE" inofgenpkg_rules(); the main package branch has the exact main package name (afoo-dev)branch written twice leftxfprintempty). - Every branch ends with
;;, and runsh -n receiptbefore committing. One receipt with a syntax error kills the cooker's architecture database: every package after it in alphabetical order is silently skipped on marmite ("Cooker arch : skip ..." inlog/commits.log). - Each new branch copies everything the old split receipt copied.
copy @devdoes not take extra dirs such as/usr/share/apr-1(build rules),/usr/share/idlor tools inbin/: add them (copy @dev idl/). Read theChanges since ...: files : +N -Mblock of the cook log, every-line is a file no package ships any more. - The main package keeps what it shipped before: a
copy *.so*orcook_copy_files *.so.*line is easy to lose (net-snmp shipped no library). - DEPENDS, CONFIG_FILES, TAGS... are set in the split rule that needs them (splits do not inherit them, see above).
- Install/remove functions of the main package get the
_<main>suffix (see below). - Paths to annex files use
$stuff, notstuff/: in v2 all the packages share the main packagestuff/directory (cp -a stuff/*shipped the patches into QtDesigner). - Remove the old split directories in the same commit.
post_install() and friends
You may define one of the following functions:
pre_install();post_install();pre_remove();post_remove().
These functions may be defined for every one of main or
split packages, so you need to extend function names with an
underscore (_) and the package name. Like this for the
cookutils package:
post_install_cookutils()
Attention! You should know that some characters that are valid in
package names are not allowed in function names. Please, substitute each
symbol that doesn't belong to the intervals A-Z, a-z, 0-9 by
yet another underscore (_). Example for
coreutils-disk:
post_install_coreutils_disk()
Cook copies post_install_cookutils() into the
cookutils package only, renamed post_install():
tazpkg and spk only ever see the standard names.
Attention! A function WITHOUT the suffix (plain
post_install()) is copied into EVERY package of the receipt,
-dev, -lang and -doc included, with
$PACKAGE set to that split. When converting a v1 receipt,
rename the old install/remove functions of the main package with its
suffix, or else:
apache-devran theapachepost_install, which reconfigures every package using/etc/apache/conf.d-- apache and apache-dev reconfigured each other forever;- removing
openvpn-docranrm -rf /etc/openvpn; - removing
pam-devremovedbusybox-pam.
A typo in the name (post_removel_...) is silently ignored:
the function is never copied.
To keep the plain function out of one package, add a line starting with
no_post_install_<name> (or no_pre_install_,
no_post_remove_, no_pre_remove_) to the receipt,
for example
no_post_install_linux_libre_source="no modules are installed":
cook then copies no such function into that package.
Function copy()
It's the flexible tool allowing you to copy files and folders from
$install to $fs using patterns. All files are
copied with the folder structure preserved:
$install/my/folder/ -> $fs/my/folder/ $install/my/system/file -> $fs/my/system/file
copy() understands 4 main forms of patterns:
@std- all the "standard" files;@dev- all the "developer" files;folder/- append folder name in question by slash;file- file name without the slash at the end.
Both patterns @std and @dev are meta-patterns
making the most common actions extremely simple. Here all files are
divided into three types: standard, development and all the others
(documentation, translations, etc). You may put @std into
the "standard" package, @dev into the "developer" package,
not packaging any documentation, man pages, translations, BASH
completion, etc...
In the folder/ and file forms of the patterns
you can use the asterisk (*) symbol meaning any number of
any characters.
Some examples (executed in the chroot with the "busybox" package installed):
| Pattern | Result |
|---|---|
bin/ |
/bin/usr/bin |
*bin/ |
/bin/sbin/usr/bin/usr/sbin/var/www/cgi-bin |
/usr/bin/ |
/usr/bin |
usr/bin/ |
/usr/bin |
r/bin/ |
(nothing) |
cat |
/bin/cat |
*.sh |
/lib/libtaz.sh/sbin/mktazdevs.sh/usr/bin/gettext.sh/usr/bin/httpd_helper.sh/usr/lib/slitaz/httphelper.sh/usr/lib/slitaz/libpkg.sh/var/www/cgi-bin/cgi-env.sh |
pt* |
/dev/pts/usr/share/locale/pt_BR/usr/share/locale/pt_BR/LC_MESSAGES |
/bin/*.sh |
/usr/bin/gettext.sh/usr/bin/httpd_helper.sh |
/lib/*.sh |
/lib/libtaz.sh/usr/lib/slitaz/httphelper.sh/usr/lib/slitaz/libpkg.sh |
Additional patterns for copy():
@rm- quick alias for theremove_already_packedfunction: remove from the current package the copied files that were already packed in any of the previously packed packages (within the current receipt);@ico- remove all the copied hicolor icons (if any) and copy only the 16px and 48px variants of hicolor icons;@rubyand@ruby-dev- the mandatory files and the development files of a Ruby gem.
Some more examples of using copy()
If your packages are used only for development purposes (like automake, flex, vala and some others), you may use the next command to put all the files you want to pack into one package:
copy @std @dev
In most cases, the package breaks up into "main" and "dev" packages. In this case, your code might look like this:
PACKAGE="my-package"
SPLIT="my-package-dev"
genpkg_rules() {
case $PACKAGE in
my-package)
copy @std
DEPENDS="your-package"
;;
*-dev)
copy @dev
;;
esac
}
In the following example, a package can contain libraries (which can be
used by other programs) and executables that use these libraries. We
need to split @std into two parts: libraries and executable
files. This can be done in a few ways.
PACKAGE="my-pkg"
# We omit "my-pkg" in the $SPLIT, then it is implicit in the first place
SPLIT="my-pkg-bin my-pkg-dev"
genpkg_rules() {
case $PACKAGE in
my-pkg) copy *.so*;; # (1) copy all the libs
*-bin) copy bin/;; # (2) copy all the execs from /usr/bin/
*-dev) copy @dev;; # (3) copy development files
esac
}
# If a package contains some more files outside of the /bin/ (for example,
# configs), that we want to pack with the "bin" package:
PACKAGE="my-pkg"
SPLIT="my-pkg-bin my-pkg-dev"
genpkg_rules() {
case $PACKAGE in
my-pkg) copy *.so*;; # (1) copy all the libs
*-bin) copy @std @rm;; # (2) copy standard (binaries and configs, etc),
# then remove already packed (libs)
*-dev) copy @dev;; # (3) copy development files
esac
}
# Pack two different libraries into two packages, and the rest into a third
# package:
PACKAGE="my-pkg"
# We explicitly specify all the packages, therefore they will be processed
# in the specified order
SPLIT="my-pkg-lib1 my-pkg-lib2 my-pkg my-pkg-dev"
genpkg_rules() {
case $PACKAGE in
*-lib1) copy lib-cli.so*;; # (1) copy first libraries
*-lib2) copy lib-gui.so*;; # (2) copy second libraries
my-pkg) copy @std @rm;; # (3) copy all the standard files,
# then remove already packed (libs)
*-dev) copy @dev;; # (4) copy development files
esac
}
Compiling sets
Sometimes you may need to compile the same source code of the same version, but with different options. For example, without PAM support and with PAM support. Or with support for GTK+2 or GTK+3. Or a complete package with all the rich features and a small limited package. You can not limit yourself in the number of options.
A compiling set is a pair of separate $src and
$install folders. You can still compile the sources using the
$src variable and install compiled files into the folder
defined by the $install variable, but these values will be
different for the different compiling sets.
A set is defined by its name, which is a simple mnemonic made up of one or more letters or numbers. It may be "1", "2", "z", or something more meaningful like "pam", "gtk2", or "gtk3".
Also you should know that the default set with the empty name always exists for backward compatibility and for the cases when you don't want to use the sets.
How to use the sets?
First, you should define which set you want to use for each package
appending package names in the $SPLIT variable. You don't
have to do it for the default set with the empty name. A few examples:
PACKAGE="fuse-emulator" SPLIT="fuse-emulator-gtk3:gtk3"
PACKAGE="yad" SPLIT="yad-html:html yad-gtk3:gtk3"
PACKAGE="urxvt" SPLIT="urxvt-full:full"
Second, the function compile_rules() will be executed
sequentially for the default set and then for all the sets you mention in
the $SPLIT variable on the previous step. You should put the
business logic inside the compile_rules() function to
compile and install different variants based on the value of the
$SET variable. This variable has an empty value for the
default set and the set name in other cases. A few examples of how you
do the job:
PACKAGE="fuse-emulator"
SPLIT="fuse-emulator-gtk3:gtk3"
compile_rules() {
SET_ARGS=''; [ -z "$SET" ] && SET_ARGS='--disable-gtk3'
./configure \
--enable-desktop-integration \
$SET_ARGS \
$CONFIGURE_ARGS &&
make && make install
}
PACKAGE="urxvt"
SPLIT="urxvt-full:full"
compile_rules() {
case $SET in
'')
./configure \
--disable-everything \
$CONFIGURE_ARGS &&
make && make install
;;
full)
./configure \
--enable-everything \
--enable-256-color \
--with-terminfo=/usr/share/terminfo \
$CONFIGURE_ARGS &&
make && make install || return 1
R="$install/usr/share/terminfo"
mkdir -p $R
tic -s -o $R $src/doc/etc/rxvt-unicode.terminfo
;;
esac
}
PACKAGE="yad"
SPLIT="yad-html:html yad-gtk3:gtk3"
compile_rules() {
case $SET in
'') Gtk=gtk2; Html=disable;;
html) Gtk=gtk2; Html=enable ;;
gtk3) Gtk=gtk3; Html=disable;;
esac
./configure \
--enable-icon-browser \
--with-gtk=$Gtk \
--$Html-html \
$CONFIGURE_ARGS &&
make &&
make install
}
Thirdly, write genpkg_rules() as usual. Cook will
switch to the required set automatically based on the conformity between
packages and sets that you described in the $SPLIT variable
on the first step. That's all.
Dependency tracking
Many packages use libtool, created during the
configure processing. This libtool contains one
old and well-known (in narrow circles) "feature" that is expressed in
the fact that unnecessary dependencies are added to libraries and
executable files. Read about it:
- Bug 655517 - using --as-needed in LDFLAGS is not respected and it links on unneeded libs
- Project:Quality Assurance/As-needed
The links above recommend adding -Wl,--as-needed to the
LDFLAGS variable (the default cook.conf already does it). You can use
the short statement fix ld at the beginning (to add
-Wl,--as-needed to the LDFLAGS) and fix libtool
just after the configure invocation (to additionally fix the
just created libtool). Example of use:
compile_rules() {
fix ld
./configure \
--sysconfdir=/etc \
$CONFIGURE_ARGS &&
fix libtool &&
make && make install
}
You should not use fix libtool if you do not see a file
named libtool in the root of the sources tree after the
configure is done. It will not lead to an error, although
there will be no sense in it.
You can check dependencies of separate files using one of the next methods:
ldd /path/to/file readelf -d /path/to/file | grep NEEDED
You can check dependencies of an entire package using the command
(cook package_name --deps is a shortcut for it):
cook-deps package_name
You can note a significant decrease in the number of dependencies. For example:
- for fontconfig:
- before: bzlib freetype liblzma libpng16 libxml2 zlib
- after: freetype libxml2
- for at-spi2-core:
- before: dbus glib libffi pcre util-linux-blkid util-linux-mount util-linux-uuid xorg-libICE xorg-libSM xorg-libX11 xorg-libXau xorg-libXdmcp xorg-libXext xorg-libXi xorg-libXtst xorg-libxcb zlib
- after: dbus glib xorg-libX11 xorg-libXtst
For some packages nothing will change.
Dependency tracking for development packages
This is a separate and complex issue.
Dependency info may be extracted from .pc, .la
and .h files. Extracting dependencies from the header files
(.h) is a non-trivial task due to conditional branching and
can not be realized using simple tools.
As for .la files, Gentoo
recommends
to remove them in most cases. As they state, .la files may
be useful only for static libraries (.a files). Currently,
the dependency tracking tool doesn't use .la files unless you
provide the special argument --la:
cook-deps fontconfig --la
It turns out that .pc files are the only development files
that describe dependencies of development packages. Usually the
configure script checks dependencies using something like
this:
pkg-config --exists --print-errors "gtk-doc >= 1.15" pkg-config --exists --print-errors "xrender >= 0.6"
Dependency tracking tools try to find the package that contains the
required libraries, then determine a *-dev package that
corresponds to the found package.
For example, the file /usr/lib/pkgconfig/cairo.pc contains
the line:
Requires.private: gobject-2.0 glib-2.0 >= 2.14 pixman-1 >= 0.30.0
fontconfig >= 2.2.95 freetype2 >= 9.7.3 libpng xcb-shm x11-xcb
xcb >= 1.6 xcb-render >= 1.6 xrender >= 0.6 x11 xext
Finding the next files shows the dependencies:
gobject-2.0.pc glib-2.0.pc pixman-1.pc fontconfig.pc freetype2.pc
libpng.pc xcb-shm.pc x11-xcb.pc xcb.pc xcb-render.pc xrender.pc
x11.pc xext.pc
Next example using the file /usr/lib/pkgconfig/apr-1.pc:
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
APR_MAJOR_VERSION=1
Libs: -L${libdir} -lapr-${APR_MAJOR_VERSION} -luuid -lrt -lcrypt -lpthread -ldl
Finding the next files shows the runtime dependencies and then the full
dependencies; *-dev packages are the full packages.
libapr-1.so libuuid.so librt.so libcrypt.so libpthread.so libdl.so
| | | | | |
v v v v v v
apr util-linux-uuid glibc-base glibc-base glibc-base glibc-base
| | | | | |
v v v v v v
apr-dev util-linux-uuid-dev glibc-dev glibc-dev glibc-dev glibc-dev
Note, sometimes the required files may be found in two or more packages,
for example, libdl.so exists within packages:
glibc-baseuclibc-armv4eb,uclibc-armv4l,uclibc-armv4tl,uclibc-armv5l,uclibc-armv6luclibc-cross-compiler-armv4eb,uclibc-cross-compiler-armv4l,uclibc-cross-compiler-armv4tl,uclibc-cross-compiler-armv5l,uclibc-cross-compiler-armv6l,uclibc-cross-compiler-i486,uclibc-cross-compiler-mips,uclibc-cross-compiler-mips64,uclibc-cross-compiler-mipsel,uclibc-cross-compiler-powerpc,uclibc-cross-compiler-sh4,uclibc-cross-compiler-sparc,uclibc-cross-compiler-x86_64uclibc-i486,uclibc-mips,uclibc-mips64,uclibc-mipsel,uclibc-powerpc,uclibc-sh4,uclibc-sparc,uclibc-x86_64