docs: BUILD-QEMU.md + 'Build QEMU from source' docs section

Adds a transparent self-hosting path for users who would rather not
run Velxio's prebuilt libqemu binaries. The prebuilts have always
been a convenience under the AGPLv3 license; this just documents
how to skip them.

- docs/BUILD-QEMU.md as the canonical step-by-step (dependencies per
  Debian/Arch/macOS, ESP32 xtensa + ESP32-C3 riscv32 configure-and-
  ninja, drop-in instructions, troubleshooting, license notes on the
  QEMU/Velxio GPL-vs-AGPL boundary).
- DocsPage gets a new 'build-qemu' section between Setup and Roadmap
  in the sidebar. Content is hardcoded English (technical reference,
  not marketing copy) and ends with a link to the .md on GitHub.
- nav + SEO meta keys added to all 9 locales (de en es fr it ja
  pt-br ru zh-cn). Body remains English in every locale; technical
  content doesn't need translation for the audience that follows it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
davidmonterocrespo24 2026-05-14 05:44:10 +02:00
parent 3ba20e9d92
commit 888ce03cc3
20 changed files with 387 additions and 10 deletions

207
docs/BUILD-QEMU.md Normal file
View File

@ -0,0 +1,207 @@
# Building QEMU from source for Velxio
The Velxio docker image ships with prebuilt `libqemu-xtensa` and
`libqemu-riscv32` libraries so ESP32 / ESP32-S3 / ESP32-C3 simulation
works out of the box. If you'd rather not use the prebuilts —
whether for licensing reasons, audit requirements, or simply because
you prefer to compile what you run — this guide walks you through
building both libraries from the upstream
[`lcgamboa/qemu`](https://github.com/lcgamboa/qemu) fork.
Velxio itself is **AGPLv3**, and that includes the binary linker
contract: you have the source, you can rebuild, you can verify the
chain end-to-end.
> The prebuilts at `velxio.dev/license/signup` and on GitHub Releases
> are a convenience, not a gate. Everything in this guide produces
> the exact same `.so` / `.dll` / `.dylib` files those bundles
> contain, byte-for-byte modulo timestamps.
## Audience
This guide assumes a Linux or macOS workstation with a working C
toolchain. Windows builds are possible via MSYS2 / MinGW but are
out of scope here — start from `lcgamboa/qemu`'s own README if you
need them.
## What you'll produce
| File | Architecture | Used for |
|---|---|---|
| `libqemu-xtensa.so` | Xtensa LX6 / LX7 | ESP32, ESP32-S3, ESP32-CAM, Arduino Nano ESP32 |
| `libqemu-riscv32.so` | RISC-V RV32IMC | ESP32-C3, XIAO ESP32-C3, CH32V003 |
The Velxio backend dlopen's these at runtime through the dynamic
linker (`backend/app/services/qemu_runtime.py`). Drop the freshly
built files into `/app/lib/` inside the container (or the host
path that mounts to it) and Velxio will use them on the next
simulation start.
## 1. Clone the fork
```bash
git clone https://github.com/lcgamboa/qemu.git
cd qemu
git checkout 822927b6 # the commit Velxio's prebuilts are anchored to
```
The exact commit ID may move forward over time. The Velxio docker
image's `Dockerfile.standalone` records the canonical SHA — `grep -E
'qemu.*checkout|QEMU_REF' Dockerfile.standalone` to read it.
## 2. Install build dependencies
**Debian / Ubuntu**:
```bash
sudo apt-get update
sudo apt-get install -y \
git ninja-build pkg-config \
libglib2.0-dev libpixman-1-dev \
python3 python3-venv python3-pip \
flex bison
```
**Arch / Manjaro**:
```bash
sudo pacman -S --needed \
git ninja pkgconf \
glib2 pixman \
python flex bison
```
**macOS** (Homebrew):
```bash
brew install ninja pkg-config glib pixman
```
## 3. Configure and build — Xtensa (ESP32 / ESP32-S3)
```bash
mkdir build-xtensa && cd build-xtensa
../configure \
--target-list=xtensa-softmmu \
--disable-werror \
--enable-shared-lib \
--disable-tools \
--disable-docs
ninja
```
This produces `libqemu-xtensa.so` under `build-xtensa/`. Verify:
```bash
file libqemu-xtensa.so
# ELF 64-bit LSB shared object, x86-64, dynamically linked
ls -lh libqemu-xtensa.so
# ~46 MB on Linux x86_64
```
Go back to the repo root:
```bash
cd ..
```
## 4. Configure and build — RISC-V (ESP32-C3)
```bash
mkdir build-riscv32 && cd build-riscv32
../configure \
--target-list=riscv32-softmmu \
--disable-werror \
--enable-shared-lib \
--disable-tools \
--disable-docs
ninja
cd ..
```
You now have `build-riscv32/libqemu-riscv32.so`.
## 5. Drop the binaries into Velxio
If you self-host Velxio via the official docker image:
```bash
docker cp build-xtensa/libqemu-xtensa.so velxio:/app/lib/libqemu-xtensa.so
docker cp build-riscv32/libqemu-riscv32.so velxio:/app/lib/libqemu-riscv32.so
docker restart velxio
```
If you're running Velxio from source:
```bash
cp build-xtensa/libqemu-xtensa.so /path/to/velxio/backend/app/lib/
cp build-riscv32/libqemu-riscv32.so /path/to/velxio/backend/app/lib/
# restart the backend
```
The next ESP32 / ESP32-C3 simulation start will use your libraries.
Check the backend logs for a line like:
```
[qemu_runtime] loaded libqemu-xtensa.so build=<your-hash>
```
## 6. ESP32 ROM blobs
The QEMU build does not produce the ESP32 ROM dumps Velxio also
needs (`esp32-v3-rom.bin`, `esp32-v3-rom-app.bin`, `esp32c3-rom.bin`).
Those come straight from Espressif's open-source toolchain and are
redistributable verbatim. The image already includes them at
`/app/lib/`; you only need to replace them if you're working from a
custom esp-idf version.
## 7. Troubleshooting
**`No such file or directory: glib-2.0`** — apt missed
`libglib2.0-dev`. Re-run the dependencies step.
**`error: CONFIG_USER_ONLY is not defined`** — you forgot
`--target-list=`. The `softmmu` suffix is required for the system
emulator Velxio uses.
**Shared library is too small** (a few hundred KB) — you built
without `--enable-shared-lib`. The default QEMU output is the
`qemu-system-*` binary, not the library Velxio loads.
**Simulation starts but the board boots into "qemu: fatal: Trying to
execute code outside RAM or ROM"** — wrong commit. `lcgamboa/qemu`
master moves; Velxio is pinned. Check out the commit listed in
`Dockerfile.standalone`.
## License notes
`lcgamboa/qemu` is **GPL-2.0** (same as upstream QEMU). Velxio is
**AGPLv3**. The dlopen boundary keeps the two licenses orthogonal:
QEMU stays GPL'd, Velxio stays AGPL'd, neither contaminates the other.
If you distribute a modified Velxio image with self-built QEMU
binaries, you owe the QEMU sources to your recipients (GPL-2.0
obligation), and you owe the Velxio modifications under AGPLv3 if
the deployment is networked.
## Why use the prebuilts at all?
For ~99% of self-hosters the prebuilts at
[`velxio.dev/license/signup`](https://velxio.dev/license/signup)
or the GitHub release are the path of least resistance — they're
the same files this guide produces, signed-by-sha256 in their
manifest, ready to drop in. The build itself takes 15-30 minutes
on a modern laptop and ~3 GB of disk for the build tree.
Building from source matters when:
- You're auditing the supply chain for a regulated deployment.
- You need to patch QEMU (e.g. add a peripheral the fork doesn't
emulate) and want to ship the patched library.
- You don't want any third-party prebuilts on your machine.
- You're on a platform we don't ship a binary for (e.g. BSD, ARM
on macOS Intel boxes, exotic libc).
All four are legitimate. The license module on velxio.dev exists to
distribute prebuilts conveniently and to detect bulk-abuse patterns;
it never tries to be the only path.

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Raspberry Pi 3-Emulation (QEMU) | Velxio-Dokumentation",
"description": "Wie Velxio einen vollständigen Raspberry Pi 3B mit QEMU raspi3b emuliert: echtes Raspberry Pi OS, Python + RPi.GPIO-Shim, zweikanaliger UART, VFS und Multi-Board-Serienbrücke."
},
"buildQemu": {
"title": "QEMU aus dem Quellcode bauen | Velxio-Dokumentation",
"description": "Schritt-für-Schritt-Anleitung zum Kompilieren von libqemu-xtensa und libqemu-riscv32 aus dem lcgamboa/qemu-Fork. Volle Transparenz unter AGPLv3."
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Wokwi-Bibliotheken",
"mcp": "MCP-Server",
"setup": "Projektstatus",
"roadmap": "Fahrplan"
"roadmap": "Fahrplan",
"buildQemu": "QEMU aus Quellcode bauen"
}
}
}

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Raspberry Pi 3 Emulation (QEMU) | Velxio Documentation",
"description": "How Velxio emulates a full Raspberry Pi 3B using QEMU raspi3b: real Raspberry Pi OS, Python + RPi.GPIO shim, dual-channel UART, VFS, and multi-board serial bridge."
},
"buildQemu": {
"title": "Build QEMU from Source | Velxio Documentation",
"description": "Step-by-step guide to compiling libqemu-xtensa and libqemu-riscv32 from the lcgamboa/qemu fork. Self-hosters who would rather not run Velxio prebuilt binaries get full transparency under the AGPLv3 license."
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Wokwi Libraries",
"mcp": "MCP Server",
"setup": "Project Status",
"roadmap": "Roadmap"
"roadmap": "Roadmap",
"buildQemu": "Build QEMU from source"
}
}
}

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Emulación Raspberry Pi 3 (QEMU) | Documentación de Velxio",
"description": "Cómo emula Velxio una Raspberry Pi 3B completa usando QEMU raspi3b: Raspberry Pi OS real, shim Python + RPi.GPIO, UART de doble canal, VFS y puente serie multi-placa."
},
"buildQemu": {
"title": "Compilar QEMU desde el código fuente | Documentación Velxio",
"description": "Guía paso a paso para compilar libqemu-xtensa y libqemu-riscv32 desde el fork lcgamboa/qemu. Para quienes self-hostean y prefieren no usar los binarios precompilados de Velxio."
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Librerías Wokwi",
"mcp": "Servidor MCP",
"setup": "Estado del proyecto",
"roadmap": "Hoja de ruta"
"roadmap": "Hoja de ruta",
"buildQemu": "Compilar QEMU"
}
}
}

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Émulation Raspberry Pi 3 (QEMU) | Documentation Velxio",
"description": "Comment Velxio émule un Raspberry Pi 3B complet en utilisant QEMU raspi3b : vrai Raspberry Pi OS, shim Python + RPi.GPIO, UART double canal, VFS et pont série multi-cartes."
},
"buildQemu": {
"title": "Compiler QEMU depuis les sources | Documentation Velxio",
"description": "Guide étape par étape pour compiler libqemu-xtensa et libqemu-riscv32 depuis le fork lcgamboa/qemu. Transparence totale sous licence AGPLv3."
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Bibliothèques Wokwi",
"mcp": "Serveur MCP",
"setup": "État du projet",
"roadmap": "Feuille de route"
"roadmap": "Feuille de route",
"buildQemu": "Compiler QEMU"
}
}
}

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Emulazione Raspberry Pi 3 (QEMU) | Documentazione Velxio",
"description": "Come Velxio emula un Raspberry Pi 3B completo usando QEMU raspi3b: vero Raspberry Pi OS, shim Python + RPi.GPIO, UART a doppio canale, VFS e ponte seriale multi-scheda."
},
"buildQemu": {
"title": "Compilare QEMU dal sorgente | Documentazione Velxio",
"description": "Guida passo-passo per compilare libqemu-xtensa e libqemu-riscv32 dal fork lcgamboa/qemu. Trasparenza completa sotto licenza AGPLv3."
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Librerie Wokwi",
"mcp": "Server MCP",
"setup": "Stato del progetto",
"roadmap": "Roadmap"
"roadmap": "Roadmap",
"buildQemu": "Compilare QEMU"
}
}
}

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Raspberry Pi 3エミュレーションQEMU | Velxio ドキュメント",
"description": "VelxioがQEMU raspi3bを使用して完全なRaspberry Pi 3Bをエミュレートする方法実際のRaspberry Pi OS、Python + RPi.GPIOシム、デュアルチャンネルUART、VFS、マルチボードシリアルブリッジ。"
},
"buildQemu": {
"title": "QEMUをソースからビルド | Velxioドキュメント",
"description": "lcgamboa/qemu フォークから libqemu-xtensa と libqemu-riscv32 をコンパイルするステップバイステップガイド。AGPLv3 ライセンスの下、完全な透明性を提供します。"
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Wokwiライブラリ",
"mcp": "MCPサーバー",
"setup": "プロジェクトステータス",
"roadmap": "ロードマップ"
"roadmap": "ロードマップ",
"buildQemu": "QEMUをソースからビルド"
}
}
}

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Emulação Raspberry Pi 3 (QEMU) | Documentação Velxio",
"description": "Como Velxio emula um Raspberry Pi 3B completo usando QEMU raspi3b: Raspberry Pi OS real, Python + shim RPi.GPIO, UART de canal duplo, VFS e ponte serial multi-placa."
},
"buildQemu": {
"title": "Compilar QEMU a partir do código-fonte | Documentação Velxio",
"description": "Guia passo a passo para compilar libqemu-xtensa e libqemu-riscv32 a partir do fork lcgamboa/qemu. Transparência total sob a licença AGPLv3."
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Bibliotecas Wokwi",
"mcp": "Servidor MCP",
"setup": "Status do Projeto",
"roadmap": "Roadmap"
"roadmap": "Roadmap",
"buildQemu": "Compilar QEMU"
}
}
}

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Эмуляция Raspberry Pi 3 (QEMU) | Документация Velxio",
"description": "Как Velxio эмулирует полноценный Raspberry Pi 3B с помощью QEMU raspi3b: реальная Raspberry Pi OS, Python + RPi.GPIO шим, двухканальный UART, VFS и многоплатный последовательный мост."
},
"buildQemu": {
"title": "Сборка QEMU из исходного кода | Документация Velxio",
"description": "Пошаговое руководство по сборке libqemu-xtensa и libqemu-riscv32 из форка lcgamboa/qemu. Полная прозрачность под лицензией AGPLv3."
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Библиотеки Wokwi",
"mcp": "MCP сервер",
"setup": "Статус проекта",
"roadmap": "План развития"
"roadmap": "План развития",
"buildQemu": "Сборка QEMU из исходников"
}
}
}

View File

@ -148,6 +148,10 @@
"raspberryPi3Emulation": {
"title": "Raspberry Pi 3 仿真 (QEMU) | Velxio 文档",
"description": "Velxio 如何使用 QEMU raspi3b 仿真完整的 Raspberry Pi 3B真实的 Raspberry Pi OS、Python + RPi.GPIO 垫片、双通道 UART、VFS 和多板串行桥。"
},
"buildQemu": {
"title": "从源码构建 QEMU | Velxio 文档",
"description": "从 lcgamboa/qemu 分支编译 libqemu-xtensa 和 libqemu-riscv32 的逐步指南。AGPLv3 许可下的完全透明。"
}
},
"rp2040": {

View File

@ -369,7 +369,8 @@
"thirdParty": "Wokwi 库",
"mcp": "MCP 服务器",
"setup": "项目状态",
"roadmap": "路线图"
"roadmap": "路线图",
"buildQemu": "从源码构建 QEMU"
}
}
}

View File

@ -35,7 +35,8 @@ type SectionId =
| 'architecture'
| 'third-party'
| 'mcp'
| 'setup';
| 'setup'
| 'build-qemu';
const VALID_SECTIONS: SectionId[] = [
'intro',
@ -51,6 +52,7 @@ const VALID_SECTIONS: SectionId[] = [
'third-party',
'mcp',
'setup',
'build-qemu',
];
interface NavItem {
@ -71,6 +73,7 @@ const NAV_ITEMS: NavItem[] = [
{ id: 'third-party', labelKey: 'docs.nav.thirdParty' },
{ id: 'mcp', labelKey: 'docs.nav.mcp' },
{ id: 'setup', labelKey: 'docs.nav.setup' },
{ id: 'build-qemu', labelKey: 'docs.nav.buildQemu' },
{ id: 'roadmap', labelKey: 'docs.nav.roadmap' },
];
@ -132,6 +135,10 @@ const SECTION_META: Record<SectionId, SectionMeta> = {
titleKey: 'docs.sectionMeta.raspberryPi3Emulation.title',
descriptionKey: 'docs.sectionMeta.raspberryPi3Emulation.description',
},
'build-qemu': {
titleKey: 'docs.sectionMeta.buildQemu.title',
descriptionKey: 'docs.sectionMeta.buildQemu.description',
},
};
/* ── Section content ───────────────────────────────────── */
@ -2509,6 +2516,123 @@ const RaspberryPi3EmulationSection: React.FC = () => {
);
};
/* ── Build QEMU from source ───────────────────────────── */
//
// Transparency section. The Velxio docker image ships with prebuilt
// libqemu-xtensa / libqemu-riscv32 — anyone who'd rather not run
// third-party binaries can rebuild them from lcgamboa/qemu and drop
// them in. Body copy is intentionally hardcoded English: the value
// here is technical clarity and a clean link to the canonical
// docs/BUILD-QEMU.md, not a localised marketing surface.
const BuildQemuSection: React.FC = () => {
return (
<div className="docs-section">
<span className="docs-label">Self-hosting</span>
<h1>Build QEMU libraries from source</h1>
<p>
Velxio ships with prebuilt <code>libqemu-xtensa.so</code> and{' '}
<code>libqemu-riscv32.so</code> so ESP32 / ESP32-S3 / ESP32-C3
simulation works the moment you pull the docker image. The
prebuilts are a convenience Velxio is <strong>AGPLv3</strong>{' '}
and so is the QEMU fork it depends on, which means you can
always rebuild the libraries yourself from source and run
those instead.
</p>
<h2>Why you might want to</h2>
<ul>
<li>
<strong>Audit the supply chain.</strong> Regulated deployments
often require that every shared object on the box was built
from a known-good source tree.
</li>
<li>
<strong>Patch QEMU.</strong> Add a peripheral the upstream
fork doesn't emulate, or backport a fix from mainline QEMU.
</li>
<li>
<strong>You're on an unusual platform.</strong> We currently
publish Linux x86_64, Linux ARM64, macOS ARM64 and Windows
x86_64. BSDs, exotic libc, macOS Intel build your own.
</li>
<li>
<strong>Trust nothing.</strong> A valid reason. Drop our
binaries, rebuild from sources you've audited, and the
chain is your tree only.
</li>
</ul>
<h2>The short version</h2>
<p>
On a Linux box with a working C toolchain:
</p>
<pre><code>{`git clone https://github.com/lcgamboa/qemu.git
cd qemu
# ESP32 (Xtensa)
mkdir build-xtensa && cd build-xtensa
../configure --target-list=xtensa-softmmu --enable-shared-lib \\
--disable-werror --disable-tools --disable-docs
ninja
# produces libqemu-xtensa.so (~46 MB)
cd ..
# ESP32-C3 (RISC-V)
mkdir build-riscv32 && cd build-riscv32
../configure --target-list=riscv32-softmmu --enable-shared-lib \\
--disable-werror --disable-tools --disable-docs
ninja
# produces libqemu-riscv32.so (~45 MB)`}</code></pre>
<p>
Drop both <code>.so</code> files into <code>/app/lib/</code>{' '}
inside the running Velxio container (or whatever host path you
bind-mount to it) and restart. The backend dlopens whichever
library is on disk on the next simulation start, so this
replaces the shipped binaries cleanly.
</p>
<h2>The full guide</h2>
<p>
Step-by-step build instructions, dependency lists per OS
(Debian / Arch / macOS), the canonical commit ID we anchor the
prebuilts to, troubleshooting for the common configure / ninja
failures, and the licensing notes (QEMU is GPL-2.0, Velxio is
AGPLv3, the dlopen boundary keeps them orthogonal) live in the
full document:
</p>
<p>
<a
href="https://github.com/davidmonterocrespo24/velxio/blob/master/docs/BUILD-QEMU.md"
target="_blank"
rel="noopener noreferrer"
>
Read <code>docs/BUILD-QEMU.md</code> on GitHub
</a>
</p>
<h2>Or use the prebuilts</h2>
<p>
If you don't have a 15-30 minute build in you, the
sha256-pinned prebuilts are available at{' '}
<a
href="https://velxio.dev/license/signup"
target="_blank"
rel="noopener noreferrer"
>
velxio.dev/license/signup
</a>{' '}
(free personal-use key, takes a minute), and the existing
public release at <code>github.com/davidmonterocrespo24/velxio
/releases/tag/qemu-prebuilt</code> still serves the same files
byte-for-byte. Both produce identical libraries to what this
guide builds there's no "blessed" version, just convenience
choices.
</p>
</div>
);
};
const SECTION_MAP: Record<SectionId, React.FC> = {
intro: IntroSection,
'getting-started': GettingStartedSection,
@ -2523,6 +2647,7 @@ const SECTION_MAP: Record<SectionId, React.FC> = {
'third-party': WokwiLibsSection,
mcp: McpSection,
setup: SetupSection,
'build-qemu': BuildQemuSection,
};
/* ── Page ─────────────────────────────────────────────── */