MKPKG(8) System Manager's Manual MKPKG(8)

mkpkg — build packages from source

mkpkg [dir] [-bdw] [-i[bcfs]] [-g file] [-r root]

mkpkg [dir] -c | -e | -f | -p | -s

mkpkg [dir] -od | -oe

mkpkg [dir] -u[cfsp] [-i[bcfs]]

mkpkg [dir] -x[dfsw]

mkpkg -h | -v

mkpkg reads a MAKEPKG(5) recipe from the current directory, or from dir if given, and builds a binary package from it. The package is written as name#version-release.pkg.tar.ext into the package directory, where ext follows MKPKG_COMPRESSION_MODE in mkpkg.conf(5).

If MAKEPKG.lock exists, it is built instead of MAKEPKG; see LOCKED PORTS.

A build runs these steps, in order:

  1. Verify the port signature; see SIGNATURE VERIFICATION. Skipped with -is.
  2. If the package must be built, make sure every source is present. Missing downloads are an error unless -d is given, in which case they are fetched with wget(1).
  3. Verify the sha256sums of the sources. Skipped with -ic.
  4. Stop if the package is up to date: it exists and no source file is newer than it. The recipe itself is not compared; after editing it, raise release or remove the package with -x.
  5. Run the first () hook. If it fails, the second shell() hook runs to clean up and nothing is built.
  6. Create the work directory, then run () or unpack the sources automatically, then ().
  7. Run () and ().
  8. Strip binaries, compress manual pages with gzip(1), remove libtool .la files and write the package metadata.
  9. Create the package archive.
  10. Check the package against .footprint; see FOOTPRINT.
  11. Sign the port if the footprint check passed; see SIGNATURE VERIFICATION.
  12. Run the second shell() hook. If the build failed at an earlier step, it runs right then, so the first hook's setup is always undone.
  13. With -r, install the package with addpkg(8).

The hooks are described in MAKEPKG(5).

Options are single letters and may be combined in one argument, as in -dw. The letters x, u, i and o start a group: every letter after them in the same argument belongs to that group, so -xdf removes downloads and the footprint, and -ic ignores checksums.

The options are as follows:

Build in the full lockbox, as if the recipe set lockbox=(yes); see lockbox(7).
Print a sha256sums array for the sources to standard output.
Download missing sources before building.
Unpack the sources into a fresh work directory and stop. Same as -oe.
Print the footprint of the built package to standard output.
file
Use the configuration file instead of /etc/mkpkg.conf, both for the MKPKG_* settings and in the hooks that source it. A relative file is taken relative to the directory mkpkg is started in.
, --help
Print a usage summary.
[bcfs]
Ignore one or more checks; the build still runs:
Do not use the lockbox, neither the full lockbox of -b or lockbox=(yes) nor the per-command form.
Do not verify sha256sums.
Sign even if the footprint does not match.
Do not verify the port signature before building, and do not sign after it.
d
Download missing sources and stop.
e
Unpack the sources into a fresh work directory and stop.
Print the public key from the recipe's () block.
root
After a successful build, install the package into root with addpkg(8). If another version of the package is installed there, it is upgraded with -u; if the same version is installed, addpkg(8) refuses.
Verify the port signature and stop.
[cfsp]
Update port files. The letters combine, and run in this order: p, c, then with s the build if one is needed, f, and signing last, so the signature covers what the others wrote.
Rewrite the sha256sums array in the recipe from the sources on disk.
Rewrite .footprint from the built package.
Sign the port. The sources are checked first as for a build: missing downloads are an error unless -d is given, and the sha256sums are verified unless -ic is given. The package is built if it is not up to date. Signing is refused if the footprint does not match, unless f or -if is also given, and fails if there is no secret key.
Write a signify() block with the public key belonging to the secret key into the recipe, replacing any existing one. The public key is looked for next to the secret key, with .sec replaced by .pub, then in /etc/ports/keys/.
, --version
Print the version.
Keep the work directory after the build. Given twice, -ww resumes: the existing work directory is used as it is, () and () are skipped and () runs again. Neither work/src nor work/pkg is cleaned first. Resuming needs the work directory of an earlier -w run, so it does not work with a tmpfs MKPKG_WORK_DIR, which is created per process.
[dfsw]
Remove the built package, then stop. Further letters remove more:
Downloaded source files. Sources saved under a name from renames are not found.
The footprint file.
The signature file.
The work directory in the port directory.

