fix(docker): patch pytantan CMakeLists to scrub AVX2 at the source#68
Merged
Conversation
added 3 commits
May 25, 2026 08:26
The prior rebuild logic relied on SKBUILD_CMAKE_ARGS='-DHAVE_AVX2=OFF' to
disable AVX2 in pytantan's CMake build. Empirically that single channel did
not make it into the final image: published builds shipped a populated
pytantan/platform/avx2.so and a lib.so with thousands of AVX/AVX2 hits,
causing 'import pytantan' to SIGILL under Rosetta 2 on Apple Silicon.
Replace the rebuild step with three independent gates so no single failure
can reintroduce AVX2:
1. Source patch: clone pytantan v${PYTANTAN_VERSION}, then surgically
delete the if(HAVE_SSE4|HAVE_AVX2|HAVE_NEON) ... endif() blocks from
the top-level CMakeLists.txt and src/pytantan/platform/CMakeLists.txt
(nesting-aware), and drop the corresponding Find*.cmake include()s.
This leaves only the scalar 'generic' Cython extension in the build
graph; add_compile_options(-mavx2) is no longer reachable.
2. Real config-settings: invoke pip with
--config-settings=cmake.define.HAVE_{SSE4,AVX2,NEON}=OFF
plus CMAKE_ARGS as a belt-and-braces redundancy.
3. Cache invalidation: introduce ARG PYTANTAN_CACHEBUST (exposed as ENV
_PT_CACHEBUST inside the RUN) so the layer hash changes when bumped,
defeating BuildKit GHA cache reuse that could mask a broken rebuild.
Strengthen the verification step too: enumerate every .so under the pixi
env, print per-file AVX hit counts to the build log (visible on success),
and fail on any positive count using a broader mnemonic set
(vpbroadcast, vfmadd, vpermd, vpgatherdd, vextracti128/vinserti128,
ymm*, zmm*).
The ghcr.io/prefix-dev/pixi base image has no system python3 on PATH;
the heredoc patcher in the pytantan rebuild RUN failed with exit 127
('python3: not found') before pip was ever invoked. Use the pixi-managed
interpreter at /app/.pixi/envs/default/bin/python, which is guaranteed
to exist after 'pixi install --locked'. Bump PYTANTAN_CACHEBUST to 3 so
the layer is re-executed.
The 'vendor/tantan' subdir of pytantan is a git submodule. Our manual 'git clone --depth 1 --branch v0.1.3' did not initialize submodules, so 'vendor/tantan/src/tantan.cc' was missing and CMake failed with: Cannot find source file: cbrc_linalg.cc Cannot find source file: .../build/Release/src/tantan/src/tantan.cc (The previous 'pip install git+...@v0.1.3' form worked by accident because pip's git fetcher recurses submodules by default.) Add --recurse-submodules --shallow-submodules to the clone, bump PYTANTAN_CACHEBUST.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
PR #67 pinned
pytantanto v0.1.3 and rebuilt it from source withSKBUILD_CMAKE_ARGS='-DHAVE_AVX2:BOOL=OFF;-DAVX2_C_FLAGS:STRING='. That envvar is a real scikit-build-core knob (it maps to
cmake.args), but thepublished
:latestimage proved that the override did not survive into thefinal build: container inspection shows a populated
pytantan/platform/avx2.soand
pytantan/lib.sowith 3,404 AVX/AVX2 instruction hits. As a resultimport pytantanSIGILLs under Rosetta 2 on Apple Silicon even on macOS 15.6with the Apple Virtualization Framework + Rosetta-x86 enabled.
The in-Dockerfile guard added in PR #67 was supposed to catch this and fail
the build, but it didn't — most likely a stale BuildKit GHA layer was reused.
What
Replace the single
SKBUILD_CMAKE_ARGS-only rebuild with three independentgates so no single failure can reintroduce AVX2:
v${PYTANTAN_VERSION}and run a smallPython script that walks the top-level and
src/pytantan/platform/CMakeLists.txt, deletes everyif(HAVE_SSE4|HAVE_AVX2|HAVE_NEON) ... endif()block (nesting-aware —pytantan's blocks contain a nestedif(IMPL_FLAGS), so a naive non-greedy regex would mis-balance), andremoves the corresponding
Find*.cmakeinclude()lines. After thepatch, only the scalar
genericCython extension is in the build graphand
add_compile_options(-mavx2)is not reachable from any code path.--config-settings=cmake.define.HAVE_{SSE4,AVX2,NEON}=OFF(direct pipplumbing) and
CMAKE_ARGS=...(standard CMake env), as belt-and-braces.ARG PYTANTAN_CACHEBUST(exposed as ENV_PT_CACHEBUSTinside the RUN) so the layer hash changes when bumped,defeating GHA layer reuse that could otherwise mask a broken rebuild.
Also strengthens the verification step: it now enumerates every
.sounderthe pixi env, prints per-file AVX hit counts to the build log (visible on
success), and fails on any positive count using a broader mnemonic set
(
vpbroadcast,vfmadd,vpermd,vpgatherdd,vextracti128/vinserti128,ymm*,zmm*).Verification done locally
The Python patcher was sanity-checked against a fresh clone of
althonos/pytantan@v0.1.3. After patching:CMakeLists.txtends up withset(HAVE_SSE4 OFF)/set(HAVE_AVX2 OFF)/set(HAVE_NEON OFF)lines in place of the three SIMD blocks, and theFind{SSE4,AVX2,NEON}.cmakeincludes are gone.src/pytantan/platform/CMakeLists.txtcontains only thegenericcython_extension(...)call — the conditionalsse4/avx2/neonextensions are gone.
Follow-up after merge
main(push=true) to overwrite
:latest.nextgenusfs/funannotate2:latest:OK 0.1.3instead of SIGILLing.Pull Request opened by Augment Code with guidance from the PR author