6.5. Building Mechanisms

6.5.1. Building Ports in Parallel

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.

6.5.2. make, gmake, and imake

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.

6.5.3. configure Script

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.

Table 6.1. Variables for Ports That Use configure
VariableMeans
GNU_CONFIGUREThe port uses configure script to prepare build.
HAS_CONFIGURESame as GNU_CONFIGURE, except default configure target is not added to CONFIGURE_ARGS.
CONFIGURE_ARGSAdditional arguments passed to configure script.
CONFIGURE_ENVAdditional environment variables to be set for configure script run.
CONFIGURE_TARGETOverride default configure target. Default value is ${MACHINE_ARCH}-portbld-freebsd${OSREL}.

6.5.4. Using cmake

For ports that use CMake, define USES= cmake, or USES= cmake:outsource to build in a separate directory (see below).

Table 6.2. Variables for Ports That Use cmake
VariableMeans
CMAKE_ARGSPort specific CMake flags to be passed to the cmake binary.
CMAKE_ONFor each entry in CMAKE_ON, an enabled boolean value is added to CMAKE_ARGS. See Example 6.4, “CMAKE_ON and CMAKE_OFF.
CMAKE_OFFFor each entry in CMAKE_OFF, a disabled boolean value is added to CMAKE_ARGS. See Example 6.4, “CMAKE_ON and CMAKE_OFF.
CMAKE_BUILD_TYPEType of build (CMake predefined build profiles). Default is Release, or Debug if WITH_DEBUG is set.
CMAKE_SOURCE_PATHPath to the source directory. Default is ${WRKSRC}.
CONFIGURE_ENVAdditional environment variables to be set for the cmake binary.

Table 6.3. Variables the Users Can Define for cmake Builds
VariableMeans
CMAKE_VERBOSEEnable verbose build output. Default not set, unless BATCH or PACKAGE_BUILDING are set.
CMAKE_NOCOLORDisables 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 *.cmake depending on the build type (see deskutils/strigi for an example). Please note that some projects may define their own build profiles and/or force particular build type by setting CMAKE_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 can be requested by using the :outsource suffix. When enabled, 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.

Example 6.3. USES= cmake Example

This 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:outsource
CMAKE_SOURCE_PATH=	${WRKSRC}/subproject

Example 6.4. CMAKE_ON and CMAKE_OFF

When 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

Important:

This is only for the default values off CMAKE_ARGS. The helpers described in Section 5.13.3.4.2, “OPT_CMAKE_BOOL and OPT_CMAKE_BOOL_OFF use the same semantics, but for optional values.


6.5.5. Using scons

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.

6.5.6. Using cargo

For ports that use Cargo, define USES=cargo.

Table 6.4. Variables the Users Can Define for cargo Builds
VariableDefaultDescription
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).
CARGO_CARGOTOML${WRKSRC}/Cargo.tomlThe path to the Cargo.toml to use.
CARGO_CARGOLOCK${WRKSRC}/Cargo.lockThe 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_CONFIGUREyesUse 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_BUILDDEPyesAdd a build dependency on lang/rust.
CARGO_CARGO_BIN${LOCALBASE}/bin/cargoLocation of the cargo binary.
CARGO_BUILDyesUse 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_INSTALLyesUse 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_TESTyesUse 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}/targetLocation of the cargo output directory.
CARGO_DIST_SUBDIRrust/cratesDirectory relative to DISTDIR where the crate distribution files will be stored.
CARGO_VENDOR_DIR${WRKSRC}/cargo-cratesLocation 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_GITHUBnoEnable fetching of crates locked to specific Git commits on GitHub via GH_TUPLE. This will try to patch both Cargo.lock and Cargo.toml to point to the offline sources instead of fetching them from a Git repository during the build. Use with caution as transitive Git dependencies are not resolved and patched correctly.
CARGO_GH_CARGOTOML${CARGO_CARGOTOML}List of Cargo.toml that will be patched when using CARGO_USE_GITHUB.

Example 6.5. Creating a Port for a Simple Rust Application

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-crates
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 \
                [...]

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 working directory currently only contains the application sources we extracted as part of the make cargo-crates step. Before attempting to build the port the working directory must be cleaned, so that the crate sources can be extracted into CARGO_VENDOR_DIR:

% make clean
===> Cleaning for tokei-7.0.2

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.


Example 6.6. Enabling Additional Application Features

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

Example 6.7. Listing Crate Licenses

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-licenses
aho-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
[...]

Note:

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”.


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>.