Build from source

Build OctoMY™ from source code with kiln, the project's own build system, and a Qt installation. Kiln is the default build path. qbs still builds the tree too, as the second path until it retires; it has a section of its own at the end of this page.

Pro Tip

Use Qt's online installer for the cleanest setup - it includes all optional Qt modules. Package manager versions often lag behind and may be missing modules like Bluetooth or Positioning.


Prerequisites

Required software

Software Version Purpose
Qt 6.10.0+ UI framework. The floor is in integration/toolchain-requirements.json, and kiln check holds qt.qmake to it
Git Any Source control
A C++ compiler C++20 support Kiln compiles with the clang it carries, but its first compile reads the host's C and C++ headers, and a stage-0 kit builds the first kiln with the host's compiler
kiln The kiln of your checkout's commit, or newer Build system. See Step 2

Linux dependencies

Debian/Ubuntu:

# Install Qt 6 and tools
sudo apt install qt6-base-dev qt6-multimedia-dev qt6-serialport-dev
sudo apt install qt6-positioning-dev qt6-svg-dev qt6-sensors-dev
sudo apt install libqt6opengl6-dev qt6-tools-dev qt6-shadertools-dev

# The compiler and its standard library headers, and git
sudo apt install build-essential git

# Mandatory system libraries (the link step needs these -dev packages).
# The apt Qt -dev packages pull most of them in transitively, but install
# them explicitly when building against a Qt-installer ~/Qt:
sudo apt install libudev-dev libgl1-mesa-dev libglu1-mesa-dev libvulkan-dev libssl-dev

For the full mandatory-vs-optional breakdown (and the gotcha where a Qt-installer ~/Qt does not provide the system -dev libraries), see Build for Linux desktop → Prerequisites. Debian 13 ships Qt 6.8.2, below the floor, so on Debian the Qt itself comes from the Qt online installer.

Fedora:

# Install Qt 6
sudo dnf install qt6-qtbase-devel qt6-qtmultimedia-devel
sudo dnf install qt6-qtserialport-devel qt6-qtpositioning-devel
sudo dnf install qt6-qtsvg-devel qt6-qtsensors-devel

# Build tools
sudo dnf install gcc-c++ git

Arch Linux:

sudo pacman -S qt6-base qt6-multimedia qt6-serialport qt6-positioning
sudo pacman -S qt6-svg qt6-sensors qt6-tools
sudo pacman -S base-devel git

Build without a Qt installation

Kiln can build Qt itself from its pinned source (Build through the kiln queue). Then no Qt installer, CMake or Ninja is needed. Qt's configure looks for the system's development libraries instead, as Qt's own build does. A library that is missing turns off what needs it: Qt's configure says each feature it turned off and why, and the modules or features of OctoMY™ that need it are off too.

Debian/Ubuntu (the list Debian 13 was measured with):

sudo apt install build-essential git pkgconf libgl1-mesa-dev libglu1-mesa-dev libvulkan-dev libssl-dev libudev-dev libzstd-dev libicu-dev libdbus-1-dev libkrb5-dev libcups2-dev libatspi2.0-dev libgtk-3-dev libdrm-dev libgbm-dev libwayland-dev libwayland-bin wayland-protocols libxcb1-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-shape0-dev libxcb-shm0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev libxcb-xkb-dev libxcb-cursor-dev libxcb-glx0-dev libxcb-xinput-dev libxcb-util-dev libx11-xcb-dev libxkbcommon-dev libxkbcommon-x11-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libva-dev libpulse-dev libasound2-dev libpipewire-0.3-dev libspa-0.2-dev libbluetooth-dev libpcsclite-dev

Fedora:

