.Dd September 27, 2026 .Dt MAKEPKG 5 .Os .Sh NAME .Nm MAKEPKG .Nd package build recipe .Sh SYNOPSIS .Pa /ports/ Ns Ar collection Ns / Ns Ar port Ns Pa /MAKEPKG .Pa /usr/ports/ Ns Ar collection Ns / Ns Ar port Ns Pa /MAKEPKG .Sh DESCRIPTION A .Nm file describes how to fetch, build and package one piece of software. It is read by .Xr 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. .Pp The first line must be exactly .Dl #!/bin/mkpkg .Pp Empty lines and lines starting with .Ql # are ignored. By convention the file starts with .Ql # description:\& and .Ql # url:\& comments, and ends with a .Fn signify block and a .Li # vim: filetype=sh line. .Sh VARIABLES A variable is set with .Ar name Ns = Ns Ar value . Quotes around the value and a trailing .Ql # comment are removed. .Bl -tag -width Ds .It Va name The package name. Required. .It Va version The upstream version. Required. .It Va release The package release, raised when the recipe changes but .Va version does not. Required. .It Va _ Ns Ar custom Any variable whose name starts with .Ql _ , such as .Va _commit . .El .Pp Other variables are ignored. All of the above are exported to the hooks. In .Va source and .Va renames , .Li $ Ns Ar var and .Li ${ Ns Ar var Ns } are replaced by their values, as far as they are set earlier in the file. .Sh ARRAYS An array is set with .Sm off .Ar name No =( Ar value No ... ) , .Sm on and may continue over several lines up to the closing parenthesis. Values are separated by white space and may be quoted. .Va source and .Va sha256sums also accept .Sm off .Ar name No +=( Ar value ) . .Sm on .Bl -tag -width Ds .It Va source The sources. A URL starting with .Li http:// , .Li https:// or .Li ftp:// is downloaded into the source directory, under the last component of the URL. Any other entry is a file in the port directory. .Pp Archives ending in .Pa .tar , .Pa .tar.gz , .Pa .tgz , .Pa .tar.bz2 , .Pa .tbz2 , .Pa .tar.xz , .Pa .txz , .Pa .tar.lz , .Pa .tar.lzma , .Pa .tar.zst , .Pa .tzst or .Pa .tar.Z are unpacked into .Ev SRC ; other files, including .Pa .zip archives, are copied there. .It Va renames Names to save the downloads under, by position: entry .Ar n applies to entry .Ar n of .Va source . An empty entry, .Li \(dq\(dq or .Li '' , keeps the original name, so only the first of three sources is renamed with .Bd -literal -offset indent renames=($name-$version.tar.gz "" "") .Ed The entry .Li SKIP leaves that source out: it is neither downloaded nor unpacked. .It Va sha256sums The SHA256 of each source, by position. .Li SKIP disables the check for that entry. Print a new array with .Ic mkpkg -c , or rewrite it in place with .Ic mkpkg -uc . .It Va depends Packages needed at run time. .It Va makedeps Packages needed only to build. .Pp Both are read by .Xr pkg 8 , and are what a build in the lockbox may read; see .Xr lockbox 7 . .It Va provides Other names this package satisfies as a dependency, such as .Li ninja for samurai. Read only by .Xr pkg 8 . .It Va variant A one-line description that makes a port .Ar name Ns - Ns Ar suffix a variant of the port .Ar name , offered by .Ic pkg add Ar name . Read only by .Xr pkg 8 . .It Va lockbox Build in the lockbox. .Li yes , .Li on or .Li 1 select the full lockbox; .Li no and .Li off do nothing. Any other value is a command to run through .Xr lbexec 8 wherever a line of .Fn build starts with it. The forms may be combined. .It Va groups System groups and users to create before the package's files are installed. An entry is one of: .Bl -tag -width Ds .It Ar group A system group. .It Xo .Sm off .Ar group : Ar gid .Sm on .Xc A system group with a fixed GID. .It Xo .Sm off .Ar group No \&:user:\& Ar user : Ar home : Ar mode .Op \&: Ar uid : Ar gid .Sm on .Xc A system group, and a system user in it with shell .Pa /bin/false and home directory .Ar home , which is created with .Ar mode , owned by the user. The second field is the literal word .Li user . With both .Ar uid and .Ar gid , the IDs are fixed, so they are the same on every machine. No home directory is created for .Pa / , .Pa /dev/null , .Pa /nonexistent or .Pa /var/empty . .El .Pp Groups of the base system, such as .Li wheel or .Li 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. .It Va services runit services to enable when the package is installed: a link .Pa /service/ Ns Ar name to .Pa /etc/sv/ Ns Ar name is made, unless something by that name exists. The service directory itself must be part of the package. When the package is removed, the link is removed and the service stopped. .It Va permissions Owner, group and mode to set after installing, as .Sm off .Ar path : Ar owner : Ar group : Ar mode , .Sm on with an octal .Ar mode . The mode of a symbolic link is not changed. .It Va capabilities File capabilities to set after installing, as .Sm off .Ar path : Ar capabilities , .Sm on using .Xr setcap 8 . Capabilities are extended attributes, which do not survive in the package archive, so they are set at install time. .El .Pp Paths in .Va permissions and .Va capabilities are relative to the installation root. .Sh HOOKS A hook is written like a shell function: .Bd -literal -offset indent build() { ... } .Ed .Pp 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 .Ql # do not count. .Pp Each hook runs as a separate .Xr sh 1 script with .Ic set -e , after the variables in .Xr mkpkg 8 .Sx ENVIRONMENT are exported. Some hooks first source .Pa /etc/mkpkg.conf . .Bl -tag -width Ds .It Fn shell A .Fn shell before .Fn 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 .Fn shell after .Fn build runs after the package is made, checked and signed, or as soon as a step fails, the first .Fn shell included, so it can undo the setup either way. Both run in .Ev PKGMK_SOURCE_DIR and source .Pa /etc/mkpkg.conf . Typical use is to create wrappers the build needs and to remove them again. .It Fn extract Unpacks the sources itself; without it, .Xr mkpkg 8 unpacks them as described under .Va source . Runs in .Ev PKGMK_SOURCE_DIR , without .Pa /etc/mkpkg.conf . .It Fn patch Applies patches. Runs in .Ev SRC , without .Pa /etc/mkpkg.conf . Patch files listed in .Va source have been copied into .Ev SRC . .It Fn build Builds and installs into .Ev PKG . Required. Runs in .Ev SRC and sources .Pa /etc/mkpkg.conf . .It Fn post_build Adds to or cleans up the package, such as runit service files. Runs in .Ev SRC after .Fn build and sources .Pa /etc/mkpkg.conf . .El .Sh SIGNIFY BLOCK .Fn signify holds the .Xr 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. .Bd -literal -offset indent signify() { untrusted comment: signify public key RWQ... } .Ed .Pp The key only names the signer. It is trusted only if the same key is in a .Pa .pub file in .Pa /etc/ports/keys/ ; see .Xr mkpkg 8 .Sx SIGNATURE VERIFICATION . Write or replace the block with .Ic mkpkg -up , print it with .Ic mkpkg -p . .Sh PACKAGE METADATA If any of .Va groups , .Va services , .Va permissions or .Va capabilities is set, .Xr mkpkg 8 adds the file .Pa var/lib/pkg/meta/ Ns Ar name to the package, one line per entry: .Bd -literal -offset indent group dhcpcd:user:dhcpcd:/var/lib/dhcpcd:700 service dhcpcd permission /sbin/dhcpcd:root:dhcpcd:750 capability /usr/bin/ping:cap_net_raw+ep .Ed .Pp It is read by .Xr addpkg 8 and .Xr delpkg 8 . .Sh EXAMPLES A minimal recipe: .Bd -literal -offset indent #!/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 .Ed .Pp A daemon with its own user and a runit service: .Bd -literal -offset indent #!/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\enexec 2>&1\enexec dhcpcd -B\en' > $PKG/etc/sv/$name/run chmod 755 $PKG/etc/sv/$name/run } signify() { untrusted comment: signify public key RWQ... } # vim: filetype=sh .Ed .Sh SEE ALSO .Xr signify 1 , .Xr mkpkg.conf 5 , .Xr lockbox 7 , .Xr addpkg 8 , .Xr delpkg 8 , .Xr lbexec 8 , .Xr mkpkg 8 , .Xr pkg 8 .Sh CAVEATS Entries beyond these limits are ignored without a warning: 256 sources and checksums, 64 entries each in .Va depends and .Va makedeps , 16 each in .Va groups , .Va services , .Va permissions , .Va capabilities and the commands of .Va lockbox , 32 custom variables and 512 lines per hook.