Skip to content

Commit 5f58e78

Browse files
diagonalcisoclaude
andcommitted
build: bundle matplotlib+pillow in release binaries (plots work out-of-box)
CI builds desktop binaries with NETSIM_WITH_PLOTS=1 (pip install matplotlib pillow) so 'run plots/gif/viz' work with no setup; adds a 'run plots' smoke test (MPLBACKEND=Agg). Trade-off: binaries ~80MB vs ~8-20MB. Android APK unaffected (uses canvas charts). Docs + spec comment updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3fbc811 commit 5f58e78

4 files changed

Lines changed: 39 additions & 15 deletions

File tree

.github/workflows/build.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,17 @@ jobs:
3333
- uses: actions/setup-python@v5
3434
with:
3535
python-version: "3.12"
36-
- run: pip install pyinstaller
37-
- run: pyinstaller netsim.spec --clean --noconfirm
38-
- name: smoke test
36+
- run: pip install pyinstaller matplotlib pillow
37+
- name: build (matplotlib/pillow folded in so plot demos work out-of-box)
38+
run: pyinstaller netsim.spec --clean --noconfirm
39+
env:
40+
NETSIM_WITH_PLOTS: "1"
41+
- name: smoke test — core
3942
run: ${{ matrix.binpath }} bakeoff --cc reno,bbr --time 4
43+
- name: smoke test — bundled plotting
44+
run: ${{ matrix.binpath }} run plots
45+
env:
46+
MPLBACKEND: Agg
4047
- name: rename to unique asset name
4148
shell: bash
4249
run: mv "${{ matrix.binpath }}" "dist/${{ matrix.artifact }}"

PACKAGING.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ is what each one is, in everyday language.
2323
### The desktop programs (pick the one for your computer)
2424

2525
These four files are the **same program**, each compiled for a different kind of
26-
computer. They are *self-contained*: the Python language runtime is baked inside,
27-
so you do **not** need to install Python or anything else. Download, allow it to
28-
run, done.
26+
computer. They are *self-contained*: the Python language runtime **and** the
27+
plotting library (matplotlib) are baked inside, so you do **not** need to install
28+
Python or anything else — even the chart-drawing demos work immediately. Download,
29+
allow it to run, done. (That bundled library is why each download is ~80 MB.)
2930

3031
| If your computer is… | Download this file | What "x86_64 / arm64" means |
3132
|----------------------|--------------------|------------------------------|
@@ -43,6 +44,8 @@ arguments tip-of-the-day style, or give it a command:
4344

4445
- `list` — show all the built-in demonstrations.
4546
- `run m3` — run demo #3 (the TCP "sawtooth"); `m1``m16` are available.
47+
- `run plots` / `run gif` / `run viz` — render the figures/animation (matplotlib
48+
is bundled in the binaries, so these work with no setup).
4649
- `bakeoff …` — a configurable experiment comparing congestion-control
4750
algorithms (see Part 4).
4851
- `web` — start a small website on your own machine (`http://127.0.0.1:8112`)
@@ -184,15 +187,21 @@ is why CI builds each platform on its own runner.
184187
```bash
185188
pip install pyinstaller
186189
pyinstaller netsim.spec --clean --noconfirm
187-
./dist/netsim list # Linux/macOS -> dist/netsim (~7-20 MB)
190+
./dist/netsim list # Linux/macOS -> dist/netsim (~7-20 MB, no plots)
188191
dist\netsim.exe list # Windows -> dist\netsim.exe
189192
```
190193

191-
Fold the plotting demos into the binary too (much bigger — pulls in matplotlib):
194+
A plain local build (above) excludes matplotlib to stay small, so `run
195+
plots`/`gif`/`viz` won't work in it. The **published release binaries** are
196+
instead built with `NETSIM_WITH_PLOTS=1`, which folds matplotlib + pillow in so
197+
the plotting demos work out of the box (at the cost of a larger ~80 MB file).
198+
Reproduce that locally:
192199

193200
```bash
201+
pip install pyinstaller matplotlib pillow
194202
NETSIM_WITH_PLOTS=1 pyinstaller netsim.spec --clean --noconfirm # Linux/macOS
195203
set NETSIM_WITH_PLOTS=1 && pyinstaller netsim.spec --clean --noconfirm # Windows
204+
./dist/netsim run plots # now works -> plots/*.png
196205
```
197206

198207
### Android APK — Chaquopy
@@ -230,9 +239,10 @@ that starts with `v` (e.g. `v1.0.1`) it:
230239
`windows-latest``netsim-windows-x86_64.exe`,
231240
`macos-latest``netsim-macos-arm64`,
232241
`macos-13``netsim-macos-x86_64`.
233-
Each binary is renamed to its unique asset name before upload (Linux and macOS
234-
both produce a file literally called `netsim`, which would otherwise collide
235-
on the Release).
242+
Each is built with `NETSIM_WITH_PLOTS=1` (matplotlib + pillow folded in) and a
243+
plotting smoke-test (`run plots`) before upload, and renamed to its unique
244+
asset name (Linux and macOS both produce a file literally called `netsim`,
245+
which would otherwise collide on the Release).
236246
2. **builds and signs the Android APK** in a separate `android` job (gated on the
237247
repo variable `BUILD_ANDROID` plus the keystore secrets — see below). This job
238248
is independent, so it never blocks the desktop release.

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ Pre-built, **single-file, zero-dependency** binaries are attached to every
6767
[GitHub Release](https://github.com/diagonalciso/netsim/releases/latest). Pick
6868
the one for your platform, mark it executable, and run it. There is nothing to
6969
install — the Python runtime is baked into the binary by PyInstaller (desktop)
70-
or Chaquopy (Android).
70+
or Chaquopy (Android). The desktop binaries also bundle **matplotlib + pillow**,
71+
so the plotting demos (`run plots`, `run gif`, `run viz`) work out of the box
72+
with no extra setup (this is why the desktop downloads are ~80 MB rather than a
73+
few MB).
7174

7275
| Platform | Asset | Notes |
7376
|----------|-------|-------|
@@ -145,7 +148,9 @@ pip install -e '.[plots]' # + matplotlib/pillow for viz/plots/gif demos
145148
```
146149

147150
The plotting demos (`viz`, `plots`, `gif`) are the **only** things that need a
148-
third-party package. Keep matplotlib in a venv so the core stays dependency-free:
151+
third-party package (the pre-built binaries already bundle it; this only applies
152+
when running from source). Keep matplotlib in a venv so the core stays
153+
dependency-free:
149154

150155
```bash
151156
python3 -m venv .venv && .venv/bin/pip install matplotlib pillow

netsim.spec

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
# pyinstaller netsim.spec # -> dist/netsim (or dist/netsim.exe)
55
#
66
# The examples/ dir is bundled as data so `netsim run mN` works inside the
7-
# frozen binary. matplotlib is NOT collected by default (keeps the binary
7+
# frozen binary. matplotlib is NOT collected by default (keeps a local build
88
# small + the stdlib demos work everywhere); build with NETSIM_WITH_PLOTS=1
9-
# to fold matplotlib/pillow in for the viz/plots/gif demos.
9+
# to fold matplotlib/pillow in for the viz/plots/gif demos. The CI release
10+
# binaries ARE built with NETSIM_WITH_PLOTS=1, so the published downloads have
11+
# the plotting demos working out of the box (at the cost of a larger file).
1012
import os
1113
from PyInstaller.utils.hooks import collect_all
1214

0 commit comments

Comments
 (0)