sudo dnf install gcc-c++ git pkgconf mesa-libGL-devel mesa-libGLU-devel vulkan-loader-devel openssl-devel systemd-devel libzstd-devel libicu-devel dbus-devel krb5-devel cups-devel at-spi2-core-devel gtk3-devel libdrm-devel mesa-libgbm-devel wayland-devel wayland-protocols-devel libxcb-devel xcb-util-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-renderutil-devel xcb-util-wm-devel xcb-util-cursor-devel libX11-devel libxkbcommon-devel libxkbcommon-x11-devel ffmpeg-free-devel libva-devel pulseaudio-libs-devel alsa-lib-devel pipewire-devel bluez-libs-devel pcsc-lite-devel

Arch Linux:

sudo pacman -S base-devel git pkgconf mesa glu vulkan-icd-loader vulkan-headers openssl systemd zstd icu dbus krb5 libcups at-spi2-core gtk3 libdrm wayland wayland-protocols libxcb xcb-util xcb-util-image xcb-util-keysyms xcb-util-renderutil xcb-util-wm xcb-util-cursor libx11 libxkbcommon libxkbcommon-x11 ffmpeg libva libpulse alsa-lib pipewire bluez-libs pcsclite

The Debian list is the one the vendored Qt was built with, on Debian 13. The Fedora and Arch lists name the same libraries by those distributions' package names; no build has run on them yet.

Qt installation via Qt Installer

For the latest Qt with all modules:

  1. Download Qt Online Installer
  2. Run and select:
    • Qt 6.x for Desktop
    • Qt Creator
    • Qt Debug Information Files (optional)

Step 1: Clone the repository

# Clone with submodules
git clone --recursive https://github.com/mrdeveloperdude/OctoMY.git
cd OctoMY

# If already cloned without --recursive
git submodule update --init --recursive

kiln fetch and kiln bootstrap, below, fetch a commit without the git command.


Step 2: Get a kiln

Kiln builds the tree without qbs, without a compiler or linker on the machine, and without the git command: it carries clang, lld and the part of git it needs. What it still needs is the operating system, a Qt installation, a network path to the source, and on Windows the Build Tools and the Windows SDK.

First look for the kiln the machine already has. A machine that builds this project runs one kiln broker for each account, and you build with its kiln. Step 1 of Start here says where its door file names that kiln, and where a build site keeps its kiln when no broker runs. Get a kiln of your own only when the machine has none.

No release ships kiln yet. Get your first kiln in one of two ways:

  • The standalone kiln. A tree with kiln and the Qt libraries that it links. Unpack it anywhere and run bin/kiln. It needs a C++ compiler and the standard library headers, because its first compile captures the host's headers into the tree. It is for Linux x64.
  • A stage-0 kit. A Makefile and a bash script that kiln writes from its own build plan. The kit builds kiln with the compiler and Qt you already have, and needs no qbs.

The build farm will publish both for each main commit on the kiln page of the download site. Anyone with a kiln makes the standalone kiln with kiln package kiln <folder>:

sha256sum -c kiln-<commit>-linux-x64.tar.gz.sha256
tar -xzf kiln-<commit>-linux-x64.tar.gz
kiln-<commit>-linux-x64/bin/kiln --version

To build kiln from a kit instead:

What the machine needs for that one build: bash, GNU make, a C++ compiler (GCC or clang), Qt 6 with Qt Svg, zlib's development package (zlib1g-dev on Debian and Ubuntu), and curl or wget with tar for the pinned LLVM sources. Take the kit of the commit you build. Anyone with a kiln writes one with kiln kit write <folder>. Then:

sha256sum -c kiln-stage0-<commit>.tar.gz.sha256
tar -xzf kiln-stage0-<commit>.tar.gz
kiln-stage0-<commit>/bootstrap.sh --checkout ~/octomy \
    --qmake ~/Qt/6.11.1/gcc_64/bin/qmake6

The script checks your tools and your checkout first and says what is missing, fetches and verifies the LLVM sources, and builds. It prints where the new kiln is. --check-only stops after the checks, and --archive llvm=<file> uses an LLVM archive you already have. If you have no kit but a working qbs, the second path, qbs build -p kiln config:release also builds kiln: kiln cannot build the first kiln, so this is the one job left where qbs stands in for it.

