@@ -45,63 +45,49 @@ jobs:
4545 include :
4646 - os : ubuntu-latest
4747 platform : linux-x86_64
48- extra_build_flags : --clang
4948
5049 - os : macos-latest
5150 platform : macos-universal2
52- extra_build_flags : --clang --macos-target-arch=universal
5351
5452 - os : windows-latest
5553 platform : windows-x86_64
56- extra_build_flags : " "
5754
5855 steps :
5956 - uses : actions/checkout@v4
6057
6158 - uses : actions/setup-python@v5
6259 with :
6360 python-version : " 3.11"
64- # No cache: pip β we cache the entire installed env in Layer 1,
65- # which is strictly better (zero pip activity on a cache hit).
6661
6762 # ββ Layer 1: installed Python environment ββββββββββββββββββββββββββββ
68- # Caches the full Python + site-packages directory. On a hit, pip is
69- # never invoked at all. Keyed on pyproject.toml only β bangen itself
70- # is installed with -e (editable) so source changes are always live
71- # without busting this cache.
7263 - name : Cache pip environment
7364 id : pip-cache
7465 uses : actions/cache@v4
7566 with :
7667 path : ${{ env.pythonLocation }}
7768 key : pip-env-${{ runner.os }}-py3.11-${{ hashFiles('pyproject.toml') }}
78- # Intentionally no restore-keys: a partial env restore causes subtle
79- # import errors that are harder to debug than a clean install.
8069
8170 - name : Install dependencies
8271 if : steps.pip-cache.outputs.cache-hit != 'true'
8372 run : |
8473 python -m pip install --upgrade pip
85- pip install -e . nuitka
86-
87- # ββ Layer 2: sccache (C compiler output cache) βββββββββββββββββββββββ
88- # Nuitka translates Python β C, then compiles the C with clang/MSVC.
89- # sccache caches the compiled C object files keyed on content hash,
90- # so unchanged modules are never recompiled.
91- #
92- # Linux / macOS: we shim the clang binary so every compiler call Nuitka
93- # makes goes through sccache transparently. The shim must land before
94- # /usr/bin in PATH β /usr/local/bin satisfies this on both runners.
95- #
96- # Windows: Nuitka calls cl.exe (MSVC) through its own Scons backend in
97- # a way that cannot be intercepted with a shim. Layer 3 carries Windows.
74+ pip install -e . "nuitka[onefile]"
75+
76+ # ββ Layer 2: sccache (C compiler object file cache) ββββββββββββββββββ
77+ # Intercepts clang calls on Linux/macOS via a shim in /usr/local/bin.
78+ # Windows MSVC (cl.exe) is called through Nuitka's Scons backend in a
79+ # way that cannot be shimmed β Layer 3 handles Windows compilation cost.
9880 -
uses :
mozilla-actions/[email protected] 9981
100- - name : Configure sccache
82+ - name : Install clang (Linux)
83+ if : runner.os == 'Linux'
84+ run : sudo apt-get install -y clang
85+
86+ - name : Configure sccache + compiler shim
10187 shell : bash
10288 run : |
103- echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV"
104- echo "SCCACHE_CACHE_SIZE=2G" >> "$GITHUB_ENV"
89+ echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV"
90+ echo "SCCACHE_CACHE_SIZE=2G" >> "$GITHUB_ENV"
10591
10692 if [ "${{ runner.os }}" = "Linux" ]; then
10793 REAL_CLANG="$(which clang)"
@@ -119,14 +105,6 @@ jobs:
119105 fi
120106
121107 # ββ Layer 3: Nuitka bytecode + download cache βββββββββββββββββββββββββ
122- # Caches two things inside Nuitka's cache dir:
123- # β’ PythonβC translation results (expensive, source-sensitive)
124- # β’ Onefile bootstrap downloads (AppImage on Linux, etc. β one-time)
125- #
126- # Three-tier restore-key cascade:
127- # 1. Exact hit β source + deps unchanged, fully warm
128- # 2. Deps hit β only deps unchanged; translation cache partially warm
129- # 3. OS hit β bootstrap downloads reused; compilation starts cold
130108 - name : Set Nuitka cache dir
131109 shell : bash
132110 run : |
@@ -143,9 +121,7 @@ jobs:
143121 ~/.cache/Nuitka
144122 ~/AppData/Local/Nuitka
145123 key : >-
146- nuitka-${{ runner.os }}-py3.11-
147- ${{ hashFiles('pyproject.toml') }}-
148- ${{ hashFiles('bangen/**/*.py', '_entry.py') }}
124+ nuitka-${{ runner.os }}-py3.11-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('bangen/**/*.py') }}
149125 restore-keys : |
150126 nuitka-${{ runner.os }}-py3.11-${{ hashFiles('pyproject.toml') }}-
151127 nuitka-${{ runner.os }}-py3.11-
@@ -161,44 +137,71 @@ jobs:
161137 main()
162138 EOF
163139
164- - name : Build (Nuitka onefile optimized)
140+ # Shared Nuitka flags, extracted to an env var to avoid duplication
141+ # across the two macOS arch passes and the single Linux/Windows pass.
142+ - name : Set common Nuitka flags
143+ shell : bash
144+ run : |
145+ cat >> "$GITHUB_ENV" << 'EOF'
146+ NUITKA_COMMON_FLAGS=--mode=onefile --assume-yes-for-downloads --output-dir=build --follow-imports --include-package=bangen --include-package=rich --include-package-data=rich --include-package=pyfiglet --include-package-data=pyfiglet --include-package=PIL --include-package=typer --include-package=click --nofollow-import-to=tkinter --nofollow-import-to=unittest --nofollow-import-to=test --nofollow-import-to=distutils --nofollow-import-to=setuptools --nofollow-import-to=pkg_resources --lto=yes --python-flag=no_asserts --python-flag=no_docstrings --python-flag=isolated --onefile-tempdir-spec={CACHE_DIR}/bangen/${{ needs.metadata.outputs.version }}
147+ EOF
148+
149+ # ββ macOS: two separate arch passes + lipo fat binary βββββββββββββββββ
150+ # Nuitka onefile cannot produce a universal2 binary in a single pass
151+ # (fatal error). Build arm64 and x86_64 separately, then lipo-merge.
152+ - name : Build arm64 (macOS)
153+ if : runner.os == 'macOS'
165154 shell : bash
166155 run : |
167156 python -m nuitka \
168- --mode=onefile \
169- --assume-yes-for-downloads \
170- --output-dir=build \
157+ $NUITKA_COMMON_FLAGS \
158+ --output-filename=bangen-arm64 \
159+ --clang \
160+ --macos-target-arch=arm64 \
161+ _entry.py
162+
163+ - name : Build x86_64 (macOS)
164+ if : runner.os == 'macOS'
165+ shell : bash
166+ run : |
167+ python -m nuitka \
168+ $NUITKA_COMMON_FLAGS \
169+ --output-filename=bangen-x86_64 \
170+ --clang \
171+ --macos-target-arch=x86_64 \
172+ _entry.py
173+
174+ - name : Lipo merge β universal2 (macOS)
175+ if : runner.os == 'macOS'
176+ shell : bash
177+ run : |
178+ lipo -create \
179+ -output build/bangen \
180+ build/bangen-arm64 \
181+ build/bangen-x86_64
182+
183+ # ββ Linux / Windows: single pass ββββββββββββββββββββββββββββββββββββββ
184+ - name : Build (Linux)
185+ if : runner.os == 'Linux'
186+ shell : bash
187+ run : |
188+ python -m nuitka \
189+ $NUITKA_COMMON_FLAGS \
171190 --output-filename=bangen \
172- --follow-imports \
173- \
174- --include-package=bangen \
175- \
176- --include-package=rich \
177- --include-package-data=rich \
178- \
179- --include-package=pyfiglet \
180- --include-package-data=pyfiglet \
181- \
182- --include-package=PIL \
183- \
184- --include-package=typer \
185- --include-package=click \
186- \
187- --nofollow-import-to=tkinter \
188- --nofollow-import-to=unittest \
189- --nofollow-import-to=test \
190- --nofollow-import-to=distutils \
191- --nofollow-import-to=setuptools \
192- --nofollow-import-to=pkg_resources \
193- \
194- --lto=yes \
195- --python-flag=no_asserts \
196- --python-flag=no_docstrings \
197- --python-flag=isolated \
198- --onefile-tempdir-spec="{CACHE_DIR}/bangen/${{ needs.metadata.outputs.version }}" \
199- ${{ matrix.extra_build_flags }} \
191+ --clang \
200192 _entry.py
201193
194+ - name : Build (Windows)
195+ if : runner.os == 'Windows'
196+ shell : bash
197+ run : |
198+ python -m nuitka \
199+ $NUITKA_COMMON_FLAGS \
200+ --output-filename=bangen \
201+ _entry.py
202+
203+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
204+
202205 - name : Prepare release asset
203206 shell : bash
204207 run : |
0 commit comments