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
~/Qtdoes not provide the system-devlibraries), 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:
- Download Qt Online Installer
- 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:
- Open
project.qbsin Qt Creator - Configure kit (Qt 6 + Qbs)
- 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)