On Windows the kit is a Windows kit: write it on Windows, or elsewhere with kiln kit write <folder> --os windows. It runs in Git Bash and needs clang from LLVM's Windows release (clang+llvm-<version>-x86_64-pc-windows-msvc, which also brings llvm-ar and lld-link), the Visual Studio Build Tools with the Windows SDK, a GNU make built for Windows (ezwinports' make 4.4.1 works; MSYS2's make does not read C: in a path), and Qt for MSVC:

bash kiln-stage0-<commit>/bootstrap.sh --checkout C:/src/octomy \
    --qmake C:/Qt/6.10.1/msvc2022_64/bin/qmake.exe \
    --cxx C:/llvm/bin/clang++.exe --make C:/make/bin/make.exe

The first kiln is kiln.exe, with the Qt DLLs it links and a qt.conf beside it, so it starts without Qt on PATH.

A kiln reads the .kiln files of a newer checkout. It sets aside a key that it does not know, and says so with the file and the line. A key in the root .kiln changes nothing that kiln builds. A key in the .kiln of a product leaves that product out, and each program that links it. A kiln built before 2026-10-13 refuses the whole checkout for one such key. In each case, get the standalone kiln or the kit of the checkout's commit, as above.

Fetch, provision and build in one command

One command fetches a commit, provisions the pinned source trees the build uses (LLVM, the validation layer and the rest), and builds and installs every program the install tree holds:

kiln bootstrap https://gitlab.com/octomy/octomy.git main ~/octomy-kiln \
    --qmake ~/Qt/6.11.1/gcc_64/bin/qmake6

main can be a branch, a tag or a commit. The programs land in ~/octomy-kiln/release/install-root/usr/local/bin. The command writes the Qt it was given into ~/octomy-kiln/.kiln.local, the file for this machine's settings, so later commands in that folder need no flag:

cd ~/octomy-kiln
kiln test --variant release          # every suite, each held to its contract
kiln build src/construct             # one program, in debug
kiln package deb                     # the Debian package, as the release builds it

Step 3: Check the checkout

In the checkout, run kiln check, then each command that it gives, until its last line is next: kiln build:

kiln check

It checks that you run the machine's kiln, that the broker answers, that .kiln.local exists and git ignores it, that qt.qmake names a Qt that meets the floor, that the build folder has room, and that the pinned source trees are there (kiln vendor writes them). It changes nothing itself. Step 2 of Start here shows what it prints.


Step 4: Build the project

# Every product, in debug
kiln build

# The main applications, and what they link
kiln build src/hub src/agent src/remote

# Every product, in release
kiln build --variant release

# Build, then lay out the install tree
kiln build --install

A build that can take more than 10 minutes, a first build of the whole tree for one, runs best detached, and kiln progress follows it. Steps 4 and 5 of Start here give the commands.

Every compile and link goes through the kiln broker, which keeps the machine usable while it builds. kiln status says what runs and what waits; the kiln reference lists every command and key.

Optional features

Kiln builds a feature when its Qt modules and its pinned source tree are there, and leaves its products out with one line when they are not. kiln vendor writes the pinned trees. A build option of the project is an option.<name> key: set it for this machine in .kiln.local, for example option.enableLto = off. The options and what each does are in the kiln reference.


Step 5: Build output

With no output.dir in .kiln.local, a debug build goes into debug/ in the checkout:

debug/
├── install-root/          # after kiln build --install
│   └── usr/local/bin/
│       ├── agent          # Agent executable
│       ├── remote         # Remote executable
│       ├── hub            # Hub executable
│       └── zoo            # Zoo executable
└── <product>/
    └── <product>          # each program, where it was linked

A release build goes into release/. The whole convention is in Start here → The build convention.

Run built applications

Start applications from the install tree, because the hub finds the other programs beside itself:

# Run Agent
./debug/install-root/usr/local/bin/agent --personality Test

# Run Remote
./debug/install-root/usr/local/bin/remote --personality Test

# Run with debug output
./debug/install-root/usr/local/bin/agent --debug

Build specific targets

