Tue, 03 Sep 2019 13:27:11 +0200

David Demelier <>
Tue, 03 Sep 2019 13:27:11 +0200
changeset 1080
parent 821
child 1106

vanilla: update manual page with implicit dependencies

Getting started

This documentation explains how to write a package file from scratch.


Each package lives under a dedicated directory broken down into several
categories. A package consists of the following files:

- a pure POSIX shell that process the build and contains some
  metadata required for installation.
- NAME.sha1: contains the checksums for individual source files (Optional).
- a script to be executed before/after the installation

In the listing above, replace NAME with the actual package name. For example the
package *zlib* contains the following files:

- compression/zlib/
- compression/zlib/zlib.sha1

The build script

The build script ( is a pure POSIX shell that defines various
information about the package and how to build it. To be included within the
official Vanilla Linux repository it must be licensed under the terms of the ISC

Several templates are already available for most build systems in the Templates


A package requires several information to be installed, the following variables
must be present:

- PKGNAME: the package name (same as the directory).
- PKGVERSION: the package upstream version.
- PKGREVISION: the initial revision (starts at 1).
- PKGLICENSE: a space separated list of licenses (see file).
- PKGSUMMARY: a short summary.

The following variables are optional

- PKGDEPENDS: a space separated list of packages required to build (see below). 
- PKGDOWNLOAD: a space separated list of files to download from the web, if the
  package does not need to download anything don't set it.
- PKGUIDS: a space separated list of uid to create (see below)
- PKGGIDS: a space separated list of gid to create (see below)
- PKGPROTECT: a space separated list of relative path to files to preserve on
  installation (e.g. etc/nginx/nginx.conf)
- PKGOPTIONS: a space separated list of CAPITALIZED options.


To build the package, you need to define a build function that install the
package into the $DESTDIR variable.

Usually, the build function does:

1. Clean the build directory in case the previous build failed.
2. Extract distribution files.
3. Process build and installs into $DESTDIR.
4. Clean up again the build directory.

Package naming

The following prefixes must be used for those packages:

- py-: for python modules.
- py2-: for python modules (only for exceptional cases).
- ruby-: for native ruby modules.
- rubygem-: for rubygems modules.
- p5-: for perl 5 modules.
- hs-: for haskell modules.
- font-: for fonts (of any kind).

When a package is available with different versions (e.g. Gtk, Qt) we add the
major number as suffix to the PKGNAME to *old* versions. Example, if Qt 5 is the
current major version and Qt 4 is also shipped then, the package *qt* refers to
version 5 while *qt4* to version 4.

Handling dependencies

Add any dependencies the packages requires in *PKGDEPENDS* variable.

Also, the following selectors may be appended to the dependency to alter the

- `:build` the dependency is only required for building,
- `:optional` the dependency is optional and not strictly required.


	PKGDEPENDS="cmake:build qt5:optional zlib"

The following dependencies are implicit and must *never* be marked in

- autoconf
- automake
- busybox
- clang
- compiler-rt
- filesystem
- libc++
- libc++abi
- libtool
- libunwind
- lld
- llvm
- musl
- pkgconf

Protected files

Configuration files (usually everything under /etc) must be marked as well in
*PKGPROTECT* variables. This prevents `vpk` for overriding user configurations.

Note: if the package ships a init script file, it must be marked as well.


	PKGPROTECT="etc/nginx.conf etc/rc.d/nginx"

In this case, `vpk` will rename the file to *etc/nginx.conf.vpk* and
*/etc/rc.d/nginx.vpk* in the archive and only be renamed if they are not present
on the disk or not manually modified.

Uids / Gids

If the package requires UNIX users and groups, adapt the *PKGUIDS* and *PKGGIDS*
variables as a space separated list. You can assign a default numeric id using
the syntax `:number`.


	PKGUIDS="messagebus" # vpk will assign an id
	PKGUIDS="gdm:55"     # vpk will use 55

Warning: if you need to change file permissions, do it *ONLY* in a post install
script as users may have set different numeric id than the package defaults.

Once you need a new UID/GID, edit the file in this directory as well.


If the package offer build options, edit the *PKGOPTIONS* variable and always
add default values that match upstream if possible. Boolean options must always
be considered as *yes* or *no*. If an option requires a list, use a space
separated list of values.



	: ${NLS:=yes}
	: ${DRIVERS:=amd intel}

	if [ "$NLS" = "yes" ]; then

Then at configure step:

	./configure $with_nls

Proper handling of options is done by explicitly disabling/enabling options.
Most programs will try to enable/disable features depending on what is available
on the system thus, if the package finds a dependency and enable it you need to
adapt *PKGDEPENDS*. Always check what options are available in the package and
use their default as explicit knobs to avoid invisible dependencies.

See the file for predefined options and proper naming.


The package must ensure appropriate directories for installing files. This

- /etc/rc.d: for service files,
- /lib/pkgconfig: for .pc files,
- /lib/cmake: for CMake config files,
- /lib: for libraries (no lib64 suffix),
- /share/PKGNAME: data directory (if applicable),
- /share/locale: for NLS files,
- /share/man/man{1,2,3,4,5,6,7,8}: for man pages (in uncompressed form),
- /share/doc/PKGNAME (exact directory, no version): arbitrary documentation.

Keep neutral

Do not make any modifications to the package. Keep it as close to upstream as
possible. Only minor tweaks are allowed including:

- adjusting pid/uid/gid in a default configuration file for easier deployment
  (but not on the original file example),
- making sure paths are consolidated,
- making sure system libraries are used rather than in-source bundles,
- replacing PAM files (see below).

PAM files

The PAM system is an flexible and well designed authentication tool, it has a
large number of modules and configuration settings. This complexity leads to
inconsistent upstream PAM files that are not always compatible with the default
Vanilla Linux generic's files, therefore you *must* always replace the provided
PAM files with custom alternatives and sane defaults. In general, LFS is a good
recommandation regarding PAM files.

Also, don't forget to add PAM files to the *PKGPROTECT* variable as they are
meant to be edited by the system administrator.


If a software requires patching, always try to see if there is already an
upstream patch that fixes the issue. If not, you may check how other Linux
distributions fix the problem with a local workaround.

Then, please consider sending the patch to the upstream if applicable.

Patches must be named in the form *patch-category.patch*. We encourage old style
of patches that you usually create by editing the file and comparing with the
original one.


	cp Makefile.orig Makefile
	vim Makefile
	diff -ub Makefile.orig Makefile > patch-musl.patch

Warning: by default busybox patch is used and is much stricter than standalone
         counterpart, in doubt always try to apply the patch manually with
         busybox patch and edit if required.

The following names are recommended depending on the situation:

- patch-fhs.patch: when a patch is required to adapt installation/usage to the
  Vanilla Linux file system hierarchy,
- patch-musl.patch: when the code assume a glibc specific code,
- patch-clang.patch: when the code does not compile with LLVM/Clang. Make sure
  the patch does not break GCC, if it does apply the patch in a conditional.

Also, do not create a patch for individual files if they all belong to the same
category. For example, if several source files require patching to build against
musl, use only one *patch-musl.patch* file.


Services files must be installed in /etc/rc.d in the mode 0644.


	install -Dm0644 food $DESTDIR/etc/rc.d/food

The script must at least support start, stop and restart.

UX style

You must use the following conventions regarding messages the service will

### start (required)

Always add arguments with the invocation.

	Starting foo: /bin/foo -d

If the service is already running, show:

	foo is already running with pid: 1234

### stop (required)

If the service is not running, don't write any message. Otherwise write:

	Stopping foo.

### restart (required)

Basically, this command just calls stop and start.

	Stopping foo.
	Starting foo: /bin/foo -d

### status (recommended)

Depending on the status, write the following messages.

	foo is running with pid: 1234
	foo is not running

### usage (required)

If the script is invoked with invalid arguments or none, write the usage like
this through stderr and exit 1. Also keep all subcommands sorted.

	usage: foo restart|start|status|stop

If your script may support additional operations, messages and usage are up to
the maintainer discretion.

See also the template file in Templates/rc.

Libtool files

Do not ship libtool files.

Manual pages

Do never install compressed manual pages. The `vpk` tool performs automatic
compression on installation depending on the user setting. Check how to disable
compression in the package or decompress them after installation in the
destination directory.

Post install scripts

If you need to perform some custom steps after the installation of the binary
package in the target systems, you may create the script. This
script must be written also in pure POSIX shell language.

As unique argument, `vpk` will provide one of these to the post script:

- pre-install: before the extraction of the package.
- post-install: after the extraction of the package.
- pre-uninstall: before removing the package.
- post-uninstall: after the removal of the package.

Note: if the package wants to call a binary from an other package, it is usually
      a good idea to check it's presence first.



	if [ -x /bin/gtk-update-icon-cache ]; then
		gtk-update-icon-cache -vf /share/icons/hicolor

Desktop files

We usually never add .desktop files for any package that doesn't provide one by
itself. This also includes terminal based applications.

If a .desktop is provided by the package, make sure though that it is valid and
specifies the appropriate category (i.e. it does not appear in multiple menus at

See [desktop entry specification][] for more information.

[desktop entry specification]: