BUILD(7)

πŸ“¦
version 15.1 Β· 3 versions
, in freebsd 15.1

πŸ› οΈ BUILD(7) β€” general instructions on how to build the FreeBSD system

🌸 NAME 🌸

build β€” general instructions on how to build the FreeBSD system

✨ DESCRIPTION ✨

okay bestie, gather round: the sources for the FreeBSD system and its applications live in three directories, normally:

  • /usr/src β€” the β€œbase system”, loosely defined as everything required to build the system to a useful state
  • /usr/doc β€” system documentation, excluding manual pages
  • /usr/ports β€” third-party software, with a consistent interface for building and installing them; see ports(7)

These directories may be initially empty or non-existent until updated with Git (devel/git from the FreeBSD Ports Collection).

The make(1) command is used in each of these directories to build and install the things in that directory. Issuing the make(1) command in any directory issues the make(1) command recursively in all subdirectories. With no target specified, the items in the directories are built and no further action is taken.

A source tree is allowed to be read-only. As described in make(1), objects are usually built in a separate object directory hierarchy specified by the environment variable MAKEOBJDIRPREFIX, or under /usr/obj if variable MAKEOBJDIRPREFIX is not set. The canonical object directory is described in the documentation for the buildworld target below.

The build may be controlled by defining make(1) variables described in the β€œENVIRONMENT” section below, and by the variables documented in make.conf(5).

The default components included in the build are specified in the file /etc/src.conf in the source tree. To override the default file, include the SRCCONF option in the make steps, pointing to a custom src.conf file. For more information see src.conf(5).

The following list provides the names and actions for the targets supported by the build system:

  • analyze β€” Run Clang static analyzer against all objects and present output on stdout.
  • check β€” Run tests for a given subdirectory. The default directory used is ${.OBJDIR}, but the check directory can be changed with ${CHECKDIR}.
  • checkworld β€” Run the FreeBSD test suite on installed world.
  • clean β€” Remove any files created during the build process.
  • cleandepend β€” Remove the ${.OBJDIR}/${DEPENDFILE}* files generated by prior make and make depend steps.
  • cleandir β€” Remove the canonical object directory if it exists, or perform actions equivalent to make clean cleandepend if it does not. This target will also remove an obj link in ${.CURDIR} if that exists.

It is advisable to run make cleandir twice: the first invocation will remove the canonical object directory and the second one will clean up ${.CURDIR}.

  • depend β€” Generate a list of build dependencies in file ${.OBJDIR}/${DEPENDFILE}. Per-object dependencies are generated at build time and stored in ${.OBJDIR}/${DEPENDFILE}.${OBJ}.
  • install β€” Install the results of the build to the appropriate location in the installation directory hierarchy specified in variable DESTDIR.
  • obj β€” Create the canonical object directory associated with the current directory.
  • objlink β€” Create a symbolic link to the canonical object directory in ${.CURDIR}.
  • tags β€” Generate a tags file using the program specified in the make(1) variable CTAGS. The build system supports ctags(1) and GNU Global.

The other supported targets under directory /usr/src are:

  • buildenv β€” Spawn an interactive shell with environment variables set up for building the system or individual components. For cross-building the target architecture needs to be specified with make(1) variables TARGET_ARCH and TARGET.

