PKGFILE(5) File Formats Manual PKGFILE(5)

Pkgfilebuild file for pkgmk

Pkgfile

This manual page describes the format of the Pkgfile file. The file is a POSIX sh(1p) script with some exceptions (see below), which defines a number of variables (, , and ) and a function (build) that should be executed in order to compile a package.

In POSIX sh, “local” is undefined. You can adopt some convention to avoid accidentally overwriting variable names, e.g. prefixing with the function name:

build() {
        _build_foo="bar"
        ...
}

However, “local” is supported in many shells, including bash(1), ksh(1), dash(1) (which is used in Zeppe-Lin as default /bin/sh provider), and BusyBox' ash(1). So, strictly speaking, it's not POSIX, but since quite a lot of real world shells support this feature, prefixing variables is little ugly, and finding bugs with overwriting variables is a big headache for developers, it was decided to allow "local". In the end, the choice is yours to use or not.

The name of a package should always be lowercase (e.g. “name=eterm” and not “name=Eterm”). Dashes are also allowed.

In case the package is added to the packages sources tree the exact same name should be used for the name of the directory in the packages sources structure (e.g. ).

Do not combine several separately distributed programs/libraries into one package. Make several packages instead.

In general packages should install files in these directories. Exceptions are of course allowed if there is a good reason. But try to follow the following directory structure as close as possible.

/usr/bin User command/application binaries
/usr/sbin System binaries (e.g. daemons)
/usr/lib Libraries
/usr/include Header files
/usr/lib/⟨prog⟩ Plug-ins, add-ons, etc
/usr/share/man Man pages
/usr/share/⟨prog⟩ Data files
/usr/etc/⟨prog⟩ Configuration files
/etc Configuration files for system software (daemons, etc)

/opt directory is reserved for manually compiled/installed applications, or binary distributable packages. Good packages (built from sources) should never place anything there.

/usr/libexec is not used, thus packages should never install anything there. Use “/usr/lib/⟨prog⟩” instead.

Packages should not contain “junk files”. This includes info pages and other online documentation, man pages excluded (e.g. “/usr/share/doc”, “README”, “*.info”, “*.html”, etc).

Also should be removed:

  • Files related to NLS (National Language Support), always use “--disable-nls” and similar build options when available and remove /usr/share/locale when not.
  • Useless or obsolete binaries (e.g. /usr/games/banner and /sbin/mkfs.minix).

Do not add new variables to the Pkgfile. Only in very few cases does this actually improve the readability or the quality of the package. Further, the only variables that are guaranteed to work with future versions of pkgmk(8) are “name”, “version”, “release”, and “source”. Other names could be in conflict with internal variables in pkgmk(8). Use the “$name” and “$version” variables to make the package easier to update/maintain. For example,

source=http://xyz.org/$name-$version.tar.gz

is better than

source=http://xyz.org/longprogramname-1.0.3.tar.gz

since the URL will automatically updated when you modify the “version” variable.

Note that “source” variable is a string, where each item is separated by a whitespace. If you want to specify multiple URIs/files, use quotes:

source="http://xyz.org/$name-$version.tar.gz
        http://xyz.org/$name-$version.patch"

By the way, while building packages, sometimes source tarballs have names that could collide with other sources. So, pkgmk(8) allows renaming the downloaded source by prefixing the URL like this:

source="$name-$version.tar.gz::http://xyz.org/v$version.tar.gz
        $name-$version.patch::http://xyz.org/$name.patch"

Provide a header including the following fields:

Description Short description of the package (keep it factual)
Maintainer Your full name and e-mail address (can be obfuscated)
URL Website with more information on this software package
Depends on List of dependencies, separated either by spaces

“Depends on” can be omitted if there are no dependencies.

Dependencies are supported by pkgman(1). The following rules should be respected:

  • We list all linked runtime dependencies except for (libstdc++), , , and the package itself (to prevent cyclic dependencies).
  • contains essential packages for a system, and our scripts and source packages expect the programs provided by core to be installed. This means the following:
    • Build dependencies provided by core are not listed in the dependency header.
    • Runtime dependencies from core which aren't dynamically linked are not to be listed : if the package provides a library for Perl/Python/etc and/or contains a specific interpreter version in its .footprint file.