Give kiln build the folder of each product. It builds them in one plan, with what they link:

# Build only the Agent
kiln build src/agent

# Build and run every suite under test/
kiln test

kiln build --dry-run says what a build would run, and kiln explain <folder> gives a product's settings and sources.


Cross-Compilation

Android build

kiln build --os android src/hub                  # needs android.ndk in .kiln.local
kiln package apk src/hub --arch arm64            # the signed package

The kiln reference lists what --os android needs, and Build for Android has the details.

Raspberry Pi (ARM)

kiln build --arch arm64                          # needs linux.sysroot in .kiln.local

Build options

Branding

Every build carries the edition in integration/editions/octomy/ — names, palette seed colors, logo — which the root .kiln names in edition.dir. To brand a build as something else, see Build a branded edition.


Clean build

There is nothing to clean before a build: kiln rebuilds what changed, and a compile it already did comes from its object cache. To start a build folder from nothing, delete it while no build of yours runs:

rm -rf debug/

kiln clean --report lists the build folders of the machine and how large each is (Find build storage to reclaim).


IDE integration

A compile database

kiln commands prints every compile that a build would run, as a compile database for an editor or a language server:

kiln commands > compile_commands.json

Qt Creator

Qt Creator builds through qbs, the second path:

  1. Open project.qbs in Qt Creator
  2. Configure kit (Qt 6 + Qbs)
  3. Build and run from IDE

Visual Studio Code

Install extensions:

  • C/C++ (Microsoft)
  • Qbs Tools, only to build with qbs

Configure settings.json:

{
    "qbs.qbsPath": "/usr/bin/qbs",
    "qbs.settingsDirectory": "~/.config/QtProject/qbs"
}

Troubleshooting

"Qt not found"

# What kiln finds, and the line that corrects it
kiln check

# Verify the Qt installation
qmake6 --version

"Module not found"

# Install missing Qt module
sudo apt install qt6-<module>-dev

# Example for Bluetooth
sudo apt install qt6-connectivity-dev

"kiln: no kiln broker is listening"

The broker could not start. See When a build says it cannot reach the broker.

Build fails with OpenGL

# Install OpenGL development files
sudo apt install libgl1-mesa-dev libglu1-mesa-dev

Build with qbs (the second path)

qbs builds the same tree until it retires, and some legs of the build farm and Qt Creator still use it. This section keeps its steps. The facts of the qbs path are in Qbs reference → The qbs build convention.

What qbs needs

Software Version Purpose
Qbs 3.3.1+ Build system. No distribution ships it; build it from source (Build for Linux desktop → Qbs from source)
GCC/Clang C++20 support Compiler
mold Any The linker of a qbs debug build
lld Any Only for a qbs release build with link-time optimization
sudo apt install build-essential mold lld

Configure Qbs

# Configure Qbs to use your Qt installation
qbs setup-toolchains --detect

# Setup Qt profile
qbs setup-qt /path/to/qmake qt6

# List available profiles
qbs config --list profiles

For Qt installed via package manager:

qbs setup-qt /usr/bin/qmake6 qt6

For Qt installed via Qt Installer:

qbs setup-qt ~/Qt/6.11.1/gcc_64/bin/qmake qt6

Verify the configuration:

qbs config profiles.qt6.baseProfile
# Should show: gcc or clang

Resolve (first time and after file changes)

The qbs build uses cached file discovery — source files are scanned once during qbs resolve and cached across subsequent builds. This reduces incremental build overhead from ~2 minutes to ~3 seconds.

# First resolve (scans all source directories, runs probes)
qbs resolve

# Force re-scan (e.g. after checking out a different branch)
qbs resolve --force-probe-execution

When to re-run qbs resolve:

  • After adding or removing .cpp, .hpp, .ui, or resource files
  • After regenerating the dependency manifest (cross-library includes changed)
  • After checking out a branch with different files
  • After enabling/disabling features in oc_use.json

Build

# Build main applications
qbs build --products hub,agent,remote

# Build everything (all libs, apps, tests)
qbs build

# Debug or release
qbs build config:debug      # Default: -g -O0
qbs build config:release    # Optimized: -O2

A qbs build lands in default/, and its programs in default/install-root/usr/local/bin/.

File cache modes

The project.fileCacheMode property controls source file discovery:

Mode Behavior Use case
"cached" (default) Files scanned at resolve time, cached across builds Normal development
"never" Native Qbs globs on every build (~2 min overhead) Debugging file discovery issues
# Bypass cache for one build
qbs build project.fileCacheMode:"never"

Dependency manifest

Cross-library #include paths of the qbs build are managed by integration/qbs/dep_manifest.json. When you add an #include that references a header from another library, regenerate the manifest from the repository root, then resolve again:

kiln build src/tools/analyze-deps
debug/analyze-deps/analyze-deps
qbs resolve --force-probe-execution

The manifest is a file of the qbs build, and a qbs build checks that it is current, so keep it current while qbs is a build path.

Optional features (oc_use.json)

Create oc_use.json in the project root (gitignored) to disable expensive features of a qbs build per workstation. Kiln does not read it:

{
  "llvm": false,
  "webEngine": false,
  "multimedia": false,
  "fem": false
}

Available keys: bluetooth, positioning, sensors, serialPort, webSockets, webEngine, pdf, multimedia, llvm, fem, llama, kwin, rl.

Project properties

Property Default Description
project.fileCacheMode "cached" Source file discovery: "cached" or "never"
project.resolveTests true Include test products in resolve
project.qbsDebugOutput false Verbose Qbs debug logging
project.wantBluetooth true Enable Bluetooth support
project.wantMultimedia true Enable audio/video
project.wantWebEngine true Enable WebEngine
project.wantLlvm true Enable LLVM compiler toolchain
project.wantFem true Enable FEM/mesh/watermark
qbs build project.wantWebEngine:false project.wantLlvm:false

A qbs build is branded with project.editionDir; see Build a branded edition.

Build specific targets

# List available products
qbs list-products -f project.qbs

# Build only the Agent
qbs build -f project.qbs profile:qt6 -p agent

# Build only tests
qbs build -f project.qbs profile:qt6 -p "test*"

Cross-compilation with qbs

# Android: set up an NDK profile, then build
qbs setup-android --ndk-dir ~/Android/Sdk/ndk/25.1.8937393 android
qbs build -f project.qbs profile:android

# ARM: detect the toolchains, then build
qbs setup-toolchains --detect
qbs build -f project.qbs profile:arm-linux

Clean a qbs build

# Clean build artifacts
qbs clean -f project.qbs

# Full clean (removes build directory)
rm -rf default/

# Clean and rebuild
qbs clean && qbs build -f project.qbs profile:qt6

qbs troubleshooting

# "Qt not found": check the Qbs profile, and set it again
qbs config profiles.qt6
qbs setup-qt $(which qmake6) qt6

# Compiler errors: check the compiler version (need C++20, GCC 10+ or Clang 11+)
g++ --version

"qbs: command not found". Build qbs 3.3.1 or newer from source (Build for Linux desktop → Qbs from source). The qbs of a distribution and the one bundled with Qt Creator are older than the floor.


Dependencies reference

Core Qt modules

Module Package Purpose
Qt Core qt6-base-dev Core functionality
Qt GUI qt6-base-dev Graphics
Qt Widgets qt6-base-dev UI components
Qt Network qt6-base-dev Networking

Optional Qt modules

Module Package Feature
Qt Bluetooth qt6-connectivity-dev Bluetooth
Qt Multimedia qt6-multimedia-dev Audio/Video
Qt SerialPort qt6-serialport-dev Arduino
Qt Positioning qt6-positioning-dev GPS
Qt Sensors qt6-sensors-dev IMU

Third-party libraries

OctoMY™ includes these as submodules:

  • mbedTLS (cryptography)
  • QMapControl (maps)
  • QHexEdit (binary editor)
  • Hoedown (Markdown)

In this section