Reference

Build the apps

The release files are built by the same scripts you can run yourself. Each produces a self-contained bundle with a Python interpreter, Qt and every runtime dependency inside, named from the VERSION file.

Entry points

./build.sh          # Linux: AppImage.  macOS: .app
./build.sh --dmg    # macOS: also a .dmg
.\build-windows.ps1 -Zip    # Windows: dist\Corvus GCS\ and a versioned .zip

build.sh dispatches to the script for the computer you are on and never pretends to cross-build. Windows has its own PowerShell entry point; build.sh run from Git Bash on Windows says so rather than trying.

PlatformScriptResult in dist/
Linux x86_64build-appimage.shCorvus_GCS-<version>-x86_64.AppImage
macOS arm64 / x86_64build-macos-app.shCorvus GCS.app, and Corvus_GCS-<version>-macOS-<arch>.dmg with --dmg
Windows x64build-windows.ps1Corvus GCS\, and Corvus_GCS-<version>-windows-x64.zip with -Zip

Linux

Needs Ubuntu or Debian on x86_64, python3 3.12 or newer, pip, wget or curl, and about 1 GB of free disk. The first run downloads appimagetool and the Python wheels and caches them under build/.

An AppImage links against the C library of the machine it was built on, so it runs on that release and newer ones. The official releases are built on Ubuntu 22.04 for that reason; a build on a newer system narrows the machines the file runs on.

macOS

Needs the Xcode command line tools (xcode-select --install) and a framework CPython 3.12 or newer, such as Homebrew's python@3.12 or a python.org install. A conda interpreter cannot be moved into a bundle and is rejected with a clear error.

The app needs macOS 15 or later, because the Qt it ships (PySide6) is built for it. The bundle keeps only the architecture of the Mac it is built on and only the Qt modules Corvus uses (tools/qt_bundle.py), and the build stops if anything left would miss a library it needs.

The bundle is ad hoc signed. To sign it with a developer certificate, set the identity:

CODESIGN_IDENTITY="Developer ID Application: ..." ./build.sh --dmg

Building inside iCloud Drive, OneDrive or Dropbox

The bundle is assembled, signed and verified in a private folder under the system temporary directory, and only then moved to dist/. That is what lets a checkout inside a cloud synced folder build at all: iCloud Drive, OneDrive and Dropbox write Finder metadata into a bundle while it is being built, and codesign refuses a bundle that carries it.

The .dmg is sealed and safe to hand out from anywhere. A loose .app left in a synced dist/ still runs on that Mac, but give other Macs the .dmg. To deliver somewhere else than dist/:

CORVUS_DIST=/tmp/corvus-dist ./build.sh --dmg

Windows

Needs a 64 bit python.org CPython 3.12 or newer on PATH and about 2 GB of free disk for Qt. A conda interpreter is rejected, because its DLLs live outside its own folder and cannot be packaged.

Unlike the other two, the Windows bundle is built with PyInstaller rather than a hand relocated interpreter: Windows puts no constraint on where a DLL may point, so there is nothing for the extra work to buy. The icon (assets\corvus-gcs.ico) is generated from the logo with Pillow, which the build installs into its own environment along with PyInstaller. If that step fails, the build still succeeds with the default icon.

What every build guarantees

  • Self-contained. No system Python, conda or Qt is needed on the target machine.
  • Offline at run time. The build may download wheels and tools once; the running app never needs the network.
  • One version. Every file name, window title and launcher reads the one VERSION file; no script carries a version of its own.
  • The licence travels with it. LICENSE.md is inside every bundle, because the licence requires that whoever receives the software also receives its terms.
  • Clean signals. The launcher hands over to the bundled Python, so quitting from the operating system reaches Corvus's own shutdown directly.

Continuous integration

GitHub Actions runs the tests on Linux and Windows, the linter, the frontend checks, and all three builds with the same scripts, in .github/workflows/build.yml. A tag v<version> publishes the AppImage, the macOS disk image and the Windows zip as a GitHub release. Build output (build/, dist/, *.AppImage, *.dmg, the Windows zip) is never committed.

Running the tests

.venv/bin/python -m pytest -q
.venv/bin/python -m ruff check corvus serve.py tests plugins
node tools/frontend_tests.js

Both runners take the tests in tests/ and those of every plugin in plugins/, which keeps its own in plugins/<id>/tests/. A plugin that is not installed has no tests to run, so leaving one out never fails the suite.

Suggest a change to this page