This target is only useful after a complete toolchain (including the compiler, linker, assembler, headers and libraries) has been built; see the toolchain target below.

  • buildworld β€” Build everything but the kernel, configure files in etc, and release. The object directory can be changed from the default /usr/obj by setting the MAKEOBJDIRPREFIX make(1) variable. The actual build location prefix used depends on the WITH_UNIFIED_OBJDIR option from src.conf(5). If enabled it is ${MAKEOBJDIRPREFIX}${.CURDIR}/${TARGET}.${TARGET_ARCH} for all builds. If disabled it is ${MAKEOBJDIRPREFIX}${.CURDIR} for native builds, and ${MAKEOBJDIRPREFIX}/${TARGET}.${TARGET_ARCH}${.CURDIR} for cross builds and native builds with variable CROSS_BUILD_TESTING set.
  • cleankernel β€” Attempts to clean up targets built by a preceding buildkernel, or similar step, built from the same source directory and KERNCONF.
  • cleanworld β€” Attempt to clean up targets built by a preceding buildworld, or similar step, built from this source directory.
  • cleanuniverse β€” When WITH_UNIFIED_OBJDIR is enabled, attempt to clean up targets built by a preceding buildworld, universe, or similar step, for any architecture built from this source directory.
  • distributeworld β€” Distribute everything compiled by a preceding buildworld step. Files are placed in the directory hierarchy specified by make(1) variable DISTDIR. This target is used while building a release; see release(7).
  • native-xtools β€” This target builds a cross-toolchain for the given TARGET and TARGET_ARCH, as well as a select list of static userland tools for the host system. This is intended to be used in a jail where QEMU is used to improve performance by avoiding emulating binaries that do not need to be emulated. TARGET and TARGET_ARCH should be defined.
  • native-xtools-install β€” Installs the results to ${DESTDIR}/${NXTP} where NXTP defaults to nxb-bin. TARGET and TARGET_ARCH must be defined.
  • packages β€” Create a freebsd-base(7) package repository containing packages that can be used to install or upgrade the base system. The repository is created in the object directory, under ${REPODIR}/${PKG_ABI} where REPODIR is the base directory where the repository will be created, and PKG_ABI is the pkg(7) ABI for the build target, for example, /usr/obj/${SRCDIR}/repo/FreeBSD:15:amd64.
  • packageworld β€” Archive the results of distributeworld, placing the results in DISTDIR. This target is used while building a release(7) and is unrelated to building freebsd-base(7) packages.
  • installworld β€” Install everything built by a preceding buildworld step into the directory hierarchy pointed to by make(1) variable DESTDIR.

If installing onto an NFS file system and running make(1) with the -j option, make sure that rpc.lockd(8) is running on both client and server. See rc.conf(5) on how to make it start at boot time.

  • toolchain β€” Create the build toolchain needed to build the rest of the system. For cross-architecture builds, this step creates a cross-toolchain.
  • universe β€” For each architecture, execute a buildworld followed by a buildkernel for all kernels for that architecture, including LINT. This command takes a long time. 😭
  • kernels β€” Like universe with WITHOUT_WORLDS defined so only the kernels for each architecture are built.
  • worlds β€” Like universe with WITHOUT_KERNELS defined so only the worlds for each architecture are built.
  • targets β€” Print a list of supported TARGET / TARGET_ARCH pairs for world and kernel targets.
  • tinderbox β€” Execute the same targets as universe. In addition print a summary of all failed targets at the end and exit with an error if there were any.
  • toolchains β€” Create a build toolchain for each architecture supported by the build system.
  • xdev β€” Builds and installs a cross-toolchain and sysroot for the given TARGET and TARGET_ARCH. The sysroot contains target library and headers. The target is an alias for xdev-build and xdev-install. The location of the files installed can be controlled with DESTDIR. The target location in DESTDIR is ${DESTDIR}/${XDTP} where XDTP defaults to /usr/${XDDIR} and XDDIR defaults to ${TARGET_ARCH}-freebsd.
  • update-packages β€” Create or update the freebsd-base(7) package repository for the base system.
    • If an old repository is being updated, then packages whose contents have not changed since the previous version will be copied into the new repository to avoid needless updating of the version number.
    • If PKG_REPO_SIGNING_KEY is defined, the repo will be signed according to pkg-repo(8).
  • xdev-build β€” Builds for the xdev target.
  • xdev-install β€” Installs the files for the xdev target.
  • xdev-links β€” Installs autoconf-style symlinks to ${DESTDIR}/usr/bin pointing into the xdev toolchain in ${DESTDIR}/${XDTP}.

