Which Path Do I Want?

I want to…UseSection
put OCTAVE in a car or just run ita pre-built release binaryInstalling a Pre-built Release
change the code, run the developer tools, or build for Androidthe C++ tree with CMakeBuilding from Source / Android Build

System Requirements

RequirementMinimumNotes
OS Windows 10+, macOS, Linux (x86_64 or aarch64), Android 11+ Raspberry Pi OS / Orange Pi (Debian-based) supported. macOS releases are built on macOS 14 against Qt 6.7.3.
C++ toolchain (source builds only) CMake 3.21+, Qt 6.7.3, a C++17 compiler GCC 11+ / Clang 14+ / MSVC 2022. Qt modules: Multimedia, SerialPort, Connectivity, Qt5Compat, optionally Quick3D + QuickTimeline and WebEngine. See Build Dependencies and Building.
Display Responsive layout src/main.cpp divides the shorter available screen edge by 720, clamped to 0.4–3.0; the user scale is applied on top.
Audio Working system audio output Playback is provided by Qt Multimedia; available codecs and outputs depend on the installed Qt backend.
Network Optional Needed for update checks. Local playback, OBD and phone mirroring work offline.

Installing a Pre-built Release

The current CI release workflow builds the packages on the GitHub Releases page from the C++ tree. No toolchain needed.

PlatformFileInstall
WindowsOCTAVE-<version>-windows-x86_64.exeRun the Inno Setup installer. Bundles Qt, TagLib, FFmpeg DLLs and adb.
macOSOCTAVE-<version>-macos.dmgOpen, drag to Applications. adb is inside the bundle.
Linux x86_64OCTAVE-<version>-linux-x86_64.AppImagechmod +x and run. CI builds on Ubuntu 22.04; runtime compatibility also depends on the host graphics, audio, and system libraries. Arch may need fuse2, or use --appimage-extract-and-run.
Linux aarch64 (Pi / Orange Pi)OCTAVE-<version>-linux-aarch64.AppImageSame as above. Install the distro's adb (sudo apt install adb) if you want phone mirroring — Google ships no aarch64 platform-tools.
AndroidOCTAVE-<version>-android-arm64-v8a.apkSideload. The workflow uses a persistent release key when signing secrets are available. An update must use the same key as the installed app; older releases and builds without the secrets can have different keys. Back up app data before any required uninstall.

Building from Source

A desktop build needs CMake 3.21+, Qt 6.7.3 (the CI-pinned version) with the Multimedia, SerialPort, Connectivity and Qt5Compat modules, TagLib, and optionally FFmpeg (libavcodec/libavutil, for the built-in phone-mirror decoder), Qt Quick 3D (for the 3D vehicle view) and Qt WebEngine (for the in-app wiki viewer). The per-platform steps follow; BUILD.md is the full guide.

# Get the source
git clone https://github.com/RobDeGeorge/OCTAVE.git
cd OCTAVE

# Configure + build (Debug, current platform)
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j

# Run — the binary finds frontend/ one directory up from build/
./build/octave            # Linux
# macOS: stage the frontend, then run
cp -R frontend build/octave.app/Contents/MacOS/
./build/octave.app/Contents/MacOS/octave # macOS
# Windows PowerShell: stage the frontend, then run
Copy-Item -Recurse -Force frontend build/Debug/
./build/Debug/octave.exe  # Windows (MSVC multi-config)

For the Windows multi-config and macOS bundle layouts, stage the runtime frontend before launching. In PowerShell, run Copy-Item -Recurse -Force frontend build/Debug/ for the Debug executable (use build/Release/ for Release). On macOS, run cp -R frontend build/octave.app/Contents/MacOS/. Refresh these copies after QML or asset changes. Linux's build/octave finds the checkout's frontend one level up.

A Debug build also turns on OCTAVE_DEV_TOOLS (the --dev / --profile tooling, see Developer Mode) and OCTAVE_BUILD_TESTS (the QtTest suite, run with ctest --test-dir build; see Testing). A Release build has neither.

CMake reports Built-in phone mirror decoder (libavcodec): ON/OFF and whether QtQuick3D was found at configure time; both are optional and the app degrades gracefully without them (phone mirroring unavailable without FFmpeg, greyed-out "3D View" card without Quick3D). Per-platform package lists, the AppImage / DMG / Inno Setup packaging that CI runs, and the pinned tool versions are in BUILD.md and on the Building & CI/CD page.

