diff --git a/.github/actions/build-wheel-for-publish/action.yml b/.github/actions/build-wheel-for-publish/action.yml index 1471b2e71c14..db5d5ea84cd2 100644 --- a/.github/actions/build-wheel-for-publish/action.yml +++ b/.github/actions/build-wheel-for-publish/action.yml @@ -129,16 +129,20 @@ runs: # env overrides replace rather than merge, so there is no shared base block. CIBW_ENVIRONMENT_MACOS: >- CMAKE_PREFIX_PATH="/opt/llvm" - CMAKE_ARGS="-DUSE_LLVM='/opt/llvm/bin/llvm-config --link-static' -DZLIB_USE_STATIC_LIBS=ON -DCMAKE_PREFIX_PATH=/opt/llvm ${{ inputs.cmake_defines }} ${{ inputs.include_cuda_runtime == '1' && '-DTVM_PACKAGE_EXTRA_LIBS=/project/build-wheel-cuda/lib/libtvm_runtime_cuda.so' || '' }}" + CMAKE_ARGS="-DUSE_LLVM='/opt/llvm/bin/llvm-config --link-static' -DZLIB_USE_STATIC_LIBS=ON -DCMAKE_PREFIX_PATH=/opt/llvm ${{ inputs.cmake_defines }}" CIBW_ENVIRONMENT_LINUX: >- CMAKE_PREFIX_PATH="/opt/llvm" LIBRARY_PATH="/opt/llvm/lib" - CMAKE_ARGS="-DUSE_LLVM='/opt/llvm/bin/llvm-config --link-static' -DZLIB_USE_STATIC_LIBS=ON -DCMAKE_PREFIX_PATH=/opt/llvm ${{ inputs.cmake_defines }} ${{ inputs.include_cuda_runtime == '1' && '-DTVM_PACKAGE_EXTRA_LIBS=/project/build-wheel-cuda/lib/libtvm_runtime_cuda.so' || '' }}" + CMAKE_ARGS="-DUSE_LLVM='/opt/llvm/bin/llvm-config --link-static' -DZLIB_USE_STATIC_LIBS=ON -DCMAKE_PREFIX_PATH=/opt/llvm ${{ inputs.cmake_defines }} -DTVM_PACKAGE_EXTRA_LIBS=/project/build-wheel-cuda/lib/libtvm_runtime_cuda.so" CIBW_ENVIRONMENT_WINDOWS: >- CMAKE_PREFIX_PATH="C:/opt/llvm/Library" PATH="C:/opt/llvm/Library/bin;$PATH" - CMAKE_ARGS="-DUSE_LLVM='C:/opt/llvm/Library/bin/llvm-config.exe --link-static' -DZLIB_USE_STATIC_LIBS=ON -DCMAKE_PREFIX_PATH=C:/opt/llvm/Library ${{ inputs.cmake_defines }} ${{ inputs.include_cuda_runtime == '1' && format('-DTVM_PACKAGE_EXTRA_LIBS={0}', env.TVM_CUDA_EXTRA_LIB) || '' }}" - # Tells tests/python/wheel to assert the CUDA runtime is bundled - # (only on the CUDA wheels; the value is "0" for CPU wheels). + CMAKE_ARGS="-DUSE_LLVM='C:/opt/llvm/Library/bin/llvm-config.exe --link-static' -DZLIB_USE_STATIC_LIBS=ON -DCMAKE_PREFIX_PATH=C:/opt/llvm/Library ${{ inputs.cmake_defines }} -DTVM_PACKAGE_EXTRA_LIBS=${{ env.TVM_CUDA_EXTRA_LIB }}" + # Turns the wheel-specific assertions in + # tests/python/all-platform-minimal-test/test_validate_runtime_library.py + # ON (they skip unless these are set). Every published wheel is LLVM-enabled, + # so TVM_WHEEL_EXPECT_LLVM is always "1"; the CUDA runtime is only bundled on + # the CUDA wheels, so TVM_WHEEL_EXPECT_CUDA_RUNTIME is "0" for CPU wheels. CIBW_TEST_ENVIRONMENT: >- + TVM_WHEEL_EXPECT_LLVM="1" TVM_WHEEL_EXPECT_CUDA_RUNTIME="${{ inputs.include_cuda_runtime }}" diff --git a/pyproject.toml b/pyproject.toml index c5a16defbb20..baf38b3bcf6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -213,14 +213,14 @@ docstring-code-line-length = "dynamic" skip = "*-win32 *-manylinux_i686 *-musllinux*" build-verbosity = 1 test-requires = ["pytest", "numpy"] -test-command = "pytest -p no:tvm.testing.plugin -vvs {project}/tests/python/wheel && pytest -vvs {project}/tests/python/all-platform-minimal-test" +test-command = "pytest -vvs {project}/tests/python/all-platform-minimal-test" [tool.cibuildwheel.linux] repair-wheel-command = "auditwheel repair --exclude libtvm_ffi.so --exclude libtvm_runtime_cuda.so --exclude 'libcuda.so.*' --exclude 'libcudart.so.*' --exclude 'libnvrtc.so.*' --exclude 'libnvrtc-builtins.so.*' -w {dest_dir} {wheel}" [tool.cibuildwheel.macos] -repair-wheel-command = 'delocate-wheel --ignore-missing-dependencies --exclude libtvm_ffi.dylib --require-archs {delocate_archs} -w {dest_dir} -v {wheel}' +repair-wheel-command = '''bash -c 'set -euo pipefail; r="$(mktemp -d)"; delocate-wheel --ignore-missing-dependencies --exclude libtvm_ffi.dylib --require-archs {delocate_archs} -w "$r" -v "{wheel}"; python -m pip install -q wheel; u="$(mktemp -d)"; python -m wheel unpack "$r"/*.whl -d "$u"; find "$u" -type f \( -name "*.dylib" -o -name "*.so" \) -print0 | xargs -0 -n1 codesign --force --sign -; python -m wheel pack "$u"/*/ -d "{dest_dir}"' ''' [tool.cibuildwheel.windows] -before-build = 'python -m pip install delvewheel' -repair-wheel-command = "delvewheel repair --analyze-existing --ignore-existing --exclude tvm_ffi.dll --exclude libtvm_ffi.dll --exclude tvm_runtime_cuda.dll --exclude nvcuda.dll --exclude cudart64_13.dll --exclude nvrtc64_130_0.dll -w {dest_dir} {wheel}" +before-build = 'python -m pip install "delvewheel>=1.12.0"' +repair-wheel-command = 'delvewheel repair --analyze-existing --ignore-existing --exclude "*tvm_ffi*.dll" --exclude tvm_runtime_cuda.dll --exclude nvcuda.dll --exclude cudart64_13.dll --exclude nvrtc64_130_0.dll -w {dest_dir} {wheel}' diff --git a/tests/python/wheel/test_validate_runtime_library.py b/tests/python/all-platform-minimal-test/test_validate_runtime_library.py similarity index 59% rename from tests/python/wheel/test_validate_runtime_library.py rename to tests/python/all-platform-minimal-test/test_validate_runtime_library.py index 10a455f2a917..928255f6cea4 100644 --- a/tests/python/wheel/test_validate_runtime_library.py +++ b/tests/python/all-platform-minimal-test/test_validate_runtime_library.py @@ -16,12 +16,15 @@ # under the License. """Post-install checks for a built TVM wheel. -Run by cibuildwheel against the installed wheel (``test-command`` in -``[tool.cibuildwheel]``). These assert the two wheel-specific things the standard -``tests/python/all-platform-minimal-test`` suite cannot: that LLVM is enabled (its -LLVM test merely *skips* when LLVM is absent), and that the CUDA runtime library -got bundled (when ``TVM_WHEEL_EXPECT_CUDA_RUNTIME=1``). The functional LLVM -compile / ndarray ops are covered by that all-platform suite. +These live in ``tests/python/all-platform-minimal-test`` so the standard suite and +the cibuildwheel ``test-command`` run a single pytest invocation. The assertions +here are wheel-specific things the rest of the suite cannot check -- that LLVM is +enabled (the other LLVM test merely *skips* when LLVM is absent) and that the CUDA +runtime library got bundled -- so each is gated behind a ``TVM_WHEEL_EXPECT_*`` env +var and SKIPS unless that var is set. cibuildwheel sets the vars (see +``CIBW_TEST_ENVIRONMENT`` in ``.github/actions/build-wheel-for-publish``); ordinary +source-build CI (e.g. ``main.yml``) leaves them unset, so these tests skip there and +never fail a non-wheel / non-LLVM / non-CUDA build. """ import glob @@ -34,8 +37,11 @@ def test_llvm_enabled(): - """Every TVM wheel ships with LLVM enabled. The all-platform suite only skips - (does not fail) when LLVM is absent, so assert presence here.""" + """Every published TVM wheel ships with LLVM enabled. Only assert this when + validating a wheel (``TVM_WHEEL_EXPECT_LLVM=1``); skip otherwise so source + builds with LLVM off do not fail.""" + if os.environ.get("TVM_WHEEL_EXPECT_LLVM") != "1": + pytest.skip("LLVM enablement only asserted during wheel validation") assert tvm.runtime.enabled("llvm"), "wheel was not built with LLVM enabled"