Docs/manual.md

Wed, 23 Oct 2019 21:04:00 +0200

author
David Demelier <markand@malikania.fr>
date
Wed, 23 Oct 2019 21:04:00 +0200
changeset 1178
8cbb83c16868
parent 1165
8d2032c88258
permissions
-rw-r--r--

vanilla: add PKGWWW in templates

Getting started
===============

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

Synopsis
========

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

- NAME.sh: 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).
- NAME-post.sh: a script to be executed before/after the installation
  (Optional).

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

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

The build script
================

The build script (NAME.sh) 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
license.

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

Metadata
--------

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 licenses.md file).
- PKGSUMMARY: a short summary.
- PKGWWW: the project homepage with the scheme (e.g. http://example.org).

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.

Build
-----

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
meaning:

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

Example:

	PKGDEPENDS="cmake:build qt5:optional zlib"

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

- autoconf
- automake
- busybox
- clang
- compiler-rt
- etc
- filesystem
- libc++
- libc++abi
- libtool (except linked to it)
- libunwind
- lld
- 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.

Example:

	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`.

Example:

	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 UIDS.md in this directory as well.

Options
=======

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.

Example:

	PKGOPTIONS="NLS DRIVERS"

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

	if [ "$NLS" = "yes" ]; then
		PKGDEPENDS="core/gettext $PKGDEPENDS"
		with_nls="--enable-nls"
	else
		with_nls="--disable-nls"
	fi

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 options.md for predefined options and proper naming.

Paths
=====

The package must ensure appropriate directories for installing files. This
includes:

- /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.

Patches
=======

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.

Example:

	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
========

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

Example:

	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
print.

### 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.

Static and shared libraries
===========================

By default, your package *MUST* ship both static and shared libraries if
applicable.

If possible, the package should provide the option *STATIC* that should do the
following if set to *yes*:

- On library packages, disable generation of shared libraries,
- On executables, build static binaries,
- If the package provides both, do the two steps.

This option should not be enabled by default unless absolutely necessary.

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 NAME-post.sh 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.

Example:

	#!/bin/sh

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

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
once).

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

[desktop entry specification]: https://specifications.freedesktop.org/desktop-entry-spec/latest

mercurial