| MAKEPKG(5) | File Formats Manual | MAKEPKG(5) |
MAKEPKG — package
build recipe
/ports/collection/port/MAKEPKG /usr/ports/collection/port/MAKEPKG
A MAKEPKG file describes how to fetch,
build and package one piece of software. It is read by
mkpkg(8), which parses it itself
rather than running it as a script: it looks like a shell script, but only
the forms described here are understood.
The first line must be exactly
#!/bin/mkpkgEmpty lines and lines starting with
‘#’ are ignored. By convention the
file starts with ‘# description:’ and
‘# url:’ comments, and ends with a
signify()
block and a # vim: filetype=sh line.
A variable is set with
name=value. Quotes around the
value and a trailing ‘#’ comment are
removed.
_’, such as
_commit.Other variables are ignored. All of the above are exported to the
hooks. In source and renames,
$var and
${var} are replaced by their
values, as far as they are set earlier in the file.
An array is set with name=(value...), and may continue over several lines up to the closing parenthesis. Values are separated by white space and may be quoted. source and sha256sums also accept name+=(value).
http://,
https:// or ftp:// is
downloaded into the source directory, under the last component of the URL.
Any other entry is a file in the port directory.
Archives ending in .tar,
.tar.gz, .tgz,
.tar.bz2, .tbz2,
.tar.xz, .txz,
.tar.lz, .tar.lzma,
.tar.zst, .tzst or
.tar.Z are unpacked into
SRC; other files, including
.zip archives, are copied there.
"" or '', keeps
the original name, so only the first of three sources is renamed with
renames=($name-$version.tar.gz "" "")
SKIP leaves that source out: it is neither
downloaded nor unpacked.SKIP
disables the check for that entry. Print a new array with
mkpkg -c, or rewrite it in place with
mkpkg -uc.Both are read by pkg(8), and are what a build in the lockbox may read; see lockbox(7).
ninja for samurai. Read only by
pkg(8).pkg
add name. Read only by
pkg(8).yes,
on or 1 select the full
lockbox; no and off do
nothing. Any other value is a command to run through
lbexec(8) wherever a line of
build()
starts with it. The forms may be combined.user. With both
uid and gid, the IDs are
fixed, so they are the same on every machine. No home directory is
created for /,
/dev/null,
/nonexistent or
/var/empty.Groups of the base system, such as
wheel or video, are
never created or removed. When the package is removed, its user is
deleted, and its group too, unless another installed package declares
the same group.
Paths in permissions and capabilities are relative to the installation root.
A hook is written like a shell function:
build() {
...
}
The opening brace may also be on a line of its own. Each line of
the body is taken with its leading white space removed, so a here-document
cannot rely on indentation. The body ends at the matching closing brace;
braces inside quotes and after a ‘#’
do not count.
Each hook runs as a separate sh(1)
script with set -e, after the variables in
mkpkg(8)
ENVIRONMENT are exported. Some hooks
first source /etc/mkpkg.conf.
shell()shell() before build()
in the file runs before the build: after the sources are downloaded and
verified, before the work directory is set up. If it fails, nothing is
built. A shell() after
build() runs after the package is made, checked
and signed, or as soon as a step fails, the first
shell() included, so it can undo the setup either
way. Both run in PKGMK_SOURCE_DIR and source
/etc/mkpkg.conf. Typical use is to create wrappers
the build needs and to remove them again.extract()PKGMK_SOURCE_DIR, without
/etc/mkpkg.conf.patch()SRC, without
/etc/mkpkg.conf. Patch files listed in
source have been copied into
SRC.build()PKG. Required. Runs in
SRC and sources
/etc/mkpkg.conf.post_build()SRC after build() and
sources /etc/mkpkg.conf.signify() holds the
signify(1) public key of the key the port was
signed with. It is not a hook: its body is the two lines of the public key
file.
signify() {
untrusted comment: signify public key
RWQ...
}
The key only names the signer. It is trusted only if the same key
is in a .pub file in
/etc/ports/keys/; see
mkpkg(8)
SIGNATURE VERIFICATION.
Write or replace the block with mkpkg -up, print it
with mkpkg -p.
If any of groups, services, permissions or capabilities is set, mkpkg(8) adds the file var/lib/pkg/meta/name to the package, one line per entry:
group dhcpcd:user:dhcpcd:/var/lib/dhcpcd:700 service dhcpcd permission /sbin/dhcpcd:root:dhcpcd:750 capability /usr/bin/ping:cap_net_raw+ep
A minimal recipe:
#!/bin/mkpkg
# description: Shows the full path of shell commands
# url: https://www.gnu.org/software/which/
name=which
version=2.21
release=1
source=(https://ftp.gnu.org/gnu/$name/$name-$version.tar.gz)
sha256sums=(...)
build() {
cd $name-$version
./configure --prefix=/
make
make DESTDIR=$PKG install
}
signify() {
untrusted comment: signify public key
RWQ...
}
# vim: filetype=sh
A daemon with its own user and a runit service:
#!/bin/mkpkg
# description: DHCP client daemon
# url: https://github.com/NetworkConfiguration/dhcpcd
name=dhcpcd
version=10.2.2
release=1
depends=(openssl)
groups=(dhcpcd:user:dhcpcd:/var/lib/dhcpcd:700)
services=(dhcpcd)
permissions=(/sbin/dhcpcd:root:dhcpcd:750)
source=(https://github.com/NetworkConfiguration/$name/releases/download/v$version/$name-$version.tar.xz)
sha256sums=(...)
build() {
cd $name-$version
./configure --prefix=/ --privsepuser=dhcpcd
make
make DESTDIR=$PKG install
}
post_build() {
install -d $PKG/etc/sv/$name
printf '#!/bin/sh\nexec 2>&1\nexec dhcpcd -B\n' > $PKG/etc/sv/$name/run
chmod 755 $PKG/etc/sv/$name/run
}
signify() {
untrusted comment: signify public key
RWQ...
}
# vim: filetype=sh
signify(1), mkpkg.conf(5), lockbox(7), addpkg(8), delpkg(8), lbexec(8), mkpkg(8), pkg(8)
Entries beyond these limits are ignored without a warning: 256 sources and checksums, 64 entries each in depends and makedeps, 16 each in groups, services, permissions, capabilities and the commands of lockbox, 32 custom variables and 512 lines per hook.
| September 27, 2026 | mkpkg 1.6.0 |