QML is loaded from disk
Desktop builds load frontend/Main.qml from disk at runtime rather than compiling it in, so a QML change is visible on the next launch when the app loads that checkout directly; refresh staged Windows/macOS frontend copies first. Android bundles the directory as assets:/frontend, so QML changes there require a new APK.

Linux

Linux is the primary development and deployment platform. On Debian / Ubuntu, install the toolchain and libraries (this is the package set the cpp-compile-check CI job uses on Ubuntu 22.04, plus the XCB runtime libraries from BUILD.md), then Qt 6.7.3 from the Qt online installer or aqtinstall. Distro Qt is too old on Ubuntu 22.04 (6.2 lacks QtQuick.Effects), so use the pinned version:

sudo apt install -y build-essential cmake ninja-build pkg-config \
  libtag1-dev libavcodec-dev libavutil-dev libgl1-mesa-dev libegl1-mesa-dev \
  libxkbcommon-dev libpulse-dev libssl-dev libfontconfig1 libdbus-1-3 \
  libxcb-cursor0 libxcb-xinerama0 libxcb-icccm4 libxcb-image0 \
  libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 \
  libxcb-shape0 libxcb-sync1 libxcb-xfixes0 libxcb-xkb1

pipx install aqtinstall
aqt install-qt linux desktop 6.7.3 linux_gcc_64 -O ~/Qt \
    -m qtmultimedia qtserialport qtconnectivity qtsensors qtquick3d qt5compat qtshadertools qtquicktimeline

export PATH="$HOME/Qt/6.7.3/gcc_64/bin:$PATH"
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j
./build/octave

Arch Linux / Manjaro / EndeavourOS

Arch's Qt is current enough to build against directly. You need cmake, ninja, taglib and ffmpeg plus the Qt 6 modules listed above (qt6-multimedia, qt6-serialport, qt6-connectivity, qt6-5compat, optionally qt6-quick3d and qt6-webengine). qt6-quick3d additionally needs assimp: without Qt's assimp asset-import plugin the Jeep model silently fails to load with Failed to load asset import plugin with key: "assimp".

Raspberry Pi / Orange Pi

For an aarch64 board the simplest path is the linux-aarch64 AppImage from the releases page; to build on the board, follow the Debian steps with aqt install-qt linux_arm64 desktop 6.7.3 .... Google ships no aarch64 platform-tools, so install the distro's adb (sudo apt install adb) for phone mirroring. The author's Jeep runs an Orange Pi 5 Plus; its boot, system and session configuration is kept as a reference in deployment/orange-pi-5-plus/. See Hardware Setup for I²C sensors and the ESP32 knob.

Serial devices (OBD adapters, ESP32 knob)
On Linux, add your user to the dialout group so USB serial and Bluetooth rfcomm devices are accessible without root:
sudo usermod -a -G dialout $USER
Log out and back in for the change to take effect.

Windows

Install Visual Studio 2022 with the "Desktop development with C++" workload, Qt 6.7.3 for MSVC from the Qt online installer, and vcpkg for TagLib and FFmpeg (vcpkg install taglib:x64-windows "ffmpeg[core,avcodec]:x64-windows", as CI does). Then, in PowerShell:

cmake -S . -B build `
  -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" `
  -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j
Copy-Item -Recurse -Force frontend build/Release/
./build/Release/octave.exe

Visual Studio is a multi-config generator, so OCTAVE_DEV_TOOLS defaults to off there; pass -DOCTAVE_DEV_TOOLS=ON to get --dev / --profile. CI packages the build with windeployqt and the Inno Setup script build_scripts/installer_windows.iss.

macOS

xcode-select --install
brew install taglib ffmpeg pkg-config

pipx install aqtinstall
aqt install-qt mac desktop 6.7.3 -O ~/Qt \
    -m qtmultimedia qtserialport qtconnectivity qtsensors qtquick3d qt5compat qtshadertools qtquicktimeline

export PATH="$HOME/Qt/6.7.3/macos/bin:$PATH"
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
cp -R frontend build/octave.app/Contents/MacOS/
./build/octave.app/Contents/MacOS/octave

The output is build/octave.app; CI turns it into the .dmg with macdeployqt. Apple Silicon and Intel are both supported.

Android Build