Kernel specific build targets in /usr/src are:

  • buildkernel β€” Rebuild the kernel and the kernel modules. The object directory can be changed from the default /usr/obj by setting the MAKEOBJDIRPREFIX make(1) variable.
  • installkernel β€” drops the kernel and its modules into ${DESTDIR}/boot/kernel, and if there's already a directory there holding the kernel you're currently running, it gets renamed to kernel.old (no deleting your safety net, we love that πŸ’–). Wanna change where it lands under ${DESTDIR}? Use the INSTKERNNAME or KODIR make(1) variables.
  • distributekernel β€” installs the kernel into ${DISTDIR}/kernel/boot/kernel. This one's a release-building thing, so peep release(7).
  • packagekernel β€” archives whatever distributekernel produced, and chucks the result into DISTDIR. Also a release(7) era target, and it's got nothing to do with building freebsd-base(7) packages β€” don't mix them up bestie πŸ™ˆ
  • kernel β€” literally just buildkernel followed by installkernel. Two for one, iconic.
  • kernel-toolchain β€” rebuilds all the tools you need to compile a kernel. Use this when you skipped buildworld first. It's giving "I'll just do the kernel part" energy ✨
  • reinstallkernel β€” reinstalls the kernel and modules, straight-up overwriting the contents of the target directory (yes, over it, no backup behaviour here πŸ’€). Same deal as installkernel: you can point the target directory somewhere else with the make(1) variable INSTKERNNAME.

okay so there's also a whole set of convenience targets for cleaning up the install destination directory β€” that's the one held in the DESTDIR variable btw β€” and they go like this:

  • check-old β€” prints a list of old files and directories in the system. Just looks, doesn't touch πŸŽ€
  • check-old-libs β€” prints a list of obsolete base system libraries.
  • delete-old β€” actually deletes obsolete base system files and directories, interactively. Pass -DBATCH_DELETE_OLD_FILES on the command line and it stops asking β€” full non-interactive mode, no vibes check, it just goes 😭. Set the variables DESTDIR, TARGET_ARCH and TARGET the same way you would for make installworld.
  • delete-old-libs β€” deletes obsolete base system libraries, interactively. ⚠️ Only use this one if no third party software uses these libraries β€” like, fr fr, check first. Passing -DBATCH_DELETE_OLD_FILES on the command line makes the delete non-interactive. The variables DESTDIR, TARGET_ARCH and TARGET should be set as with make installworld.

✨ ENVIRONMENT ✨

The variables that influence all builds include:

  • DEBUG_FLAGS β€” defines a set of debugging flags that get used to build all userland binaries under /usr/src. And the slay part: when DEBUG_FLAGS is defined, the install and installworld targets install binaries from the current MAKEOBJDIRPREFIX without stripping, so the debugging information stays in the installed binaries. Your future self debugging at 3am says thank you 🫢
  • DESTDIR β€” the directory hierarchy prefix where built objects get installed. If you don't set it, DESTDIR defaults to the empty string. If you do set it, it must be an absolute path. no exceptions πŸ’…
  • MAKEOBJDIRPREFIX β€” defines the prefix for directory names in the tree of built objects. Defaults to /usr/obj if not defined. 🚨 Big one: this variable should only be set in the environment or in /etc/src-env.conf β€” not via /etc/make.conf, not via /etc/src.conf, and not on the command line. Also MAKEOBJDIRPREFIX must specify an absolute path.
  • WITHOUT_WERROR β€” if defined, compiler warnings will not cause the build to halt, even if the makefile says otherwise. Chill mode: enabled 🌸
  • WITH_CTF β€” if defined, the build process runs the DTrace CTF conversion tools on built objects. CTF stands for CTF, iykyk ✨

πŸ› οΈ and the make(1) variables that steer stuff in /usr/src πŸ› οΈ

Additionally, builds in /usr/src are influenced by these make(1) variables:

  • CROSS_TOOLCHAIN β€” asks for an external toolchain to build either the world or the kernel. The value can be either the full path to a file, or the base name of a file in ${LOCALBASE}/share/toolchains. That file should be a make file which sets variables requesting an external toolchain, such as XCC.

External toolchains are available in ports for both LLVM and GCC/binutils. For the ones available in ports, CROSS_TOOLCHAIN should be set to the name of the package. LLVM toolchain packages use the name llvm<major version>. GCC toolchains give you separate packages for each architecture and use the name ${MACHINE_ARCH}-gcc<major version>.

  • INSTKERNNAME β€” if set, specifies an alternative name to build and install for the various kernel make targets. Defaults to kernel.
  • KERNCONF β€” specify one or more space-separated kernels to build and install for the various kernel make targets. If you list multiple, the first kernel listed installs to /boot/${INSTKERNNAME}, and every subsequent kernel installs to /boot/${INSTKERNNAME}.NAME. If it's unset, it defaults to GENERIC β€” except on POWER architectures, where it defaults to GENERIC64 for powerpc64, and GENERIC64LE for powerpc64le. Icons only πŸ’…
  • KERNBUILDDIR β€” overrides the default directory used to grab all the opt_*.h files when building a kernel module. Super useful for stand-alone modules that depend on config(8) options. It's set automatically for modules built with a kernel.
  • KERNCONFDIR β€” overrides the directory where KERNCONF (and any files included by KERNCONF) should be found. Defaults to sys/${ARCH}/conf.
  • KERNFAST β€” if set, the buildkernel target defaults to setting NO_KERNELCLEAN, NO_KERNELCONFIG, and NO_KERNELOBJ. And when it's set to a value other than 1, then KERNCONF is set to the value of KERNFAST. Sneaky but valid πŸ¦‹
  • KODIR β€” if set, specifies an alternative directory to install the kernel into.
  • LOCAL_DIRS β€” if set, supplies a list of additional directories (relative to the root of the source tree) to build as part of the everything target. These get built in parallel with each other and with the base system directories. Drop a .WAIT directive at the beginning of the LOCAL_DIRS list to make sure all base system directories build first β€” .WAIT may also be used as needed elsewhere in the list.
  • LOCAL_ITOOLS β€” if set, supplies a list of additional tools used by the installworld and distributeworld targets.
  • LOCAL_LIB_DIRS β€” if set, supplies a list of additional directories (relative to the root of the source tree) to build as part of the libraries target. They build in parallel with each other and with the base system libraries. Insert a .WAIT directive at the beginning of the LOCAL_DIRS list to make sure all base system libraries build first β€” .WAIT may also be used as needed elsewhere within the list.
  • LOCAL_MTREE β€” if set, supplies a list of additional mtrees (relative to the root of the source tree) to use as part of the hierarchy target.
  • LOCAL_LEGACY_DIRS β€” if set, supplies a list of additional directories (relative to the root of the source tree) to build as part of the legacy target.
  • LOCAL_BSTOOL_DIRS β€” if set, supplies a list of additional directories (relative to the root of the source tree) to build as part of the bootstrap-tools target.
  • LOCAL_TOOL_DIRS β€” if set, supplies a list of additional directories (relative to the root of the source tree) to build as part of the build-tools target.
  • LOCAL_XTOOL_DIRS β€” if set, supplies a list of additional directories (relative to the root of the source tree) to build as part of the cross-tools target.
  • OBJROOT β€” the object directory root, defined as ${OBJDIR}/${SRCDIR}/. See share/mk/src.sys.obj.mk.
  • PKG_FORMAT β€” specify a package compression format when building freebsd-base(7) packages. Default: tzst. Consider using tar to disable compression entirely. The accepted options are documented in the -f description of pkg-create(8).
  • PORTS_MODULES β€” a list of ports with kernel modules that should be built and installed as part of the buildkernel and installkernel process. Heads up: this is currently incompatible with building freebsd-base(7) packages. Each port must be specified as category/port[@flavor], like:
PORTS_MODULES=graphics/gpu-firmware-intel-kmod@kabylake
PORTS_MODULES+=graphics/drm-66-kmod
  • LOCAL_MODULES β€” a list of external kernel modules that should be built and installed as part of the buildkernel and installkernel process. Defaults to the list of sub-directories of LOCAL_MODULES_DIR.
  • LOCAL_MODULES_DIR β€” the directory to search in for the kernel modules specified by LOCAL_MODULES. Each kernel module should consist of a directory containing a makefile. Defaults to ${LOCALBASE}/sys/modules.
  • SRCCONF β€” specify a file to override the default /etc/src.conf. The src.conf file controls which components get built. See src.conf(5).
  • REPODIR β€” the root directory used to create the package repository for building packges(7). Defaults to ${OBJROOT}/repo/. You can also set this in src-env.conf(5).
  • STRIPBIN β€” the command used at install time to strip binaries. Big heads-up: if STRIPBIN needs any extra tools to actually run, add them to the LOCAL_ITOOLS make(1) variable before you run distributeworld or installworld, k? See install(1) for the whole story.
  • SUBDIR_OVERRIDE β€” overrides the default list of sub-directories so you build only the sub-directory named in this variable. Careful tho: if you combine it with buildworld, all the libraries and includes plus some of the build tools will still build too. Specify -DNO_LIBS and -DWORLDFAST and it'll only build the specified directory, the way it was done historically. When you combine it with buildworld, you gotta override LOCAL_LIB_DIRS with any custom directories that contain libraries. This lets you build a subset of the system the same way buildworld does, using its sysroot handling. Also super handy when you're debugging a failed build. πŸ›
