Files
MeshTerm/packaging/meshterm.spec
T
Jean-Pierre MartineauandClaude Opus 5 4f60f44512 A build you can download and run without Python
Most people who want MeshTerm have a radio and a terminal, not a Python
toolchain. This is the install for them: one file, download it, run it.

`packaging/meshterm.spec` freezes the app with PyInstaller in console mode —
which is not a detail, since a windowed build of a terminal program starts with
nowhere to draw and exits. The assets land at `meshterm/assets` inside the bundle
so that `Path(__file__).parent.parent / "assets"` keeps resolving exactly as it
does in a checkout, and bleak's per-platform backends are named as hidden imports
because nothing static ever sees the one that actually gets used. UPX is off: a
few megabytes are not worth being flagged by antivirus on a first release.

The build was run here rather than only written. The Windows executable comes out
at 14 MB, runs from a directory with no source tree in sight, and draws the
specimen card — which is the real test, because the specimen reads the asset
files.

`installers.yml` does the same on five machines, because frozen builds cannot be
cross-compiled. Windows, macOS on both Apple silicon and Intel (plenty of people
still have one, and an arm64 build will not run for them), and Linux on x64 and
ARM64 — the last for the uConsole. Each leg runs the binary from a temporary
directory before uploading it, so a build that only works beside its own source
fails on the runner instead of on somebody's laptop, and each one gets a checksum
written beside it. It publishes nothing; attaching these to a release stays a
separate decision.

Also here: `meshterm --help` now opens with the same sentence as the package
summary, rather than a fourth description of the project written in its own way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 05:00:22 -04:00

68 lines
2.1 KiB
RPMSpec

# PyInstaller spec for the downloadable builds. Run from the repository root:
#
# pyinstaller packaging/meshterm.spec
#
# One file, console mode. Console is not a detail: MeshTerm *is* a terminal program, and
# a windowed build would start with nowhere to draw and exit immediately.
#
# Built on the machine it targets. There is no cross-compiling here — the Windows build
# comes off a Windows runner, the macOS one off macOS. That is what the workflow is for.
from PyInstaller.utils.hooks import collect_submodules
# The assets have to land at `meshterm/assets`, because `ui/about.py` finds them with
# `Path(__file__).parent.parent / "assets"` and that path has to keep resolving inside
# the bundle exactly as it does in a checkout.
datas = [
("../meshterm/assets", "meshterm/assets"),
]
hiddenimports = [
# bleak picks its backend at runtime by platform, so static analysis never sees the
# one that actually gets used. Collect all of them and let the unused ones sit.
*collect_submodules("bleak.backends"),
# Same story for the companion library's transports.
*collect_submodules("meshcore"),
# Rich and prompt_toolkit both reach for things dynamically.
"rich.console",
"prompt_toolkit.output.win32",
"prompt_toolkit.output.vt100",
]
a = Analysis(
["entry.py"],
pathex=[".."],
binaries=[],
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
# Nothing here is used, and each one drags in a GUI toolkit or a test framework.
excludes=["tkinter", "pytest", "IPython", "matplotlib", "numpy", "PIL"],
noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name="meshterm",
debug=False,
bootloader_ignore_signals=False,
strip=False,
# UPX is off deliberately: it saves a few megabytes and gets the result flagged by
# antivirus often enough that it is not a trade worth making for a first release.
upx=False,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)