diff --git a/packaging/appimage/build.sh b/packaging/appimage/build.sh index c0b815f..62dec9e 100755 --- a/packaging/appimage/build.sh +++ b/packaging/appimage/build.sh @@ -463,9 +463,15 @@ _compile_pywhispercpp_vulkan() { found {exit}' "$REPO_ROOT/requirements/vad.txt" > "$WORKDIR/pywhispercpp.txt" # Hosts that default cc/c++ to clang (this Cloud Agent image) fail the # CMAKE C++ compiler test: clang does not search gcc's libstdc++ path. + # GGML_NATIVE is ggml's default and compiles libggml-cpu with -march=native, + # tuned to whichever runner the build lands on. A runner with AVX-512 ships a + # libggml-cpu.so that dies with SIGILL on any CPU without it (#938), and the + # native cache then serves the same binary to every later build. OFF builds + # the portable baseline the PyPI wheel already ships; the Vulkan path is + # unaffected because its shaders run on the GPU. if ! CC="${CC:-gcc}" CXX="${CXX:-g++}" \ GGML_VULKAN=1 \ - CMAKE_ARGS="-DCMAKE_INSTALL_RPATH=\$ORIGIN -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DVulkan_INCLUDE_DIR=$VULKAN_INCLUDE_DIR" \ + CMAKE_ARGS="-DCMAKE_INSTALL_RPATH=\$ORIGIN -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DGGML_NATIVE=OFF -DVulkan_INCLUDE_DIR=$VULKAN_INCLUDE_DIR" \ uv_install --verbose --require-hashes --no-deps \ --reinstall-package pywhispercpp --no-binary pywhispercpp \ -r "$WORKDIR/pywhispercpp.txt" >"$pip_log" 2>&1; then diff --git a/packaging/flatpak/python3-dependencies.yaml b/packaging/flatpak/python3-dependencies.yaml index b6864fc..c6b484a 100644 --- a/packaging/flatpak/python3-dependencies.yaml +++ b/packaging/flatpak/python3-dependencies.yaml @@ -26,7 +26,12 @@ modules: # Assert the shape instead. - python3 -c "from pathlib import Path; p = Path('pywhispercpp-1.5.0/setup.py'); s = p.read_text(); n = 'setup(\\n name=\"pywhispercpp\",'; assert n in s, 'pywhispercpp setup.py no longer matches the injection point'; p.write_text(s.replace(n, n + '\\n version=\"1.5.0\",'))" - tar --owner=0 --group=0 -czf pywhispercpp-1.5.0.tar.gz pywhispercpp-1.5.0 - - PYWHISPERCPP_VERSION=1.5.0 NO_REPAIR=1 GGML_VULKAN=1 pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}" + # GGML_NATIVE is ggml's default and compiles libggml-cpu with + # -march=native, so the package inherits whichever instruction set the + # Flatpak builder has. An AVX-512 builder ships a binary that SIGILLs on + # any CPU without it (#938). OFF ships the portable baseline the PyPI + # wheel carries. + - PYWHISPERCPP_VERSION=1.5.0 NO_REPAIR=1 GGML_VULKAN=1 CMAKE_ARGS="-DGGML_NATIVE=OFF" pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}" --prefix=${FLATPAK_DEST} "pywhispercpp" --no-build-isolation # whisper.cpp installs its shared libraries next to the extension module. # Symlink them onto the default loader path so the extension resolves them diff --git a/tests/test_appimage_packaging.py b/tests/test_appimage_packaging.py index 98b6b5f..3b5fc69 100644 --- a/tests/test_appimage_packaging.py +++ b/tests/test_appimage_packaging.py @@ -251,6 +251,21 @@ def test_vulkan_builds_against_pinned_headers_not_the_base_image_ones(): ), "the rebuild does not point ggml at the pinned headers" +def test_vulkan_rebuild_does_not_borrow_the_builders_instruction_set() -> None: + """GGML_NATIVE is ggml's default and puts -march=native on libggml-cpu, so + the AppImage inherits whichever instruction set the CI runner has. A runner + with AVX-512 ships a binary that SIGILLs on any CPU without it (#938), and + the shared native cache then serves the same one to every later build. OFF + matches the portable baseline the PyPI wheel falls back to.""" + text = BUILD_SH.read_text(encoding="utf-8") + command_lines = [line for line in text.splitlines() if not line.lstrip().startswith("#")] + cmake_args = re.findall(r'CMAKE_ARGS="([^"]*)"', "\n".join(command_lines)) + assert any("-DGGML_NATIVE=OFF" in args for args in cmake_args), ( + "the Vulkan rebuild must not compile with -march=native; the AppImage" + " runs on CPUs the runner's instruction set does not describe" + ) + + def test_vulkan_shaders_get_the_compiler_the_base_image_lacks(): """ggml demands glslc specifically, and Ubuntu 22.04 packages none.""" text = BUILD_SH.read_text(encoding="utf-8") diff --git a/tests/test_flatpak_packaging.py b/tests/test_flatpak_packaging.py index 649d614..c97a682 100644 --- a/tests/test_flatpak_packaging.py +++ b/tests/test_flatpak_packaging.py @@ -218,6 +218,25 @@ def test_the_version_injection_names_the_version_being_built() -> None: ) +def test_the_vulkan_build_does_not_borrow_the_builders_instruction_set() -> None: + """GGML_NATIVE is ggml's default and puts -march=native on libggml-cpu, so + the Flatpak inherits whichever instruction set the builder has, and the + result SIGILLs on any CPU without it (#938). OFF ships the portable + baseline the PyPI wheel carries.""" + module = re.search( + r"^ - name: python3-pywhispercpp$(.*?)(?=^ - name: |\Z)", + DEPS_YAML.read_text(encoding="utf-8"), + re.M | re.S, + ) + assert module, "the pywhispercpp module is gone; this test needs rewriting" + command_lines = [ + line for line in module.group(1).splitlines() if not line.lstrip().startswith("#") + ] + assert any( + "-DGGML_NATIVE=OFF" in line and "pip3 install" in line for line in command_lines + ), "the Flatpak Vulkan build must not compile with -march=native" + + def test_the_manifest_env_agrees_with_the_module() -> None: """build-options.env sets PYWHISPERCPP_VERSION for the whole build. Left behind, it tells the build one version while the module builds another."""