make some-target SUBDIR_OVERRIDE=foo/bar
  • SYSDIR β€” sets where the kernel source lives, overriding the default /usr/src/sys. Ngl the kernel source sits in the sys subdirectory of the source tree you checked out from the src.git repository.
  • TARGET β€” the target hardware platform, basically the uname -m output vibe. You need this to cross-build some target architectures. Like, cross-building for ARM64 machines requires TARGET_ARCH=aarch64 and TARGET=arm64. If you don't set it, TARGET defaults to the current hardware platform β€” unless TARGET_ARCH is also set, in which case it defaults to the appropriate value for that architecture. ✨
  • TARGET_ARCH β€” the target machine processor architecture, the uname -p equivalent. Set it to cross-build for a different architecture. Not set? Then TARGET_ARCH defaults to the current machine architecture, unless TARGET is also set, in which case it defaults to the appropriate value for that platform. Typically you only need to set TARGET β€” that's the main character here πŸ‘‘

πŸ› οΈ Builds under /usr/src

Builds under /usr/src are also influenced by defining one or more of these symbols, using the -D option of make(1):

  • LOADER_DEFAULT_INTERP β€” sets which interpreter the default loader program gets. Valid values are 4th, lua, and simp. This creates the default link for /boot/loader pointing at the loader with that interpreter, and it also decides which interpreter gets compiled into userboot.
  • NO_CLEANDIR β€” if set, the build targets that clean parts of the object tree use the equivalent of make clean instead of make cleandir.
  • NO_CLEAN β€” if set, no object tree files get cleaned at all. Fun fact: this is already the default when WITH_META_MODE is used with filemon(4) loaded. See src.conf(5) for more. Heads up: setting NO_CLEAN implies NO_KERNELCLEAN, so when NO_CLEAN is set, no kernel objects get cleaned either.
  • NO_CTF β€” if set, the build process doesn't run the DTrace CTF conversion tools on built objects.
  • NO_SHARE β€” if set, the build doesn't descend into the /usr/src/share subdirectory. Translation: manual pages, locale data files, timezone data files and other /usr/src/share files will not be rebuilt from their sources. 😭
  • NO_KERNELCLEAN β€” if set, the build process doesn't run make clean as part of the buildkernel target.
  • NO_KERNELCONFIG β€” if set, the build process doesn't run config(8) as part of the buildkernel target.
  • NO_KERNELOBJ β€” if set, the build process doesn't run make obj as part of the buildkernel target.
  • NO_LIBS β€” if set, the libraries phase gets skipped entirely. bye bestie πŸ‘‹
  • NO_OBJWALK β€” if set, no object directories get created. Fr only use this if object directories were created in a previous build and no new directories are connected β€” otherwise you're gonna have a bad time.
  • UNIVERSE_TOOLCHAIN β€” requests use of the toolchain built as part of the universe target as an external toolchain.
  • WORLDFAST β€” if set, the build target buildworld defaults to setting NO_CLEAN, NO_OBJWALK, and skips most bootstrap phases. It'll only bootstrap libraries and build all of userland. Only use this when you know none of the bootstrap needs changed and that no new directories have been connected to the build. Ignore that and it's giving chaos πŸ’€

πŸ“š Builds under /usr/doc

Builds under the directory /usr/doc are influenced by this make(1) variable:

  • DOC_LANG β€” if set, restricts the documentation build to the language subdirectories you list as its content. The default action is to build documentation for all languages.

