The FreeBSD ports framework supports parallel building
using multiple make sub-processes, which
allows SMP systems to utilize all of
their available CPU power, allowing port
builds to be faster and more effective.
This is achieved by passing -jX flag
to make(1) running on vendor code. This is the default
build behavior of ports. Unfortunately, not all ports
handle parallel building well and it may be required to
explicitly disable this feature by adding the
MAKE_JOBS_UNSAFE=yes variable. It is
used when a port is known to be broken with
-jX due to race conditions causing
intermittent build failures.
When setting MAKE_JOBS_UNSAFE, it
is very important to explain either with a comment in the
Makefile, or at least in the commit
message, why the port does not build
when enabling. Otherwise, it is almost impossible to
either fix the problem, or test if it has been fixed when
committing an update at a later date.
Several differing make
implementations exist. Ported software often requires a
particular implementation, like GNU
make, known in FreeBSD as
gmake.
If the port uses GNU make,
add gmake to
USES.
MAKE_CMD can be used to reference the
specific command configured by the USES
setting in the port's Makefile.
Only use MAKE_CMD within the
application Makefiles in
WRKSRC to call the
make implementation expected by the
ported software.
If the port is an X application that uses
imake to create
Makefiles from
Imakefiles, set USES=
imake.. See the USES=imake
section of Chapter 17, Using USES Macros for more details.
If the port's source Makefile has
something other than all as the
main build target, set ALL_TARGET
accordingly. The same goes for
install and
INSTALL_TARGET.
If the port uses the configure
script to generate Makefile from
Makefile.in, set
GNU_CONFIGURE=yes. To give
extra arguments to the configure script
(the default argument is --prefix=${PREFIX}
--infodir=${PREFIX}/${INFO_PATH}
--mandir=${MANPREFIX}/man
--build=${CONFIGURE_TARGET}), set those
extra arguments in CONFIGURE_ARGS. Extra
environment variables can be passed using
CONFIGURE_ENV.
configure| Variable | Means |
|---|---|
GNU_CONFIGURE | The port uses configure
script to prepare build. |
HAS_CONFIGURE | Same as GNU_CONFIGURE,
except default configure target is not added to
CONFIGURE_ARGS. |
CONFIGURE_ARGS | Additional arguments passed to
configure script. |
CONFIGURE_ENV | Additional environment variables to be set
for configure script run. |
CONFIGURE_TARGET | Override default configure target. Default
value is
${MACHINE_ARCH}-portbld-freebsd${OSREL}. |
For ports that use CMake,
define USES= cmake.
cmake| Variable | Means |
|---|---|
CMAKE_ARGS | Port specific CMake
flags to be passed to the cmake
binary. |
CMAKE_ON | For each entry in CMAKE_ON, an
enabled boolean value is added to
CMAKE_ARGS. See Example 6.3, “CMAKE_ON and
CMAKE_OFF”. |
CMAKE_OFF | For each entry in CMAKE_OFF, a
disabled boolean value is added to
CMAKE_ARGS. See Example 6.3, “CMAKE_ON and
CMAKE_OFF”. |
CMAKE_BUILD_TYPE | Type of build (CMake
predefined build profiles). Default is
Release, or
Debug if
WITH_DEBUG is set. |
CMAKE_SOURCE_PATH | Path to the source directory. Default is
${WRKSRC}. |
CONFIGURE_ENV | Additional environment variables to be set for
the cmake binary. |
cmake Builds| Variable | Means |
|---|---|
CMAKE_NOCOLOR | Disables color build output. Default not set,
unless BATCH or
PACKAGE_BUILDING are set. |
CMake supports these
build profiles: Debug,
Release,
RelWithDebInfo and
MinSizeRel. Debug and
Release profiles respect system
*FLAGS, RelWithDebInfo
and MinSizeRel will set
CFLAGS to -O2 -g and
-Os -DNDEBUG correspondingly. The
lower-cased value of CMAKE_BUILD_TYPE is
exported to PLIST_SUB and must be
used if the port installs
depending on the build type (see
devel/kf5-kcrash for an
example). Please note that some projects may define their own
build profiles and/or force particular build type by setting
*.cmakeCMAKE_BUILD_TYPE in
CMakeLists.txt. To make a port for such
a project respect CFLAGS and
WITH_DEBUG, the
CMAKE_BUILD_TYPE definitions must be
removed from those files.
Most CMake-based projects
support an out-of-source method of building. The
out-of-source build for a port is the default setting.
An in-source build can be requested by using the
:insource suffix. With out-of-source
builds, CONFIGURE_WRKSRC,
BUILD_WRKSRC and
INSTALL_WRKSRC will be set to
${WRKDIR}/.build and this
directory will be used to keep all files generated during
configuration and build stages, leaving the source directory
intact.
USES= cmake ExampleThis snippet demonstrates the use of
CMake for a port.
CMAKE_SOURCE_PATH is not usually
required, but can be set when the sources are not located
in the top directory, or if only a subset of the project
is intended to be built by the port.
USES= cmake
CMAKE_SOURCE_PATH= ${WRKSRC}/subprojectCMAKE_ON and
CMAKE_OFFWhen adding boolean values to
CMAKE_ARGS, it is easier to use the
CMAKE_ON and CMAKE_OFF
variables instead. This:
CMAKE_ON= VAR1 VAR2 CMAKE_OFF= VAR3
Is equivalent to:
CMAKE_ARGS= -DVAR1:BOOL=TRUE -DVAR2:BOOL=TRUE -DVAR3:BOOL=FALSE
This is only for the default values off
CMAKE_ARGS. The helpers described in
Section 5.13.3.4.2, “
and
OPT_CMAKE_BOOL” use the same
semantics, but for optional values.OPT_CMAKE_BOOL_OFF
If the port uses SCons,
define USES=scons.
To make third party SConstruct
respect everything that is passed to SCons in
the environment (that is, most importantly,
CC/CXX/CFLAGS/CXXFLAGS), patch
SConstruct so build
Environment is constructed like
this:
env = Environment(**ARGUMENTS)
It may be then modified with
env.Append and
env.Replace.
For ports that use Cargo,
define USES=cargo.
cargo Builds| Variable | Default | Description |
|---|---|---|
CARGO_CRATES | List of crates the port depends on. Each entry
needs to have a format like
cratename-semver for example,
libc-0.2.40. Port maintainers can
generate this list from
Cargo.lock using
make cargo-crates. Manually
bumping crate versions is possible but be mindful of
transitive dependencies. | |
CARGO_FEATURES | List of application features to build (space
separated list). To deactivate all default
features add the special token
--no-default-features
to CARGO_FEATURES. Manually
passing it to CARGO_BUILD_ARGS,
CARGO_INSTALL_ARGS, and
CARGO_TEST_ARGS is not
needed. | |
CARGO_CARGOTOML | ${WRKSRC}/Cargo.toml | The path to the Cargo.toml
to use. |
CARGO_CARGOLOCK | ${WRKSRC}/Cargo.lock | The path to the Cargo.lock
to use for make cargo-crates. It
is possible to specify more than one lock file when
necessary. |
CARGO_ENV | A list of environment variables to pass to Cargo
similar to MAKE_ENV. | |
RUSTFLAGS | Flags to pass to the Rust compiler. | |
CARGO_CONFIGURE | yes | Use the default
do-configure. |
CARGO_UPDATE_ARGS | Extra arguments to pass to Cargo during the
configure phase. Valid arguments can be looked up
with cargo update --help. | |
CARGO_BUILDDEP | yes | Add a build dependency on lang/rust. |
CARGO_CARGO_BIN | ${LOCALBASE}/bin/cargo | Location of the cargo
binary. |
CARGO_BUILD | yes | Use the default
do-build. |
CARGO_BUILD_ARGS | Extra arguments to pass to Cargo during the
build phase. Valid arguments can be looked up with
cargo build --help. | |
CARGO_INSTALL | yes | Use the default
do-install. |
CARGO_INSTALL_ARGS | Extra arguments to pass to Cargo during the
install phase. Valid arguments can be looked up with
cargo install --help. | |
CARGO_INSTALL_PATH | . | Path to the crate to install. This is passed
to cargo install via its
--path argument. When multiple
paths are specified cargo install
is run multiple times. |
CARGO_TEST | yes | Use the default
do-test. |
CARGO_TEST_ARGS | Extra arguments to pass to Cargo during the test
phase. Valid arguments can be looked up with
cargo test --help. | |
CARGO_TARGET_DIR | ${WRKDIR}/target | Location of the cargo output directory. |
CARGO_DIST_SUBDIR | rust/crates | Directory relative to DISTDIR
where the crate distribution files will be
stored. |
CARGO_VENDOR_DIR | ${WRKSRC}/cargo-crates | Location of the vendor directory where
all crates will be extracted to. Try to keep this
under PATCH_WRKSRC, so that
patches can be applied easily. |
CARGO_USE_GITHUB | no | Enable fetching of crates locked to specific Git
commits on GitHub via GH_TUPLE.
This will try to patch all
Cargo.toml under
WRKDIR to point to the
offline sources instead of fetching them from a
Git repository during the build. |
CARGO_USE_GITLAB | no | Same as CARGO_USE_GITHUB
but for GitLab instances and
GL_TUPLE. |
Creating a Cargo based port is a three stage process. First we need to provide a ports template that fetches the application distribution file:
PORTNAME= tokei DISTVERSIONPREFIX= v DISTVERSION= 7.0.2 CATEGORIES= devel MAINTAINER= tobik@FreeBSD.org COMMENT= Display statistics about your code USES= cargo USE_GITHUB= yes GH_ACCOUNT= Aaronepower .include <bsd.port.mk>
Generate an initial
distinfo:
%make makesum=> Aaronepower-tokei-v7.0.2_GH0.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://codeload.github.com/Aaronepower/tokei/tar.gz/v7.0.2?dummy=/Aaronepower-tokei-v7.0.2_GH0.tar.gz fetch: https://codeload.github.com/Aaronepower/tokei/tar.gz/v7.0.2?dummy=/Aaronepower-tokei-v7.0.2_GH0.tar.gz: size of remote file is not known Aaronepower-tokei-v7.0.2_GH0.tar.gz 45 kB 239 kBps 00m00s
Now the distribution file is ready to use and we can go
ahead and extract crate dependencies from the bundled
Cargo.lock:
%make cargo-cratesCARGO_CRATES= aho-corasick-0.6.4 \ ansi_term-0.11.0 \ arrayvec-0.4.7 \ atty-0.2.9 \ bitflags-1.0.1 \ byteorder-1.2.2 \ [...]
The output of this command needs to be pasted directly into the Makefile:
PORTNAME= tokei
DISTVERSIONPREFIX= v
DISTVERSION= 7.0.2
CATEGORIES= devel
MAINTAINER= tobik@FreeBSD.org
COMMENT= Display statistics about your code
USES= cargo
USE_GITHUB= yes
GH_ACCOUNT= Aaronepower
CARGO_CRATES= aho-corasick-0.6.4 \
ansi_term-0.11.0 \
arrayvec-0.4.7 \
atty-0.2.9 \
bitflags-1.0.1 \
byteorder-1.2.2 \
[...]
.include <bsd.port.mk>distinfo needs to be regenerated to
contain all the crate distribution files:
%make makesum=> rust/crates/aho-corasick-0.6.4.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://crates.io/api/v1/crates/aho-corasick/0.6.4/download?dummy=/rust/crates/aho-corasick-0.6.4.tar.gz rust/crates/aho-corasick-0.6.4.tar.gz 100% of 24 kB 6139 kBps 00m00s => rust/crates/ansi_term-0.11.0.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://crates.io/api/v1/crates/ansi_term/0.11.0/download?dummy=/rust/crates/ansi_term-0.11.0.tar.gz rust/crates/ansi_term-0.11.0.tar.gz 100% of 16 kB 21 MBps 00m00s => rust/crates/arrayvec-0.4.7.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://crates.io/api/v1/crates/arrayvec/0.4.7/download?dummy=/rust/crates/arrayvec-0.4.7.tar.gz rust/crates/arrayvec-0.4.7.tar.gz 100% of 22 kB 3237 kBps 00m00s => rust/crates/atty-0.2.9.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://crates.io/api/v1/crates/atty/0.2.9/download?dummy=/rust/crates/atty-0.2.9.tar.gz rust/crates/atty-0.2.9.tar.gz 100% of 5898 B 81 MBps 00m00s => rust/crates/bitflags-1.0.1.tar.gz doesn't seem to exist in /usr/ports/distfiles/. [...]
The port is now ready for a test build and further adjustments like creating a plist, writing a description, adding license information, options, etc. as normal.
If you are not testing your port in a clean environment
like with Poudriere, remember to
run make clean before any testing.
Some applications define additional features in their
Cargo.toml. They can be compiled in
by setting CARGO_FEATURES in the
port.
Here we enable Tokei's json and
yaml features:
CARGO_FEATURES= json yaml
An example [features] section
in Cargo.toml could look like
this:
[features] pulseaudio_backend = ["librespot-playback/pulseaudio-backend"] portaudio_backend = ["librespot-playback/portaudio-backend"] default = ["pulseaudio_backend"]
pulseaudio_backend is a default
feature. It is always enabled unless we explicitly turn
off default features by adding
--no-default-features to
CARGO_FEATURES. Here we turn the
portaudio_backend
and pulseaudio_backend features into
port options:
CARGO_FEATURES= --no-default-features OPTIONS_DEFINE= PORTAUDIO PULSEAUDIO PORTAUDIO_VARS= CARGO_FEATURES+=portaudio_backend PULSEAUDIO_VARS= CARGO_FEATURES+=pulseaudio_backend
Crates have their own licenses. It is important to
know what they are when adding a LICENSE
block to the port (see Section 5.7, “Licenses”). The
helper target
cargo-crates-licenses will try
to list all the licenses of all crates defined in
CARGO_CRATES.
%make cargo-crates-licensesaho-corasick-0.6.4 Unlicense/MIT ansi_term-0.11.0 MIT arrayvec-0.4.7 MIT/Apache-2.0 atty-0.2.9 MIT bitflags-1.0.1 MIT/Apache-2.0 byteorder-1.2.2 Unlicense/MIT [...]
The license names
make cargo-crates-licenses outputs are
SPDX 2.1 licenses expression which do not match the
license names defined in the ports framework. They need
to be translated to the names from
Table 5.7, “Predefined License List”.
For ports that use Meson,
define USES=meson.
meson| Variable | Description |
|---|---|
MESON_ARGS | Port specific Meson
flags to be passed to the meson
binary. |
MESON_BUILD_DIR | Path to the build directory relative to
WRKSRC. Default is
_build. |
USES=meson ExampleThis snippet demonstrates the use of Meson for a port.
USES= meson MESON_ARGS= -Dfoo=enabled
For ports that use Go,
define USES=go. Refer to Section 17.35, “go” for a list of variables that can be
set to control the build process.
Creating a Go based port is a five stage process. First we need to provide a ports template that fetches the application distribution file:
PORTNAME= ghq DISTVERSIONPREFIX= v DISTVERSION= 0.12.5 CATEGORIES= devel MAINTAINER= tobik@FreeBSD.org COMMENT= Remote repository management made easy USES= go:modules USE_GITHUB= yes GH_ACCOUNT= motemen .include <bsd.port.mk>
Generate an initial
distinfo:
%make makesum===> License MIT accepted by the user => motemen-ghq-v0.12.5_GH0.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://codeload.github.com/motemen/ghq/tar.gz/v0.12.5?dummy=/motemen-ghq-v0.12.5_GH0.tar.gz fetch: https://codeload.github.com/motemen/ghq/tar.gz/v0.12.5?dummy=/motemen-ghq-v0.12.5_GH0.tar.gz: size of remote file is not known motemen-ghq-v0.12.5_GH0.tar.gz 32 kB 177 kBps 00s
Now the distribution file is ready to use and we can extract the required Go module dependencies. This step requires having ports-mgmt/modules2tuple installed:
%make gomod-vendor[...] GH_TUPLE= \ Songmu:gitconfig:v0.0.2:songmu_gitconfig/vendor/github.com/Songmu/gitconfig \ daviddengcn:go-colortext:186a3d44e920:daviddengcn_go_colortext/vendor/github.com/daviddengcn/go-colortext \ go-yaml:yaml:v2.2.2:go_yaml_yaml/vendor/gopkg.in/yaml.v2 \ golang:net:3ec191127204:golang_net/vendor/golang.org/x/net \ golang:sync:112230192c58:golang_sync/vendor/golang.org/x/sync \ golang:xerrors:3ee3066db522:golang_xerrors/vendor/golang.org/x/xerrors \ motemen:go-colorine:45d19169413a:motemen_go_colorine/vendor/github.com/motemen/go-colorine \ urfave:cli:v1.20.0:urfave_cli/vendor/github.com/urfave/cli
The output of this command needs to be pasted directly into the Makefile:
PORTNAME= ghq DISTVERSIONPREFIX= v DISTVERSION= 0.12.5 CATEGORIES= devel MAINTAINER= tobik@FreeBSD.org COMMENT= Remote repository management made easy USES= go:modules USE_GITHUB= yes GH_ACCOUNT= motemen GH_TUPLE= Songmu:gitconfig:v0.0.2:songmu_gitconfig/vendor/github.com/Songmu/gitconfig \ daviddengcn:go-colortext:186a3d44e920:daviddengcn_go_colortext/vendor/github.com/daviddengcn/go-colortext \ go-yaml:yaml:v2.2.2:go_yaml_yaml/vendor/gopkg.in/yaml.v2 \ golang:net:3ec191127204:golang_net/vendor/golang.org/x/net \ golang:sync:112230192c58:golang_sync/vendor/golang.org/x/sync \ golang:xerrors:3ee3066db522:golang_xerrors/vendor/golang.org/x/xerrors \ motemen:go-colorine:45d19169413a:motemen_go_colorine/vendor/github.com/motemen/go-colorine \ urfave:cli:v1.20.0:urfave_cli/vendor/github.com/urfave/cli .include <bsd.port.mk>
distinfo needs to be regenerated to
contain all the distribution files:
%make makesum=> Songmu-gitconfig-v0.0.2_GH0.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://codeload.github.com/Songmu/gitconfig/tar.gz/v0.0.2?dummy=/Songmu-gitconfig-v0.0.2_GH0.tar.gz fetch: https://codeload.github.com/Songmu/gitconfig/tar.gz/v0.0.2?dummy=/Songmu-gitconfig-v0.0.2_GH0.tar.gz: size of remote file is not known Songmu-gitconfig-v0.0.2_GH0.tar.gz 5662 B 936 kBps 00s => daviddengcn-go-colortext-186a3d44e920_GH0.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://codeload.github.com/daviddengcn/go-colortext/tar.gz/186a3d44e920?dummy=/daviddengcn-go-colortext-186a3d44e920_GH0.tar.gz fetch: https://codeload.github.com/daviddengcn/go-colortext/tar.gz/186a3d44e920?dummy=/daviddengcn-go-colortext-186a3d44e920_GH0.tar.gz: size of remote file is not known daviddengcn-go-colortext-186a3d44e920_GH0.tar. 4534 B 1098 kBps 00s [...]
The port is now ready for a test build and further adjustments like creating a plist, writing a description, adding license information, options, etc. as normal.
If you are not testing your port in a clean environment
like with Poudriere, remember to
run make clean before any testing.
Some ports need to install the resulting binary under a
different name or to a path other than
the default ${PREFIX}/bin. This can be
done by using GO_TARGET tuple syntax,
for example:
GO_TARGET= ./cmd/ipfs:ipfs-go
will install ipfs binary as
${PREFIX}/bin/ipfs-go and
GO_TARGET= ./dnscrypt-proxy:${PREFIX}/sbin/dnscrypt-proxywill install dnscrypt-proxy to
${PREFIX}/sbin.
For ports that use Cabal,
build system defines USES=cabal. Refer to Section 17.8, “cabal” for a list of variables that can be
set to control the build process.
When preparing a Haskell Cabal port, the devel/hs-cabal-install program is required, so make sure it is installed beforehand. First we need to define common ports variables that allows cabal-install to fetch the package distribution file:
PORTNAME= ShellCheck DISTVERSION= 0.6.0 CATEGORIES= devel MAINTAINER= haskell@FreeBSD.org COMMENT= Shell script analysis tool USES= cabal .include <bsd.port.mk>
This minimal Makefile allows us to fetch the distribution file:
%make cabal-extract[...] Downloading the latest package list from hackage.haskell.org cabal get ShellCheck-0.6.0 Downloading ShellCheck-0.6.0 Downloaded ShellCheck-0.6.0 Unpacking to ShellCheck-0.6.0/
Now we have ShellCheck.cabal package description file, which allows us to fetch all package's dependencies, including transitive ones:
%make cabal-extract-deps[...] Resolving dependencies... Downloading base-orphans-0.8.2 Downloaded base-orphans-0.8.2 Downloading primitive-0.7.0.0 Starting base-orphans-0.8.2 (lib) Building base-orphans-0.8.2 (lib) Downloaded primitive-0.7.0.0 Downloading dlist-0.8.0.7 [...]
As a side effect, the package's dependencies are also compiled, so the command may take some time. Once done, a list of required dependencies can generated:
%make make-use-cabalUSE_CABAL=QuickCheck-2.12.6.1 \ hashable-1.3.0.0 \ integer-logarithms-1.0.3 \ [...]
Haskell packages may contain revisions, just like
FreeBSD ports. Revisions can affect only .cabal
files, but it is still important to pull them in.
To check USE_CABAL items for available
revision updates, run following command:
%make make-use-cabal-revsUSE_CABAL=QuickCheck-2.12.6.1_1 \ hashable-1.3.0.0 \ integer-logarithms-1.0.3_2 \ [...]
Note additional version numbers after _
symbol. Put newly generated USE_CABAL list
instead of an old one.
Finally, distinfo needs to be regenerated to
contain all the distribution files:
%make makesum=> ShellCheck-0.6.0.tar.gz doesn't seem to exist in /usr/local/poudriere/ports/git/distfiles/cabal. => Attempting to fetch https://hackage.haskell.org/package/ShellCheck-0.6.0/ShellCheck-0.6.0.tar.gz ShellCheck-0.6.0.tar.gz 136 kB 642 kBps 00s => QuickCheck-2.12.6.1/QuickCheck-2.12.6.1.tar.gz doesn't seem to exist in /usr/local/poudriere/ports/git/distfiles/cabal. => Attempting to fetch https://hackage.haskell.org/package/QuickCheck-2.12.6.1/QuickCheck-2.12.6.1.tar.gz QuickCheck-2.12.6.1/QuickCheck-2.12.6.1.tar.gz 65 kB 361 kBps 00s [...]
The port is now ready for a test build and further adjustments like creating a plist, writing a description, adding license information, options, etc. as normal.
If you are not testing your port in a clean environment
like with Poudriere, remember to
run make clean before any testing.
All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/
Questions that are not answered by the
documentation may be
sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.