The Android app is built from the C++ / Qt 6 tree in src/ as a native .apk for arm64-v8a (Android 11+, minSdk 30, package org.octave.app) — the same code as the desktop build, with mobile-specific parts behind Q_OS_ANDROID.

Full toolchain lives in BUILD.md
The complete step-by-step Android setup — Qt for Android 6.7.3 via aqtinstall, OpenJDK 17, the Android SDK + NDK 26.1.10909125, environment variables (QT_HOST_PATH is required), and APK signing — is documented in BUILD.md under Android build. The summary here is orientation only.

Prerequisites

  • Linux host with roughly 40–60 GB free on the $HOME disk
  • Qt for Android 6.7.3 (android_arm64_v8a) plus the matching host Qt (gcc_64) for androiddeployqt
  • OpenJDK 17 — the version used by OCTAVE's APK CI job; this checkout pins Android Gradle Plugin 7.4.1
  • Android SDK (platform android-33, Build-Tools 33.0.2) and NDK 26.1.10909125

Build the APK

With the toolchain environment variables set (see BUILD.md), configure with Qt's qt-cmake cross-compile wrapper and build the apk target. OpenSSL for Android is bundled from android/openssl/<abi>/ through QT_ANDROID_EXTRA_LIBS:

qt-cmake -S . -B build-android \
    -DCMAKE_BUILD_TYPE=Debug \
    -DANDROID_ABI=arm64-v8a \
    -DANDROID_PLATFORM=android-30 \
    -DQT_ANDROID_SIGN_APK=OFF

cmake --build build-android --target apk -j
adb install build-android/android-build/build/outputs/apk/debug/android-build-debug.apk

CI builds Release. It uses the persistent release key when signing secrets are available, otherwise a temporary key. INSTALL_FAILED_UPDATE_INCOMPATIBLE means the installed app uses a different key. Use a build signed with the same key, or back up settings before uninstalling the old app.

Android Feature Differences

On Android, desktop-only managers are compiled as stub classes behind Q_OS_MOBILE so the QML keeps working, and Android-specific code sits behind #ifdef Q_OS_ANDROID. The desktop ↔ Android split:

FeatureDesktopAndroid
OBD-II USB or Bluetooth-SPP ELM327 through a serial port (/dev/ttyUSB*, /dev/rfcomm0, COMn) BLE ELM327 through a native BluetoothGatt JNI bridge (android/src/org/octave/app/OctaveOBDBridge.java)
IMU BerryIMU v3 over I²C Device's own sensors via QtSensors (accelerometer, compass, pressure)
Gesture sensor, ESP32 knob PAJ7620U2 over I²C; ESP32 over USB serial Not applicable (stubs)
Phone mirror, Android Auto Built-in scrcpy-protocol client; Android Auto through the built-in head unit (beta, needs OpenSSL at build time) or the experimental DHU integration (see Android Auto) Not applicable (stubs)
Local media, dashboards, theming, diagnostics Same on both (runtime permissions READ_MEDIA_AUDIO / BLUETOOTH_* are requested at first launch on Android)

Running OCTAVE

Standard Mode

./build/octave

A release install runs the same binary from its installed location (the Start-menu entry, the app bundle, or the AppImage).

Command-Line Flags

FlagEffect
--debugDEBUG-level output and the extra rotating debug log octave-cpp-debug.log in the config directory's logs/ folder; without it, debug messages are filtered at the source.
--smokeLoad Main.qml, run 5 s (startup work, page pre-building), then exit 0. A build that cannot start exits non-zero or never starts; CI and the tst_boot test use it.
--simA simulated car behind the real OBD stack, IMU motion and three test tracks, driven by the sim service object, on a throwaway config deleted at exit (unless --config). Any build; with --headless, what a frontend author starts from (Writing a Frontend).
--qmlThe built-in QML UI for this run, even when an installed exec frontend is the screen (Installing Your Frontend).
--pair-codePrint a pairing code from the running OCTAVE (same user; same --config if it has one) and exit, 1 if none runs. For pairing devices while no Settings page is on screen (an exec frontend, --headless). The channel is a local socket only that user can open (src/service/adminchannel.h), never on the network.
--config DIRKeep settings, trips, dashboards and logs in DIR instead of the OS config folder.
--dev--sim on your usual config, plus the dev overlay (Developer Mode). Needs an OCTAVE_DEV_TOOLS build.
--profilePerf monitor and command server on 127.0.0.1:9876. Needs an OCTAVE_DEV_TOOLS build.
--command-port NAnother port for the command server.
--service [PORT]The service protocol on 127.0.0.1:9876 (or PORT) for another frontend or a script, in any build; open http://127.0.0.1:9876/ in a browser for the reference web client (sdk/). Off by default; the serviceEnabled setting turns it on at every start.
--headlessEvery manager and the service, no QML engine and no window (the offscreen platform unless QT_QPA_PLATFORM says otherwise). Implies --service: another frontend, a script or the SDK drives it. Desktop and the Pi only; --profile is ignored with it (--sim and --dev are not), and phone-mirror / Android Auto video is not decoded, only streamed to clients.
--dump-api DIRWrite the published API (Service API Reference) as JSON into DIR and exit. Builds the managers in a throwaway config directory, so your settings and trip history are untouched.
--service-bind ADDRESSListen on ADDRESS instead of loopback (0.0.0.0: every interface). A client from the network gets nothing but hello and pair until it pairs with a code from Settings > Device > Service; still, only on a network you trust.
--web-root DIRServe DIR (a built web frontend with index.html) at GET / instead of the reference client, same-origin with the service.
--version, --helpPrint the version, or every flag, and exit.
./build/octave --debug
./build/octave --smoke; echo $?

Performance Profiling

./build/octave --profile     # real OBD, perf monitor + command server

Starts the PerfMonitor (CSV + log under dev/perf/logs/, exposed to QML as perfMonitor), a command server on 127.0.0.1:9876 for remote control and the MCP tools, and times the hot paths marked with OCTAVE_PERF_SCOPE. The code is src/dev/, compiled in by the OCTAVE_DEV_TOOLS CMake option (on by default only for -DCMAKE_BUILD_TYPE=Debug); other builds ignore --dev / --profile with a warning. See Performance Profiling.

Developer Mode

Developer mode provides a simulated car and keyboard controls for testing without hardware or a vehicle. It is a flag on an OCTAVE_DEV_TOOLS build: the real OBDManager talks to a simulated ELM327 adapter, so the shipped OBD code runs against the simulation. The simulated car on its own is --sim (src/sim/), which every build has, release downloads included. The in-app half (src/dev/) is committed. The client tools that drive it over the command server (screenshot / story recorder, MCP servers, perf scripts, all Python scripts in dev/) are gitignored: they exist on the maintainers' machines but are not part of a fresh clone.

./build/octave --dev
./build/octave --dev --profile     # + command server: what the screenshot / MCP tooling launches
Dev Mode Features
  • Simulated OBD data: RPM, speed, temperatures, throttle, trouble codes, VIN; optional simulated IMU motion
  • Development tools panel and overlay
  • Keyboard driving (W/S throttle and brake, Space rev, E engine, F1–F4 scenarios, Tab hides the HUD)
  • Screenshot and story-driven clip recording (python -m dev.screenshots), MCP server for agents
See Development.

Build Dependencies

CMakeLists.txt
DependencyRequired?Purpose
Qt 6.7.3: Core, Gui, Qml, Quick, QuickControls2, Multimedia, Network, Concurrent, SerialPort, BluetoothyesThe app itself; Sensors is added on Android
Qt5Compat, Qt Quick Effectsat runtimeQt5Compat.GraphicalEffects and QtQuick.Effects are imported by the QML; a Qt without them builds and then fails at Main.qml load. BUILD.md's aqt lines also install qtshadertools, qtsensors and qtquicktimeline.
TagLibdesktopAudio tags and embedded cover art (pkg-config taglib, or vcpkg on Windows); compiled out on Android
FFmpeg libavcodec / libavutiloptionalH.264 decoder for the built-in phone-mirror client; -DOCTAVE_REQUIRE_FFMPEG=ON makes it mandatory. Release builds link a static LGPL decoder-only build instead (-DOCTAVE_FFMPEG_ROOT, see Building)
Qt Quick 3D (+ Quick3DAssetUtils, QuickTimeline)optional3D vehicle view and the music player objects
Qt WebEngine Quickoptional, desktopIn-app wiki viewer (Settings → About → Open Wiki)
Qt TestDebug buildsLinked by the dev tooling and the tests/cpp suite

Runtime tools that are not build dependencies: adb for phone mirroring (fetched into tools/platform-tools/ by python scripts/fetch_platform_tools.py and bundled in releases). The app itself needs no Python; the Python tools around it (the dev/ clients, the wiki and API doc generators) go into a virtualenv next to the checkout:

python3 -m venv venv && venv/bin/pip install -r requirements.txt

Directory Structure

octave/
├── src/                 # C++ application
│   ├── main.cpp                       # entry point, manager wiring
│   ├── managers/                      # one *manager.{h,cpp} per feature + elm327protocol
│   ├── util/                          # logger.cpp (rotating logs, crash handlers), uiwatchdog.cpp, perfscope.h
│   ├── phone_mirror/scrcpyclient.*    # built-in scrcpy-protocol client
│   ├── items/embeddeddhuitem.*        # QQuickItem for Android Auto frames
│   ├── platform/                      # Android JNI bridges (media, process), Linux BlueZ pairing
│   ├── sim/                           # --sim simulator (every build): simulated car, ELM327, IMU motion, the sim object
│   └── dev/                           # --dev / --profile tooling (OCTAVE_DEV_TOOLS builds only), qml/ dev overlay
├── frontend/            # QML UI
│   ├── Main.qml  MainMenu.qml  MediaRoom.qml  MediaPlayer.qml  OBDMenu.qml  CarMenu.qml ...
│   ├── JeepVehicle.qml  JeepHinge.qml  JeepLamp.qml  JeepLink.qml  JeepSteering.js
│   ├── gauges/          # gauge primitives
│   ├── dashboards/      # DashboardRenderer, WidgetCatalog, presets/*.json, editor/, widgets/
│   ├── settings/        # settings pages and components (DeviceSettingsPage has Service, Frontends and Diagnostics)
│   ├── shaders/         # .qsb shaders (compiled into the binary as resources)
│   └── assets/          # icons, fonts, jeep_tj_2003.glb + jeep_tj/ part GLBs, readme media
├── tests/
│   ├── cpp/             # QtTest suite run by ctest (CI)
│   └── fixtures/        # H.264 clips and QML fixtures used by the tests
├── phone_server/        # OCTAVE's fork of the scrcpy server (Java) + build_without_gradle.sh
├── tools/
│   ├── phone-server/    # prebuilt jar + LICENSE/NOTICE (tracked)
│   ├── platform-tools/  # adb fetched by scripts/fetch_platform_tools.py (gitignored)
│   └── vehicle/         # Blender scripts that build the Jeep model
├── android/             # AndroidManifest, gradle, JNI bridges (OctaveMediaBridge, OctaveOBDBridge)
├── packaging/linux/     # build-appimage.sh
├── build_scripts/       # installer_windows.iss (Inno Setup)
├── scripts/             # fetch_platform_tools.py, desktop / Pi launcher scripts, Android bundle builder
├── deployment/          # orange-pi-5-plus/ reference config of the Jeep head unit
├── docs/                # GAUGE_AUTHORING.md, PHONE_MIRROR_NATIVE_PLAN.md, vehicle/ references
├── wiki/                # this wiki (static HTML)
├── TODO/                # parked plans, one markdown file each
├── hardware/            # 3D-printed mount CAD/STL (2003 Jeep TJ media console)
├── dev/                 # developer client tools (gitignored, not in a clone)
├── CMakeLists.txt       # the build
├── BUILD.md             # full desktop / Android build guide
└── CLAUDE.md            # contributor rules (conventions, wiki upkeep)

First Steps After Install

  1. Set your music directory — Open Settings and point the media library at a folder of MP3 / M4A / FLAC / OGG / Opus / WAV files. OCTAVE scans it, extracts album art and caches tags in metadata_cache.json to reduce repeated metadata work on later launches.
  2. Connect OBD-II (optional) — Plug in an ELM327 adapter (USB, or pair a Bluetooth one and select its port in Settings > OBD). On Linux make sure you are in the dialout group. Then open the OBD page, pick a dashboard from the chooser, or build your own in the editor.
  3. Try the 3D view — Sensors > 3D View shows the Jeep model; with a BerryIMU attached it follows the vehicle's attitude (use ZERO on level ground).
  4. Explore Settings — OCTAVE provides settings across display, media, OBD, accessories and device, all persisted to settingsConfigure.json. Settings > Device > Diagnostics shows the app version, the device and the recent log, and lets you export the logs.