Builds using the universe and related targets are influenced by these make(1) variables:

  • JFLAG β€” passes the value of this variable to every make(1) invocation used to build worlds and kernels. Use it to enable multiple jobs within a single architecture's build while still building each architecture serially.
  • MAKE_JUST_KERNELS β€” only build kernels for each supported architecture.
  • MAKE_JUST_WORLDS β€” only build worlds for each supported architecture.
  • WITHOUT_WORLDS β€” only build kernels for each supported architecture.
  • WITHOUT_KERNELS β€” only build worlds for each supported architecture.
Yep, that's genuinely what the page says β€” I'm copying it character for character because the rule is facts never change πŸ™ˆπŸ’–
  • UNIVERSE_TARGET β€” executes the specified make(1) target for each supported architecture instead of the default action of building a world and one or more kernels. This variable implies WITHOUT_KERNELS.
  • USE_GCC_TOOLCHAINS β€” uses external GCC toolchains to build the requested targets. If the required toolchain package for a supported architecture isn't installed, the build for that architecture is skipped. You can pin a specific version of GCC by setting the value of this variable to the version you want (for example, gcc14) β€” otherwise a default version of GCC is used.
  • TARGETS β€” only build the listed targets instead of each supported architecture.
  • EXTRA_TARGETS β€” in addition to the supported architectures, also build the semi-supported architectures. A semi-supported architecture has build support in the FreeBSD tree, but it gets significantly less testing and is generally for fringe uses that don't have wide appeal. Not the main character energy, but we respect the grind 🫢

πŸ“ FILES

/usr/doc/Makefile
/usr/doc/share/mk/doc.project.mk
/usr/ports/Mk/bsd.port.mk
/usr/ports/Mk/bsd.sites.mk
/usr/src/Makefile
/usr/src/Makefile.inc1             make(1) infrastructure for each tree
/usr/ports/UPDATING
/usr/src/UPDATING                  notable changes in each tree
/usr/share/examples/etc/make.conf  example make.conf(5)
/etc/src.conf                      src build configuration, see
                                   src.conf(5)

πŸ’… EXAMPLES πŸ’…

Okay bestie, this section is literally the lore drop β€” it's all the best practices for the common situations you're gonna hit. And when you do gotta do something by hand, UPDATING will tell you.

⚠️ MAKE SURE YOU HAVE FULL BACKUPS BEFORE PROCEEDING! I'm not playing, like, actually do it. 😭

πŸŽ€ Example 1: Build and upgrade system in place πŸŽ€

So if you're running installed drivers β€” think graphics drivers or virtual machine guest drivers β€” you gotta check out the ports(7) tree, and then name those drivers in src.conf(5) so they get built and installed automatically right after the kernel. Iconic shortcut, no cap:

git clone https://git.FreeBSD.org/ports.git /usr/ports
cat << EOF >> /etc/src.conf
PORTS_MODULES+=graphics/drm-kmod emulators/virtualbox-ose-kmod
EOF

Then check out the CURRENT branch, build it, and install it β€” overwriting the current system, yeah, it's giving full send:

git clone https://git.FreeBSD.org/src.git /usr/src
cd /usr/src
make buildworld buildkernel
make installkernel
shutdown -r now

For major version upgrades, boot into single-user mode. After you restart, install userspace and merge configurations. Then β€” only after you've verified you genuinely don't need them β€” delete the old files:

cd /usr/src
etcupdate -p
make installworld
etcupdate -B
make delete-old
shutdown -r now

And once you've tested the new system and confirmed your apps don't depend on them, delete the old libraries:

make delete-old-libs

🌸 Example 2: Build and upgrade a custom kernel 🌸

Make a custom kernel config, MYKERNEL, by including an existing config and using device/nodevice and options/nooption to pick and configure your components:

cd /usr/src
cat << EOF > sys/amd64/conf/MYKERNEL
include GENERIC
ident MYKERNEL
nodevice sound
EOF

Once that's done, build a fresh toolchain, build the kernel, and install it directly β€” which moves the old kernel to /boot/kernel.old/:

