// internals

Building

Both architectures, from one tree.

x86_64

make                 # → visor_x64.efi

The Makefile finds the gnu-efi headers and crt0-efi-x86_64.o across distro layouts. If yours is unusual:

make GNU_EFI_INC=/path/to/efi CRT0=/path/to/crt0-efi-x86_64.o

Missing gnu-efi stops the build early with an explanatory message and the per-distro install command, not a cryptic compiler error.

Modular builds

Since 1.5.6 the build is driven from the feature registry in features/features.json. A PROFILE picks a canned feature set; FEATURES fine-tunes it flag-style:

make PROFILE=minimal
make PROFILE=ricer FEATURES=-blur,+capture
make PROFILE=custom FEATURES=bls,pointer,auditioning_boot

Features are listed with make list-features (which also shows the active profile and per-feature on/off state), and dependencies via make list-all-features-deps. Dropping a feature swaps in its no-op stub; features another feature depends on pull along with dependencies. make check-features re-validates the registry, the dependency graph, and the stub list against the real tree. The full features.json blurbs are what the installer & visor CLI present when choosing between profiles.

AArch64

tools/setup_gnuefi_aarch64.sh    # once: cross-builds gnu-efi for arm64
make ARCH=aarch64                # → visor_aa64.efi

Needs aarch64-linux-gnu-gcc. Distro gnu-efi packages ship x86-64 objects only, so the setup script cross-builds gnu-efi from gnu-efi-src/ and stages crt0/libs/linker script where the Makefile expects them. Builds combine ARCH= with the PROFILE/FEATURES machinery; the built-in audio driver (src/audio/hda.c) compiles to no-op stubs on AArch64 — the boot game remains x86_64.

What the build does

  1. Resolves features: a PROFILE turns into a feature set, then FEATURES=+name,-name overrides apply (with dependency closure), and every off feature pulls in its stub from src/stubs/.
  2. Compiles the feature-selected src/**/*.c freestanding: -ffreestanding -fpic -fshort-wchar -fno-stack-protector -mno-red-zone (x86) / -mstrict-align (arm), -Wall -Wextra -O2, objects into build/<arch>/. Version and the embedded VISORFT1 manifest come from PKGBUILD and the features/ registry via -DVISOR_VERSION and generated code.
  3. Links a shared object against gnu-efi with the arch linker script (src/visor_x86_64.lds / gnu-efi's arm one) and version script src/efi.vers — now including src/security/tcg2.c and src/boot/loader_iface.c.
  4. objcopy converts it to a PE (pei-x86-64 / pei-aarch64-little, subsystem 10 = EFI application).
  5. x86 only: rewrites the .reloc section with a minimal valid block and verifies its PageRVA — some binutils write a broken relocation block that firmware rejects; the build catches this instead of producing an unbootable image.
  6. Docs & tools: make also validates boot.conf.schema.json generation (via tools/tag_schema.py); host tools tools/vbg_encode.py (needs ffmpeg + python-numpy) and visor convert are installed to /usr/share/visor/tools when packaging.

Build rules of the house

Other targets

TargetPurpose
make cleanRemove objects and binaries.
make installBuild then run ./install.sh.
make list-featuresShow the active PROFILE/FEATURES, every feature with its on/off state, and the available profiles.
make list-all-featuresList all feature names, and make list-all-features-deps their dependencies.
make check-featuresValidate features/features.json, the dependency graph, and stubs against the real tree.
make bakefont FONT=/path/font.ttf FONT_PX=64Re-bake src/gui/font_jetbrains.c from a TTF (needs Python + Pillow).
make BUILD_DIR=/tmp/visor-buildBuild with objects outside the tree.