Build & Packaging
How YggdraSIM is published and run: an editable source install, a Docker image, and a bundled launcher build — each in a HIL and a non-HIL flavor. Use this to pick and produce the right distribution shape.
On this page
Distribution models
The repository supports three publication and distribution paths:
- editable install from a source checkout
- containerized execution through
Dockerfile - bundled launcher builds through
yggdrasim_main.spec
Each of those is published in two flavors:
| Flavor | HIL bridge included | Platforms | Typical operator |
|---|---|---|---|
clean |
no | Windows x86_64 / macOS x86_64 + arm64 / Linux x86_64 / Raspberry Pi arm64 | desktop / CI / field |
full |
yes | Linux x86_64 only | HIL lab |
| source | optional via [hil] |
any supported Python host | developer |
Optional extras (orthogonal to the flavor split)
These extras are independently selectable on a source install.
| Extra | Adds | Use when |
|---|---|---|
[saip] |
(empty back-compat alias; pySim is already in base deps) | onboarding scripts that reference the old name |
[hil] |
pyudev (Linux only) |
enabling the HIL bridge supervisor on a source install |
[build] |
pyinstaller |
building flavored launcher artifacts |
[test] |
pytest |
running the test suite |
[docs] |
mkdocs-material, plugins |
building / serving this site locally |
[full] |
[hil] + [build] + [test] |
one-shot install of the HIL-capable source flavor |
The active flavor is selected at build time through the
YGGDRASIM_FLAVOR environment variable. The PyInstaller spec writes a
yggdrasim_common/_build_flavor.py stamp so that runtime surfaces such
as --version, --doctor, and the main menu can report the correct
SKU even when the variable is not exported afterwards.
External host dependencies still matter for real card workflows,
especially PC/SC libraries, reader drivers, and optional gpg.
Docker
The image is flavor-aware through a build argument:
# Clean (Windows / macOS / Linux hosts)
docker build -t yggdrasim:clean .
# Full (HIL-capable; Linux host, USB passthrough required at runtime)
docker build --build-arg YGGDRASIM_FLAVOR=full -t yggdrasim:full .
Typical use:
docker run --rm -it yggdrasim:clean
docker run --rm -it yggdrasim:clean yggdrasim-profile-package --cmd "HELP; EXIT"
Persist runtime state:
docker run --rm -it \
-v "$(pwd)/YggdraSIM-data:/opt/YggdraSIM-data" \
yggdrasim:clean yggdrasim-scp11-live --cmd "HELP; EXIT"
Containers are most predictable for offline analysis, simulator flows,
docs, and CI smoke paths. Real reader access still depends on
host-specific USB, PC/SC, and permission setup. HIL mode additionally
requires explicit SIMtrace2 passthrough; see guides/HIL_BRIDGE_GUIDE.md
and guides/SIMTRACE2_CARDEM_GUIDE.md.
Bundled launcher
The committed yggdrasim_main.spec builds the unified launcher as one
flavored executable. Install build extras first:
python -m pip install -e '.[build,test]' # clean
python -m pip install -e '.[full]' # full (Linux)
Clean build:
YGGDRASIM_FLAVOR=clean python -m PyInstaller --noconfirm --clean yggdrasim_main.spec
Full build (Linux x86_64):
YGGDRASIM_FLAVOR=full python -m PyInstaller --noconfirm --clean yggdrasim_main.spec
Expected outputs:
- Linux:
dist/yggdrasim-cleanordist/yggdrasim-full - Windows:
dist/yggdrasim-clean.exe(no full build published) - macOS:
dist/yggdrasim-clean(no full build published)
Build on the target OS and architecture; CI emulates arm64 through QEMU/Buildx to publish the Raspberry Pi clean bundle.
Debian package path
The cleanest .deb flow is:
- build the bundled launcher with PyInstaller (typically the
cleanflavor) - wrap that artifact in a Debian package
- declare host runtime dependencies such as
libpcsclite1,pcscd, orgpg
Minimal skeleton (clean):
mkdir -p pkg/DEBIAN pkg/usr/lib/yggdrasim pkg/usr/bin
cp dist/yggdrasim-clean pkg/usr/lib/yggdrasim/yggdrasim
ln -sf /usr/lib/yggdrasim/yggdrasim pkg/usr/bin/yggdrasim
A full-flavor .deb should additionally depend on
osmo-remsim-client-st2 and dfu-util.
Writable runtime expectations
Frozen builds keep bundled assets read-only and move mutable state into the writable runtime root:
YggdraSIM-datanext to the executable when writable~/YggdraSIM-dataas fallbackYGGDRASIM_RUNTIME_ROOTwhen the runtime location must be forced explicitly
Recommended validation
Validate these before publication:
dist/yggdrasim-{clean,full} --versionprints the expected flavordist/yggdrasim-{clean,full} --doctorreports green on the target host, including the HIL probes forfullbuilds- the launcher opens and creates the writable runtime tree where expected
SCP11,SCP11.live, andSCP11.local_accesscan read seeded runtime materialyggdrasim-profile-packagecan still locatepySim(either the installed PyPI wheel or the optional on-diskpysim/clone when the SAIP ASN.1 compile path is needed)- state persistence writes land in runtime state, not inside the installed bundle
- smart-card flows are tested on each target OS that will be supported
- on
fullbuilds, the HIL bridge can acquire the reader, launchosmo-remsim-client-st2, and mirror GSMTAP to Wireshark
Deep reference
Use these authored guides for the complete reference:
guides/BUILD_AND_PACKAGING.md- full packaging walkthroughguides/INSTALL_CLEAN.md- clean executable installguides/INSTALL_FULL.md- full (HIL) executable installguides/INSTALL_FROM_SOURCE.md- source install matrixguides/INSTALL_RASPBERRYPI.md- Raspberry Pi notesguides/SIMTRACE2_CARDEM_GUIDE.md- SIMtrace2 firmware / toolchain