Examples:

Does not list “perl”, because the program is a Perl script (there is no binary that links to “libperl”).
list “readline”, because “bc” is linked to “readline”.
list “python3”, because the package contains the specific interpreter version in its .footprint file.

The reasoning for this policy is that you can use revdep(1) to find packages that need to be updated if one of the dependent libraries has become binary incompatible. To find out what libraries a binary is linked to, use ldd(1) or finddeps-linked(1).

Also, in the case of updating the major version of Perl/Python/etc, it will be useful that the libraries or programs that create Perl/Python bindings have a dependency on them. We will have to rebuild everything that depends on Perl/Python with one command. See pkgman-rdep(1).

The actual scripts that control services should be named “rc.⟨prog⟩”, and installed to “/etc/rc.d/⟨prog⟩”. See RC Script for template script for a package.

Runscripts are supported by pkgman(1). Packages should be built with the idea in mind that people won't execute the “pre-install”, “post-install”, “pre-remove”, and “post-remove” scripts. This is entirely true for “corepkgsrc collection”, and varies from one to another collections. Such strict requirements for core comes from the fact that the packages in this collection are designed to be installed in a separate root directory by pkgadd(8) utility.

If a package adds an user to the system using “pre-install”, a “pre-remove” script must remove that user.

What these scripts should not do:

  • Edit configuration files.
  • Remove other packages.
  • Restart servers.
  • Request for user input.

The above prohibitions apply only to packages in the official pkgsrc repositories. You may not follow them in your own collections if you need more sophisticated setups. Obviously enough.

The “build” function should use the “$SRC” variable whenever it needs to access the files listed in the “source” variable, and the “$PKG” variable as the root destination of the output files.

Being a shell script executed in the context of pkgmk(8), the entire Pkgfile file has access to the variables initialized in pkgmk.conf and the default values set by pkgmk(8). Also, as an undocumented side affect of how it is used by pkgmk(8), it can also change the behaviour of pkgmk(8) by rewriting some of its functions and variables while the current package is built. However, the build function has only read access to these mentioned above.

Most of the command failures in build function will stop the build process. There is no need to explicitly check the return codes. If you need/want to handle a command failure you should use constructs like:

if ! command ... ; then ... ; fi

command || ...

# Description: Concise description without articles and trailing dot
# URL:         http://www.gnu.org/software/somelib/index.html
# Maintainer:  Joe Maintainer, joe at myfantasticisp dot net
# Depends on:  someotherlib coolness

name=somelib
version=1.2.3
release=1
source="ftp://ftp.gnu.org/gnu/$name/$name-$version.tar.gz
        Makefile.in.patch"

build() {
        cd $name-$version

        patch -p1 -i ../Makefile.in.patch

        ./configure --prefix=/usr

        make V=1
        make DESTDIR=$PKG install

        rm -rf $PKG/usr/info
}

#!/bin/sh
#
# /etc/rc.d/daemon: start/stop daemon(8) daemon
#

SSD=/sbin/start-stop-daemon
PROG=/usr/sbin/daemon
PID=/run/daemon.pid
OPTS="--some-opts"

case $1 in
start)
        $SSD --start --pidfile $PID --exec $PROG -- $OPTS
        ;;
stop)
        $SSD --stop --pidfile $PID --retry 10
        ;;
restart)
        $0 stop
        $0 start
        ;;
status)
        $SSD --status --pidfile $PID
        case $? in
        0) echo "$PROG is running with pid $(cat $PID)" ;;
        1) echo "$PROG is not running but the pid file $PID exists" ;;
        3) echo "$PROG is not running" ;;
        4) echo "Unable to determine the program status" ;;
        esac
*)
        echo "usage: $0 [start|stop|restart|status]"
        ;;
esac

# End of file.

pkgmk.conf(5), pkgmk(8)

The initial version of this manual page was written by Just-The-Real-Fun <just.the.real.fun@gmail.com> for CRUX.

This implementation was extensively re-worked and adapted for Zeppe-Lin by Alexandr Savca <alexandr.savca89@gmail.com>.

September 6, 2023 Zeppe-Lin