When several modes are given, only the first of these runs: -x, -f, -c, -p, -s, -od, -e, -u, build.

The footprint is the sorted list of files in the package, with mode, owner and group, and the target of each symbolic link. On the first build, when there is no .footprint, it is created.

On later builds a mismatch is printed as “changed”, “missing” and “new” entries. The package is kept and mkpkg exits 0, so a long build is never lost to a footprint change; the package is just not signed. Review the list, then accept it with -uf and sign with -us. addpkg(8) refuses to install a package whose footprint does not match.

Before every build, and with -s, mkpkg verifies the port in three steps and fails on any of them:

  1. The key in the recipe's () block must equal the key of a .pub file in /etc/ports/keys/. That trusted file is used for the next step, never the key from the recipe: the recipe and its .signature arrive by the same way, so a key carried in the recipe can only vouch for itself.
  2. signify(1) verifies .signature with the trusted key. This authenticates the checksum list in it.
  3. The MAKEPKG line of that list must match the recipe on disk, and the .footprint line, when present, the footprint on disk. Sources are covered by the recipe's sha256sums.

After a build whose footprint check passed, the port is signed if the recipe has a () block and a secret key is found: MKPKG_SECRET_KEY from the configuration file or the environment, else /etc/ports/keys/rawnix.sec. Without a key, signing is skipped silently. After signing, mkpkg verifies the new signature and warns if it can never pass.

The list names the recipe MAKEPKG and the footprint .footprint whichever files were hashed; see LOCKED PORTS.

When MAKEPKG.lock exists in the port directory, mkpkg builds it instead of MAKEPKG, and uses .footprint.lock and .signature.lock in place of .footprint and .signature for every check, update and signature. ports(8) does not sync *.lock, so upstream updates never touch a locked port's recipe, footprint or signature. The lock files are created by pkg lock.

A fresh lock carries upstream's signature, which still verifies the unedited recipe. After editing MAKEPKG.lock, sign it again with -us. To sign with your own key, run -up with MKPKG_SECRET_KEY pointing at it, then -us, and install the matching .pub into /etc/ports/keys/.

mkpkg exports to every hook:

The package staging directory, work/pkg. Files installed here end up in the package.
The source directory, work/src.
The directory downloads are saved in: MKPKG_SOURCE_DIR if set, otherwise the port directory.
, version, release
From the recipe, as are its _custom variables.

With per-command lockbox, build() also gets MKPKG_WORK_DIR, MKPKG_DEPENDS and MKPKG_MAKEDEPENDS for lbexec(8).

mkpkg itself reads:

If set, trace recipe parsing and run the hooks with set -x.
Secret key for signing, if not set in the configuration file.
Package database directory for the lockbox, instead of /var/lib/pkg.
Directory for temporary files. Default: /dev/shm.

MAKEPKG
The recipe; see MAKEPKG(5).
.footprint
Expected contents of the package.
.signature
Signed checksums of the recipe, footprint, sources and package.
.nostrip
Patterns, one per line, for grep(1) -f; matching files, as paths relative to PKG, are not stripped.
MAKEPKG.lock, .footprint.lock, .signature.lock
A locked port's recipe, footprint and signature.
work/
Default work directory.
/etc/mkpkg.conf
Configuration; see mkpkg.conf(5).
/etc/ports/keys/*.pub
Trusted public keys.
/etc/ports/keys/rawnix.sec
Default secret key for signing.

0
Success, including a build whose footprint did not match.
1
General error or usage error.
2
The recipe could not be read or is incomplete.
3
A directory is missing or not accessible.
4
A download failed or a source is missing.
5
Unpacking failed.
6
A checksum did not match.
7
The footprint could not be made, or -us refused to sign because it did not match.
8
A hook or the build failed.
9
Installing with -r failed.
10
Signature verification or signing failed, or -us found no secret key.

Build a port from anywhere, downloading its sources:

$ mkpkg /usr/ports/core/zlib -d

Accept a changed footprint after a build, then sign:

$ mkpkg -uf && mkpkg -us

After a version bump: download, update the checksums, build, accept the new footprint and sign:

$ mkpkg -od && mkpkg -ucfs

Clean everything and rebuild:

$ mkpkg -xdfsw && mkpkg -d

signify(1), MAKEPKG(5), mkpkg.conf(5), lockbox(7), addpkg(8), bulk(8), lbexec(8), pkg(8), ports(8)

September 27, 2026 mkpkg 1.6.0