Repository navigation
Building
EDLD runs directly from a checkout with no build step.
git clone https://github.com/indevlin/EDLD.git
cd EDLD
pip install -r requirements.txt
python edld.py # EDCARS, the desktop window (default)
python edld.py --dashg # desktop window, Dashboard layout (or --gui)
python edld.py --dasht # terminal dashboard (or --tui)
python edld.py --term # scrolling event log (or --text)The interfaces read the same journal, the same config and the same per-commander data, so you can switch freely between them.
-
PySide6 is needed only for the desktop window — EDCARS, the default, and
--dashg. Without it the terminal modes work normally, a plain launch opens the terminal dashboard and says why, and--edcarsor--dashgexits with an explanatory message. -
Textual is needed only for
--dasht. Without it--termstill works. -
cryptography and segno are needed only for server mode (
-s, the EDAM mobile app; see SERVER.md). Without cryptography the server says so and EDLD carries on without it; without segno--pairprints the code as text instead of a QR code. -
psutil is needed only for session management. Install it from your distro
package manager rather than pip — it has C extensions:
sudo pacman -S python-psutil/sudo apt install python3-psutil/sudo dnf install python3-psutil.
pip install -r requirements-dev.txt
pyinstaller packaging/edld.spec --noconfirm --cleanscripts/build_local.sh runs the same sequence the Release workflow runs, on
this machine: the preflight on the checkout, the PyInstaller build, both smoke
tests, the archive with the license texts, and the SHA-256 file.
scripts/build_local.sh # build, test, package into out/
scripts/build_local.sh --no-package # build and test only
scripts/build_local.sh --dir # directory layout instead of onefile
scripts/build_local.sh --skip-tests # skip the smoke tests
scripts/build_local.sh --sign # also sign, using SIGNING_KEY
scripts/build_local.sh --server # EDLD-server: no dashboards--server builds EDLD-server, the same program without either dashboard —
no Qt, no Textual, about a fifth of the size — named EDLD-<version>-server-….
By hand it is EDLD_VARIANT=server pyinstaller packaging/edld.spec. See
SERVER.md.
Artefacts land in out/, named exactly as the release ones are. On Windows run
it from Git Bash or MSYS2. PyInstaller does not cross-compile, so this builds
for the platform it runs on — three machines are still needed for a full set.
It is also the fastest way to tell a broken tree from a broken runner: if this passes and CI does not, the difference is the runner, not the code.
The artefact lands in dist/ — dist/EDLD on Linux, dist/EDLD.exe on
Windows, dist/EDLD.app on macOS.
Verify it starts, and that both interfaces load:
./dist/EDLD --version # should print the contents of ./version
./dist/EDLD --selftest # imports each front end and reportsBoth matter. --version proves the process starts; --selftest proves the
interfaces are actually intact. A packaged build can start perfectly and still
be missing a module that only fails when the dashboard is drawn — Textual
resolves its widgets through a runtime __getattr__, which static analysis
cannot follow, so this has happened. The release workflow runs both on every
platform.
Qt needs a handful of X libraries present at runtime. On a bare CI image:
sudo apt-get install -y libegl1 libxkbcommon-x11-0 libxcb-cursor0 \
libxcb-icccm4 libxcb-keysyms1 libxcb-shape0 libxcb-randr0 \
libxcb-render-util0 libxcb-xinerama0Add xvfb if you want to run the GUI headlessly.
This is the LGPLv3 4(d)(1) route, and it is deliberately easy — see LICENSING.md.
pip install --force-reinstall /path/to/your/PySide6-wheel
pyinstaller packaging/edld.spec --noconfirm --cleanNothing in the spec pins a Qt version or links it statically, so the binary you get is equivalent to the official one but built against your Qt.
The spec produces a single file. If you would rather have the Qt shared
libraries as visibly separate files, build with -D:
pyinstaller packaging/edld.spec --noconfirm --clean -DThree things are shipped as data because the code alone is not enough:
-
components/— the component sources, in addition to being compiled in.core/plugin_loader.pydiscovers components by globbing that directory and loads each by file path, giving every one its own namespace and a sandboxedopen(). That needs real files on disk, which a one-file build does not otherwise have. -
A CA bundle (
certifi) — a frozen binary carries its own OpenSSL, built with the build machine's certificate paths compiled in. Those paths rarely exist on the target machine, so without a bundled store every HTTPS call fails verification and CAPI, EDDN, EDSM, EDAstro, Inara and Spansh all stop working with no visible error.core/certs.pypoints OpenSSL at the bundled copy at startup. -
licenses/— required to accompany the binary by LGPLv3 section 4(b).
Each has already been the cause of a build that looked fine and was not.
core/plugin_loader.py discovers components by walking components/ at
runtime, and both front ends resolve their dashboard blocks by name. None of
that is visible to PyInstaller's static analysis, so every component and block
is named explicitly in packaging/build_common.py, which enumerates the
directories rather than hard-coding a list.
A component missing from that list produces a binary that builds cleanly, starts cleanly, and shows an empty dashboard. That failure mode is the reason the release workflow smoke-tests every artefact before publishing it.
Textual is collected wholesale for the same reason from the other direction:
textual.widgets imports lazily by a name built at runtime, so nothing static
analysis can see refers to most of its widgets.
Tag with a bare YYYYMMDD datestamp matching the version file, as a signed
tag:
echo 20261101 > version
python3 sheets/build_bundle.py # the sheet bundle carries the version
git commit -am "Release 20261101"
git tag -s 20261101 -m "Release 20261101"
git push origin main --tagsThe authoritative repository is git.indevlin.com, mirrored to GitHub, where
the workflow runs; see SIGNING.md.
The Release workflow checks the tag matches the version file, verifies the
checkout contains everything the build needs and that the sheet bundle was
rebuilt for this version, then builds and smoke-tests
EDLD for Linux, Windows and macOS and EDLD-server for Linux and Windows, signs
the checksum manifest, and publishes a release with notes taken from
CHANGELOG.md.
A version with a suffix — 20261101-rc1 — is published as a prerelease. To
build everything without publishing, run the workflow manually from the Actions
tab with dry_run left on. That works from any branch, dev included: the
artefacts are named from the version file and attached to the run.
Survey sheets are not released this way at all. They follow a branch — main
by default — so merging to main releases sheet code, and a test sheet can
follow dev to try it first. See Trying sheet code before it is
released.
Getting Started
Guides
Reference
- Automation
- Building
- Configuration
- Dossier
- Edcars
- Exploration Exobiology Plan
- Licensing
- Mission Bootstrap
- Privacy
- Roadmap
- Server
- Signing
- Startup
- Streamer Stats Overlay
- Surface Survey
- Terminal Output
- Theming
Releases