From Adélie Linux
This page describes the internal odds and ends of the APK packaging system as used by Adélie Linux, Alpine Linux, and other distributions.
APK is the package manager used by Adélie Linux, developed originally by Alpine Linux who remain its primary maintainers. This document was created to document the internal workings of APK for development of apkkit and other projects, but may be useful to other development activities or for debugging issues. Note that this information could become inaccurate very quickly as it relies on implementation details that are not documented publicly. This document was written on 29 May 2017, against the current git version of APK (2.7.1+9325eb72).
Secrets of the build system
APK's Makefile supports a number of undocumented options.
||Empty: not build Lua module|
|Any value: Build Lua module|
||Empty: Do not build libapk.so|
|Any value: libapk.so|
|Any other value: Do not build test applet|
An APK file contains an internal signature, a manifest that describes the package, optional executables to run after certain package operations, an optional trigger to run when files are modified in specified directories, and then the package's contents.
Nominally, the APK is created in two parts:
control.tar, which contains all of the package's metadata; and
data.tar, which contains the package's data. The data.tar file is signed using SHA1 with abuild-tar.
.PKGINFO file is required. This is a text file that contains the package's metadata.
A signature file may also be present. If signed, the signature file must be the first file in the archive, and it must match the naming format
$TYPE specifies the signature algorithm, and must be either DSA or RSA [sic, meaning SHA].
$KEYNAME specifies the name of the public key that signed
control.tar; to verify the signature, an identical public key file must be present at
Certain package operations will execute named executable files if they are present in the control file (unless --no-scripts is passed):
.pre-install, if present, will be executed before the package is first installed if the package passes verification. If the package has not been signed, or failed verification but the user passed --allow-untrusted, this script will not be run. If the package is being upgraded,
.pre-upgradewill be run instead; the package must still pass verification.
.post-install, if present, will be executed after the package is first installed. If the package is being upgraded,
.post-upgradewill be run instead.
.pre-deinstall, if present, will be executed before the package is uninstalled.
.post-deinstall, if present, will be executed after the package is uninstalled.
.PKGINFO file contains most of the package's metadata. It is a text file in key/value pair format, similar to INI configuration files but with a required space on each side of the equal sign. Full-line comments, starting with a "#" symbol, are ignored; a # symbol at any other position in a line will be treated as a literal.
Presently, the following keys are recognised by APK:
|n/a||String||C||Checksum (SHA-1?) of the control part of the package, excluding signatures.|
|pkgname||String||P||The name of the package.|
|pkgver||Version||V||The version of the package.|
|pkgdesc||String||T||The user-readable description of the package.|
|url||String||U||The URL of the package, typically the developer's Web site.|
|size||Integer||I||The installed size of the package in whole bytes.|
|license||String||L||The software license of the package.|
|arch||String||A||The architecture for which the package was built.|
|depend||Atom||D||A package name, virtual, or library on which the package depends. There can be more than one depend line.|
|install_if||Atom||i||If all package, virtual, or libraries specified in install_if are installed, this package will be installed automatically. There can be more than one install_if line.|
|provides||Atom||p||A package name, virtual, or library that this package provides. There can be more than one provides line.|
|replaces||Atom||r||A package name that this package replaces. There can be more than one replaces line. The previous package will be removed and the files owned by it will become owned by this package.|
|replaces_priority||Integer||q||The priority of the replacement. The highest number in the index wins.|
|triggers||String||n/a||A space-delimited list of directories. See below section for more information.|
|maintainer||String||m||The name of the maintainer of this package.|
|builddate||Integer||t||The date this package was built. This field is a 64-bit POSIX timestamp specified in whole seconds.|
|commit||String||c||A commit ID for this package.|
|origin||String||o||The name of the origin package for this package. If this package is a subpackage (ex: foo-doc), this is the name of the base package (ex: foo). Otherwise, this is almost always the name of the package.|
Strings are internally referred to as "blob"s. Integers are always 64-bit. A version can contain numbers, ASCII alphabetical characters, and the symbols "-_=~<>". Atoms are packages, and may be only a name, or a name followed by a dash (-) followed by a Version. A virtual can be specified with a "v:" prefix; a library can be specified with a "so:" prefix.
Only pkgname and pkgver are required. Size will default to 0 bytes if not specified. Arch will default to the current architecture (as specified at $APKROOT/etc/apk/arch), or the default architecture compiled in to the binary.
.trigger executable, if present in package A's control.tar, will be executed when any package B installs a file into a directory matching the
triggers key in a package A's
.PKGINFO. Each directory in the space-delimited list will be passed to fnmatch with the FNM_PATHNAME flag. This allows you to use shell-like globbing for subdirectories.
The signature format for the data.tar needs to be documented here eventually. Rev-eng abuild-tar.
Index files (APKINDEX, APKINDEX.tar.gz)
APKINDEX.tar.gz file is created by
apk from a directory of *.apk files using the
index applet. The
index APK applet takes a few parameters:
|--quiet||(none)||Don't print any output.|
|--output||String||The filename to which to write the index.|
|--description||String||The description to use for the index. There is no default; it can be set to anything. abuild uses |
|--rewrite-arch||String||Causes all packages to appear to be built for the specified arch. This is used by abuild because otherwise 'noarch' packages would not be chosen by apk (because they would appear to be for a different CPU).|
apk will read every *.apk file in the directory and output the APKINDEX.tar.gz file to the path specified by --output, or APKINDEX.tar.gz in the current working directory if --output is not specified.
Once the file is created it must be signed similarly to control.tar.gz for the APK file itself.
There are typically three files in the APKINDEX.tar.gz file:
- This is the signature.
- This is a plain-text file that contains the string passed to --description. If no --description was specified, this file will not exist.
- The actual index, containing each record.
The index is a series of records which are separated by a blank link (\n).