Hacking on it
Building and Packaging
Every component lives in its own directory with its own PKGBUILD. There are two
build paths: the inner loop (fast, for development) and the ISO pipeline
(slow, for releases).
./build-all.sh # inner loop: every component
./build-all.sh synui # or just one — the usual case
sudo ./archiso/build.sh # full ISO pipeline (see Cutting an ISO Release)
Prerequisites: an Arch host with archiso, base-devel, meson, ninja,
wlroots0.20, scenefx0.5, quickshell, qemu, ovmf.
Budget ~20 GB of free disk, or ~32 GB with --with-model. Roughly where it
goes:
| Where | Size |
|---|---|
archiso/build/ — llama.cpp plus one tree per backend |
~3.1 GB |
archiso/work/ — mkarchiso's staging tree, then the squashfs |
the bulk of it |
| the ISO itself | ~4 GB without a model |
airootfs/local-repo — the built packages |
~0.45 GB |
/var/tmp at peak — linux-wallpaperengine unpacks a ~1.3 GB CEF blob |
several GB, transient |
The /var/tmp scratch does not stack with the staging tree: packages are built
and cleaned up before mkarchiso runs. A model costs its ~4.4 GB three times
over — overlay, staging tree, image — which is most of the difference between
the two figures.
build-all.sh builds against the staged llama tree for whichever backend this
host runs — llama-staging-cpu, -cuda or -vulkan, defaulting to the one
already installed, so a routine rebuild on a GPU box does not quietly try to
replace the GPU package with a CPU one. Produce a staging tree with
sudo ./archiso/build.sh --gpu=cuda --llama-only. It asks for sudo up
front and then runs unattended.
scenefxis built and installed beforesynui, not alongside it — synui linkslibscenefx-0.5.soand the build is red without it. It is also a fork of wlroots' scene graph, vendored inscenefx/, so a wlroots bump is a port of two things, not one.
The version model (read this before you bump anything)
There are two versions and they are not the same thing.
| Version | Where | Bump it? |
|---|---|---|
iso_version |
archiso/profiledef.sh |
Yes — this is the release version |
SYNAPSEOS_VERSION |
archiso/build.sh |
No. Leave it at 0.1.0. |
SYNAPSEOS_VERSION is the package series. Most PKGBUILDs declare
source=("<pkg>-0.1.0.tar.gz") literally, so if you bump it, build.sh's
create_source_tarball emits <pkg>-0.1.1.tar.gz and every makepkg fails to
find its source.
So packages are versioned 0.1.0-<pkgrel> and the ISO is 0.1.4. Ship a code
change by bumping the component's pkgrel.
(build.sh's completion banner cosmetically prints SYNAPSEOS_VERSION=0.1.0.
Harmless, left alone.)
The traps
These are all silent — they let a build "succeed" on the wrong code.
Always regenerate the source tarball
Most PKGBUILDs consume a tarball, not your working tree. Edit a .c, run
makepkg without regenerating <pkg>-0.1.0.tar.gz, and you package the old
code and exit 0. build-all.sh and build.sh each regenerate it — but if you
run makepkg by hand, you must too.
The src/ collision hazard
Never rm -rf src/ inside a component directory (this bit us in synui/,
and applies to synguard/ too). makepkg just recreates it, and the stale copy
gets picked up again on the next run. Cleaning the source tree's src/ by hand
does not help.
The related bug in the ISO pipeline: the temp-build cleanup removed only
src/<pkg>-* (the tarball extraction dirs) and missed the versionless
src/<pkg> that git-sourced packages (nexus-chat, tepris) extract to.
That stale git working copy got copied into the synbuild area with .git
alternates pointing back at your $HOME — unreadable by the unprivileged
synbuild user — and makepkg aborted with "does not appear to be a git
repository". Fixed by wiping the whole src/ in the temp copy.
Check for untracked source files before a release
synui/src/ctlpanel.c once sat untracked while meson.build already listed
it. git commit -a would have pushed a tree that does not build. Before cutting
a release:
git status --short --untracked=all -- synui synapd synguard synsh synnet synapse_kmod
Look for ?? on real source, not just modified files, and stage it explicitly.
Two copies of everything
Several things exist in more than one place and drift silently:
create_source_tarballexists twice — inbuild-all.shand separately inarchiso/build.sh. This one went wrong four times out of four: each fix landed in one collector and not the other, and the symptom every time was a file missing from the tarball and a build that failed later, somewhere else. Both now delegate to the component's own<pkg>/mktarball.shwhen it has one, which is the deduplication — a component that knows which files it needs says so once, in its own directory. Prefer adding amktarball.shover teaching the collectors about your package.- Which components each collector builds is the same split, and it went
wrong a fifth time: a package was named in
archiso/build.sh(so every ISO carried it) and inbuild-all.sh'sKNOWN=list — but never given a build rule inbuild-all.shitself. Asking for it by name therefore passed the argument check, matched nothing, and exited 0 having built nothing, so installed systems could never update it while the ISO was fine. Adding a component means editing both collectors;build-all.shnow fails loudly if an argument it accepted was never dispatched. - Session environment variables live in three places: the live
/usr/local/bin/synui-session, and two blocks insyn-install.sh. foot.iniis generated in three places, with two different tokenizers.- chibi has three copies of every module.
- The event-sound id chains exist twice:
sound_event_ids()insynui/src/sound.candids()insynui-sound.sh. They must stay in lockstep — the C side decides what the panel displays, the shell side decides what actually plays, so a drift means the panel confidently names a sample you will never hear.
Package builds run as synbuild
Package builds run as the unprivileged synbuild user under /var/tmp, because
makepkg must not run as root and must live outside /home (mode 0700, so
synbuild can't read it).
A failed package build aborts the run immediately rather than resurfacing later as a confusing pacstrap error. That's deliberate — an earlier version let failures through and they showed up as "package not found" much later.
llama.cpp
Pinned at tag b10241, matching CI and synapse-llama's _llama_ref —
the two are separate constants and must be bumped together. The CUDA build needs
a patch for CCCL 3.4 (cub). From b10241 the Vulkan build also requires
SPIRV-Headers, which was not a dependency at b8272.
--no-clean preserves archiso/build/llama.cpp so this doesn't get recompiled —
it is by far the most expensive step. It is safe: build.sh always wipes
mkarchiso's work/ and gates only build/ on --clean.
Shared git index hazard
Concurrent sessions working in ~/SYNAPSE share one git index. Never unstage
files you didn't stage, and stage + commit atomically (git add <paths> &&
git commit) rather than staging and then doing other work.
See also: Cutting an ISO Release, Troubleshooting.