3.2. Build Variables and Environment Files

The build environment should be explicit, shell-specific, and temporary. The supplied env files keep the book's variables out of the user's normal login setup and clear common host build overrides before work begins.

Policy: put the book's variables in a dedicated build env file, not in ~/.profile, ~/.zshrc, or config.fish. When the build shell ends, the book-specific environment should end with it.

A hand-built system is easier to reason about when the environment is narrow and intentional. Exporting build variables in a normal interactive shell and forgetting about them is a reliable way to create later confusion, because the next unrelated package build or shell session inherits choices that belonged only to this project.

For that reason, this book uses shell-specific env files. They set the variables the build needs, clear the host overrides most likely to leak into toolchain work, and leave room for local customization without forcing everyone into the same directory names or mirror choices.

Provided Files

The repository includes one base env file for each supported shell and one matching example override file for local customization:

The base files establish a predictable baseline. The example override files exist for values that are site-specific or personal, such as a local source mirror, a different root directory, or custom compiler flags that should be kept separate from the defaults.

Variables Used by the Book

The environment files use LBI_ and LWI_ prefixes so the variables are obviously tied to Linux by Intent and less likely to collide with unrelated tooling.

Stopping Host Variable Leakage

The supplied env files explicitly clear common build-time variables before defining the book's defaults. In practice, that means host settings such as CC, CXX, CPPFLAGS, CFLAGS, CXXFLAGS, LDFLAGS, LD_LIBRARY_PATH, PKG_CONFIG_PATH, PKG_CONFIG_LIBDIR, and DESTDIR do not quietly bleed into the bootstrap unless the reader chooses to set them again on purpose.

The goal is not to pretend the host environment does not exist. The goal is to stop accidental host preferences from impersonating book policy.

Representative Defaults

unset CC CXX CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
unset LD_LIBRARY_PATH PKG_CONFIG_PATH PKG_CONFIG_LIBDIR DESTDIR

export LBI_ROOT="${LBI_ROOT:-$HOME/linux-by-intent}"
export LBI_SOURCES="${LBI_SOURCES:-$LBI_ROOT/sources}"
export LBI_TOOLS="${LBI_TOOLS:-$LBI_ROOT/tools}"
export LBI_BOOT="${LBI_BOOT:-/boot}"
export LBI_ESP_MOUNT="${LBI_ESP_MOUNT:-$LBI_SYSROOT/boot/efi}"
export LBI_ARCH="${LBI_ARCH:-x86_64}"
export LBI_TARGET="${LBI_TARGET:-$LBI_ARCH-lbi-linux-musl}"
export LWI_MAKE_JOBS="${LWI_MAKE_JOBS:-$(getconf _NPROCESSORS_ONLN 2>/dev/null || printf '1')}"
export LWI_MAKE_FLAGS="${LWI_MAKE_FLAGS:--j$LWI_MAKE_JOBS}"

The fish variant expresses the same policy with fish-native syntax, and the zsh variant follows the same defaults while preserving normal zsh behavior. The values themselves may be changed, but they should be changed in one of the provided env files or in a local override file, not spread across login startup files and half-remembered shell history.

Custom Variables

Local customization belongs in the matching example override file. That keeps personal choices visible and contained instead of silently becoming the documented default for everyone else.

export LWI_CFLAGS="-O2 -pipe"
export LWI_CXXFLAGS="$LWI_CFLAGS"
export LBI_CUSTOM_LDFLAGS=""
export LBI_BOOTLOADER_ID="LinuxByIntent"

Readers who already have their own variable naming scheme may keep using it if they want, but the book will speak in terms of the LBI_ variables so that examples, notes, and scripts stay internally consistent.

Reusable Build-System Functions

The base env files also define helper functions for the three most common build systems used in this project:

Each helper applies the custom directory layout defaults from section 3.1 under the /system prefix (/system/binaries, /system/systembinaries, /system/libraries, /system/headers, /system/configuration, /system/variable, and documentation paths under /system/documentation) so package installs follow the book's intended structure.

When installing from the host build environment, use DESTDIR="$LBI_ROOT" with packages configured by these helpers. The helpers already place the runtime prefix under /system.

All three helpers accept extra flags. Extra arguments are forwarded directly to the underlying tool, so you can add project-specific options without rewriting the common layout flags each time.

For lbi_meson and lbi_cmake, the first positional argument may be used as the build directory. If omitted, they default to build.

# Autotools
lbi_configure --build="$LBI_TARGET" --disable-nls

# Meson (explicit build directory)
lbi_meson build --buildtype=release -Db_lto=true

# CMake (default build directory, extra generator/flags)
lbi_cmake -G Ninja -DCMAKE_BUILD_TYPE=Release

Makeflags and Parallel Jobs

Set LWI_MAKE_FLAGS for build commands throughout the book, and keep LWI_MAKE_JOBS for tools that require a numeric job value.

Typical setup:

export LWI_MAKE_JOBS="$(getconf _NPROCESSORS_ONLN 2>/dev/null || printf '1')"
export LWI_MAKE_FLAGS="-j$LWI_MAKE_JOBS"

Choosing LBI_CUSTOM_* Values

If you want to tune builds, do it deliberately and keep notes about why. The safest path is to start simple, build once, and only then add aggressive options.

In practice, most readers are choosing between a few repeatable profiles rather than inventing flags from scratch:

Profile LWI_CFLAGS LWI_CXXFLAGS LBI_CUSTOM_LDFLAGS Best fit Main caution
Recommended starting point -O2 -pipe $LWI_CFLAGS (empty) First full build, stable troubleshooting, and easy comparison with upstream defaults. Usually not the absolute fastest result.
Portable x86-64 -O2 -pipe -mtune=generic $LWI_CFLAGS (empty) The image may move between different x86-64 systems. Gives up some CPU-specific optimization.
Native CPU tuning -O2 -pipe -march=native $LWI_CFLAGS (empty) The built system will stay on one known machine or CPU family. Less portable; failures can be harder to compare across hosts.
Debug-heavy build -O0 -g3 $LWI_CFLAGS (empty) You are chasing a toolchain, linker, or package-level failure. Produces much slower and larger binaries.
Clang ThinLTO -O2 -pipe -flto=thin $LWI_CFLAGS -fuse-ld=lld You are building with Clang and deliberately optimizing for runtime performance. Longer builds, higher toolchain sensitivity, and a hard dependency on lld.
Size-aware linking -O2 -pipe $LWI_CFLAGS -Wl,--as-needed -Wl,-O1 You want modest link-time cleanup without changing the basic compile profile. Can expose fragile upstream link ordering.

Practical rules: