This is where all the magic of the user interface of MustardOS comes to life.
You will need make, ccache, and a C compiler.
Some dependencies are fetched and built from source on first use (see External Dependencies), which additionally needs curl or
wget, perl, and tar. Optionally,
dialog or whiptail gives build.sh a guided setup, and nasm is needed for ffmpeg's x86 assembly on x86 hosts.
Everything else depends on which target you are building for.
Cross-compiling for ARM devices (normal workflow)
A pre-built aarch64 toolchain is expected at $HOME/x-tools/aarch64-buildroot-linux-gnu/. Other toolchain roots can be pointed to by setting the XTOOL
environment variable. The toolchain must include gcc, g++, ar, ld, and strip for the target host tuple.
Native builds for x86 / x86-64
A system gcc and the following development packages are required:
| Package | Purpose |
|---|---|
SDL2 |
Display and input |
SDL2_mixer |
Audio |
SDL2_ttf |
Font rendering |
SDL2_image |
Image loading |
libcurl |
Network requests |
libpng |
PNG support |
On Fedora/RHEL:
sudo dnf install SDL2-devel SDL2_mixer-devel SDL2_ttf-devel SDL2_image-devel libcurl-devel libpng-devel
On Debian/Ubuntu:
sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-ttf-dev libsdl2-image-dev libcurl4-openssl-dev libpng-dev
All builds go through build.sh, which sets up the toolchain environment and then calls make.
# Shipping build (aarch64 Cortex-A53, the most common target)
./build.sh release
# Development build with debug symbols, for gdb and crash backtraces
./build.sh debugrelease builds with BUILD=release. debug builds the development image (BUILD=test, which keeps test only code) with DEBUGSYM=1, so binaries keep
their symbols and are not stripped. Every build runs one job per CPU core, so there is no -j to pass. Anything after release or debug is handed to
make, such as ./build.sh release clean.
Run build.sh with no arguments for a guided setup that asks for the device, build type and toolchain, then starts the build. It uses dialog or whiptail
when either is installed, and falls back to plain numbered prompts otherwise.
# Guided / Spoon Fed
./build.sh./build.sh make still works as before and takes BUILD from the environment, defaulting to test when it is unset.
Before compiling, each build:
- Sets every file in the repository to
755and owned by the current user, the same aschmod -R 755 .andchown -R "$(id -un):" .. A file that cannot be changed, such as one left owned by root, gives a warning and the build carries on. - Refreshes the generated files, see Generated metadata.
- Copies the generated language template to
../language/mux/en.jsonwhen it has changed. - Formats any C source you have changed or added with the pinned clang-format, keeping the executable bit.
- Runs
shellcheck -s shover any changed script in../internaland warns about problems. This is skipped with a warning whenshellcheckis not installed.
Set SKIP_CHECKS=1 to skip steps 2 to 5 and compile straight away. Permissions and ownership are always set.
Each build starts with a summary of what it is about to use: the build type and device, the toolchain with its GCC version, location and sysroot, whether
ccache is available, the job count and log location, whether the sibling internal and language repositories were found, and which helper tools are
installed. Anything missing is highlighted along with what it affects, and the first build for a device warns that external libraries are compiled first.
If no toolchain can be found at all, build.sh explains where one is expected and how to point it elsewhere.
After that the screen shows a short summary: each stage, every component as it builds, generated and formatted files, and any warnings or errors with the offending source line. A failed build ends with a list of the first errors.
The complete output of every step, including each sub make, is written to build.log beside build.sh, which is replaced on each build and ignored by Git.
Look there for anything the summary leaves out, rather than rebuilding with extra output.
| Variable | Effect |
|---|---|
RAW=1 |
Shows the full output on screen as well as in the log |
DEBUG=2 |
Also writes every compiler command into the log |
NO_COLOR |
Turns off coloured output, which is also off when piped |
DEVICE targets
DEVICE |
Use for |
|---|---|
ARM64_A53 |
H700, A133P - default if unset |
ARM64_A53_CRYPTO |
A53 with hardware AES/CRC |
ARM64 |
Generic ARMv8-A |
ARM32 |
Original 35x (ARMv7 hard-float) |
ARM32_A9 |
Cortex-A9 with NEON |
X86_64 |
Generic 64-bit x86 |
RISCV64 |
Generic 64-bit RISC-V |
GENERIC |
Anything else, with ARCH_FLAGS |
The toolchain is detected automatically from $HOME/x-tools (override with XTOOL), picking one whose architecture matches DEVICE. Set XDIR to a directory
name under it to choose a specific toolchain.
# Example: build for generic ARM64
DEVICE=ARM64 ./build.sh releaseUse DEVICE=NATIVE to build and run directly on the host machine. This is useful for quick iteration and debugging without hardware.
DEVICE=NATIVE ./build.sh releaseBinaries and shared libraries land in bin/ just like a cross-compiled build.
Builds are incremental. Header dependencies are tracked with -MMD -MP, and the generated dependency files are kept under .deps/, one directory per
component, so a rebuild only touches what actually changed.
# Full rebuild from nothing
./build.sh release clean
./build.sh releaseChanging DEVICE, BUILD, OPT_LEVEL or DEBUGSYM forces a clean automatically, since objects compiled with different flags cannot be reused. Switching
between release and debug therefore rebuilds everything. The current configuration is recorded in .build-config.
Generate compile_commands.json from a clean build when using CLion, clangd or another editor that supports compilation databases:
BUILD=release ./build.sh databaseThe command uses the selected cross-toolchain and records the real compiler arguments from the root project and its nested components. Temporary capture files
are written beneath /tmp/mustardos. The resulting compile_commands.json is local development metadata and remains excluded from Git.
To use it as the CLion project model, enable CLion's bundled Compilation Database plugin and restart the IDE. Close any existing Makefile project for this
directory, then select Open from the welcome screen, choose compile_commands.json, press OK, and open it as a project. An existing .idea directory
created by the Makefile importer must be moved aside before the one-time import. Afterwards, select the appropriate compiler under Build, Execution,
Deployment → Compilation Database.
Every build refreshes the generated language template, third-party version table, profile schema and internal script hashes before compiling, and again after any configuration-driven clean. Output is compared before replacement, so unchanged metadata keeps its timestamp and does not cause unnecessary recompilation.
# Refresh generated files without compiling
./build.sh generateThe standard outputs are common/generated/language.json, common/generated/thirdparty.h, common/generated/profile_schema.json and
common/generated/verify_data.h. Verification data is refreshed from the sibling internal/script tree when it is available; otherwise the checked-in data is
retained. Set INTERNAL_SCRIPT_DIR, INTERNAL_ROOT, LANGUAGE_OUTPUT, PROFILE_SCHEMA_OUTPUT, THIRDPARTY_OUTPUT, or VERIFY_OUTPUT to override those
paths, and LANGUAGE_REPO_FILE to change where the language template is copied. Generating verification data requires xxhsum.
Sources are formatted with clang-format 21.1.8, matching CLion. build.sh installs that exact version into .cache when it is not already available, or uses
the binary named by CLANG_FORMAT.
# Format everything tracked by Git
./build.sh format
# Format or check particular files
./build.sh format retro/ui/ui_manual.c
./build.sh format --checkBuilds format only the files you have changed, so committed files that predate the formatter are left alone until you format them yourself.
Some third party libraries are not kept in this repository. They are fetched from upstream, checksum verified, built static and installed into
external/prefix/$DEVICE by external/build.sh, which the build calls for you. Each library stamps what it built, so repeat runs cost nothing.
# Rebuild one of them after bumping its pinned version
DEVICE=ARM64_A53 EXT_ARCH_FLAGS="-mcpu=cortex-a53" ./external/build.sh ffmpegLinking them statically means the version shipped in a device rootfs never matters, and their symbols are hidden with
--exclude-libs so libretro cores keep their own copies.
common: Common Libraries and Functionsemmc: TrimUI internal eMMC probe moduleexternal: Third party dependencies fetched and built from sourceinput: Input service and per device input driversmodule: Frontend menu system modulesmugl: 32-bit GLES2 forwarder for TrimUI devicesretro: LibRetro core hoststage: Hardware overlay staging systemterminal: Mustard Terminal emulator, settings menu and on-screen keyboardtooling: Build and development helpersvendor: Bundled third party source and licence filesvideo: Wasabi media player
The common source tree is grouped into base, compat, config, content, display, generated, platform,
runtime, saver, storage, tooling, and ui. See common/README.md for ownership and migration rules. Its Makefile uses explicit
source groups so adding a file does not silently alter libmuxcom.so.
mubattery: Background battery monitor daemonmucredits: Supporter Creditsmudisp: Display and HDMI output controlmudns: Local network discovery over multicast DNSmufbset: Customised framebuffer resolution switchermuhotkey: Global Hotkey Systemmuinput: Input service and remote input socketmulink: Direct Link daemon for cable connections between devicesmulog: System log viewermulookup: Content Name Lookupmuremap: Background input remap daemonmurgb: RGB LED and MCU controller daemonmuscreen: Remote View screen streamermusplash: Standalone PNG splash screenmususpend: Suspend and wake helpermuswitch: Launches content directlymuvarctl: Configuration value store controlmuverify: Signed manifest verificationmuwarn: First Install Disclaimer Messagemuweb: Landing page web server, catalogue and save management APImuxcharge: Charging Information Screenmuxfrontend: Main Frontend Specific Runnermuxmedia: Wasabi media playermuxmessage: Information and Progress Screenmuxretro: Pickles, the LibRetro core hostmuxterm: Mustard Terminal
muxactivity: Activity Tracker Informationmuxapp: Application Listmuxappcon: Application Control Managermuxarchive: Archive Managermuxassign: Assignable System/Core for Contentmuxbackup: Device Backup Menumuxbtall: Bluetooth Device Listmuxbtcon: Bluetooth Connection Managermuxbtdev: Bluetooth Device Informationmuxcolfilter: Content Colour Filter Menumuxcollect: Content Collection Managermuxconfig: Configuration Menumuxconnect: Connectivity Menumuxcontrol: Content Control Scheme Selectormuxcore: Core Managementmuxcustom: Customisation Menumuxdanger: Dangerous Settingsmuxdetail: Device Detailsmuxdevice: Device Settingsmuxdistemp: Display Colour Temperaturemuxgov: System Governor Selectormuxhdmi: HDMI Configurationmuxhistory: Content History Menumuxinfo: Information Menumuxinstall: First Time Install Menumuxkiosk: Kiosk Mode Managementmuxlanguage: Language Selectormuxlaunch: Main Menumuxlink: Direct Link Settingsmuxlogo: Boot Logo Selectormuxnetadv: Advanced Network Settingsmuxnetprofile: Network Profile Managermuxnetproxy: Network Proxy Settingsmuxnetscan: Network SSID Scannermuxnetwork: Network Configurationmuxnews: Community Newsmuxoption: Content Explorer Optionsmuxorder: Content Sort Ordermuxoverlay: Content Overlay Settingsmuxpass: Passcode Screenmuxpasscfg: Passcode Configurationmuxpicker: Customisation Package Selectormuxplore: Content Explorermuxpower: Power Settingsmuxprofile: Settings Profilesmuxraopt: RetroArch Optionsmuxremap: Button Remappingmuxrgb: RGB LED Settingsmuxrgbzone: RGB LED Zone Settingsmuxrtc: Date and Timemuxsearch: Content Searchmuxshader: Shader Settingsmuxshare: Shared Frontend Module Statemuxshot: Screenshot Viewermuxsort: Sorting Settingsmuxsoundfont: Soundfont Selectormuxspace: Disk Usage Informationmuxsplash: Simple PNG Based Splash Screenmuxstorage: Storage Migrate/Sync Informationmuxtag: Content Tag Managermuxtask: Task Toolkitmuxtester: Input Testermuxtext: Basic Text File Viewermuxtheme: Theme Pickermuxthemedown: Custom Theme Downloadmuxthemefilter: Custom Theme Filtermuxthird: Third Party Licencesmuxtimezone: Timezone Selectormuxtweakadv: Advanced Settingsmuxtweakgen: General Settingsmuxwebcode: Web Dashboard Codemuxwebserv: Web Services
Embedded graphics library used as the core UI toolkit for all menus and widgets. Includes the TinyTTF font renderer for glyph rasterisation.
- Version: 8.4.0
- License: MIT
- Location:
vendor/lvgl/
Compact SVG rendering library written in C. Used to parse and render SVG icons for list and grid view glyphs, with scaling driven by the LVGL custom image decoder pipeline. Bundles PlutoVG, the 2D vector graphics canvas and rasteriser it is built on.
- PlutoSVG Version: 0.0.8
- PlutoVG Version: 1.3.3
- Author: Samuel Ugochukwu
- License: MIT
- Location:
vendor/plutosvg/
Header-only multicast DNS and DNS-SD implementation used by the mudns local discovery helper.
- Revision:
a569c475 - License: Public domain
- Location:
vendor/mdns/
Single-file C library for parsing JSON. Used throughout the codebase to read language translation files, configuration data, and API responses.
- Author: Josh Baker
- License: MIT
- Location:
vendor/json/
Minimal C INI file parser. Used for reading and writing .ini configuration files.
- Author: univrsal
- License: BSD 2-Clause
- Location:
vendor/mini/
Single-file C library for deflate/inflate, zlib-compatible compression, and ZIP archive reading and writing. Used to extract downloaded ZIP archives.
- Version: 11.3.0
- License: MIT (portions also released as public domain / Unlicense)
- Location:
vendor/miniz/
Extremely fast non-cryptographic hash algorithm. Used to compute file checksums for content verification.
Note: xxHash is non-cryptographic and is not resistant to deliberate collision attacks. It is suited for detecting accidental data corruption (content verification) but must not be used for tamper detection or cryptographic integrity verification.
- Version: 0.8.3
- Author: Yann Collet
- License: BSD 2-Clause
- Location:
vendor/xxhash/
Single-header C library for TrueType font parsing and glyph rasterisation. Used by the LVGL TinyTTF renderer to load and render custom TTF fonts at runtime.
- Version: 1.26
- Author: Sean Barrett
- License: Public domain
- Location:
vendor/stb/stb_truetype.h
Single-header C library for rectangle packing. Used by the LVGL TinyTTF renderer to pack glyph bitmaps into atlas textures.
- Version: 1.01
- Author: Sean Barrett
- License: Public domain
- Location:
vendor/stb/stb_rect_pack.h
Single-header C library for writing PNG, BMP, TGA, JPEG, and HDR image files. Used to capture and save screenshots from the framebuffer.
- Version: 1.16
- Author: Sean Barrett
- License: Public domain
- Location:
vendor/stb/stb_image_write.h
These are not kept in the repository. external/build.sh downloads a pinned release, verifies its SHA-256, and builds a trimmed static copy into
external/prefix/$DEVICE. Versions and checksums are pinned at the top of each
external/<name>.sh.
Audio and video decoding for theme wallpapers, the screensaver, the boot logo, and content video previews. Built with
--disable-everything plus only the MP4 demuxer and the handful of decoders common/platform/video.c uses.
- Version: 9.0.1
- License: LGPL 2.1 or later
- Build:
external/ffmpeg.sh
Multi-format archive reading. Used read-only by muxretro for content stored in archives. Compression codecs are detected per sysroot, since they are not present everywhere.
- Version: 3.8.9
- License: BSD 2-Clause
- Build:
external/libarchive.sh
TLS, hashing and signature verification for Network Play and achievement accounts. Built statically so the 1.1 and 3.x split across device rootfs images stops mattering.
- Version: 3.5.7 (LTS branch)
- License: Apache 2.0
- Build:
external/openssl.sh
RetroAchievements client, hashing and libretro memory helper. Desktop integration and the RetroAchievements integration DLL sources are excluded.
- Version: 12.4.0
- License: MIT
- Build:
external/rcheevos.sh
Unicode text processing library covering normalisation, collation, and case mapping without external dependencies. Used for locale-aware, Unicode-correct natural sorting of content and file lists.
- Version: 0.3.6
- Author: Francesco Bigiarini
- License: MIT
- Build:
external/mojibake.sh