make kernel-toolchain
make -DALWAYS_CHECK_MAKE buildkernel KERNCONF=MYKERNEL
make -DALWAYS_CHECK_MAKE installkernel KERNCONF=MYKERNEL
shutdown -r now

If you'd rather package the kernel into a freebsd-base(7) package instead of installing it directly, use update-packages instead of installkernel β€” the way that this just works:

make buildworld buildkernel KERNCONF=MYKERNEL
make update-packages KERNCONF=MYKERNEL

And if you wanna install the kernel directly to an alternate location, use the INSTKERNNAME variable and boot it once to test it via nextboot(8):

make installkernel KERNCONF=MYKERNEL INSTKERNNAME=testkernel
nextboot -k testkernel
shutdown -r now

πŸ¦‹ Example 3: Build and upgrade a single piece of userspace πŸ¦‹

Rebuild and reinstall one single piece of userspace β€” in this case ls(1). She's small, she's mighty:

cd /usr/src/bin/ls
make clean all
make install

✨ Example 4: Build and upgrade a loadable kernel module ✨

Same energy, but for one single loadable kernel module β€” in this case sound(4):

cd /usr/src/sys/modules/sound
make all install clean cleandepend KMODDIR=/boot/kernel

πŸ”₯ Example 5: Quickly rebuild a kernel in place πŸ”₯

Quick little rebuild-and-reinstall of the kernel where it only recompiles the files that changed since your last build. Obsessed with the efficiency, but heads up:

⚠️ This only works if you've already completed a full kernel build in the past. It will not work on a fresh source tree, and that's on periodt.
cd /usr/src
make kernel KERNFAST=1

🌈 Example 6: Cross-compiling for different architectures 🌈

Wanna rebuild parts of FreeBSD for a different CPU architecture? First prep your source tree by building the cross-toolchain:

cd src
make toolchain TARGET_ARCH=aarch64

Then this little sequence right here cross-builds the whole system for the arm64 (aarch64) architecture on a totally different host architecture β€” like amd64, for example:

cd /usr/src
make TARGET_ARCH=aarch64 buildworld buildkernel
make TARGET_ARCH=aarch64 DESTDIR=/client installworld installkernel

After all that, to build and install just one piece of userspace, use:

cd src/bin/ls
make buildenv TARGET_ARCH=aarch64
make clean all install DESTDIR=/client

And likewise, to quickly rebuild and reinstall the kernel, use:

cd src
make buildenv TARGET_ARCH=aarch64
make kernel KERNFAST=1 DESTDIR=/client

πŸ’€ DIAGNOSTICS πŸ’€

If you see these, bestie, something went sideways:

Bad system call (core dumped)
rescue/sh check failed, installation aborted

Translation: the kernel was not updated, because the build procedure was incorrect. πŸ’” Go study the examples above β€” they're literally right there, you got this. 🫢


πŸ‘‘ SEE ALSO πŸ‘‘

The whole friend group: cc(1), install(1), make(1), make.conf(5), src.conf(5), arch(7), development(7), freebsd-base(7), pkg(7), ports(7), release(7), tests(7), config(8), etcupdate(8), nextboot(8), pkg-repo(8), shutdown(8)


🧚 HISTORY 🧚

The build manpage first appeared in FreeBSD 4.3. A true icon since day one. ⭐


πŸ’œ AUTHORS πŸ’œ

Mike W. Meyer <mwm@mired.org> β€” thank you for your service, king. πŸŽ€


🌺 CAVEATS 🌺

Okay, the fine print β€” but make it fashion. Read these, fr fr:

  • Old objects can cause obscure build problems; try make cleandir cleandir. πŸ™ˆ
  • Environment poisoning can cause obscure build problems; try prefixing make(1) commands with env -i.
  • When you're doing a major release upgrade, booting into single user mode for installworld is required. Not optional, not a vibe suggestion.
  • Updating the boot loader(8) is architecture specific. Consult boot(8) for your architecture for more details. πŸ¦‹

And that's the whole page, bestie! πŸŽ‰ This one came from the Debian build of the page dated April 28, 2026 β€” go forth and make buildworld responsibly. πŸ’…βœ¨

πŸ“¦ where this page comes from