diff --git a/.github/workflows/build-vesin-torch.yml b/.github/workflows/build-vesin-torch.yml new file mode 100644 index 000000000000..609836abf7ab --- /dev/null +++ b/.github/workflows/build-vesin-torch.yml @@ -0,0 +1,142 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on the `build-torch-wheels` job of +# https://github.com/Luthaf/vesin/blob/v0.6.1/.github/workflows/build-wheels.yml +name: Build vesin-torch wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/vesin-torch.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-vesin-torch.yml' + - 'docs/packages/vesin-torch.yaml' + push: + branches: [main] + paths: + - '.github/workflows/build-vesin-torch.yml' + - 'docs/packages/vesin-torch.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + GPULITE_COMMIT: 6c221167aeca7e113ea6f27e9a2e12391bdb189a # mts-v1.3.0, pinned in vesin/CMakeLists.txt + # Our registry only has the torch release the ladybug/torchaudio ports already built. + TORCH_VERSION: '2.13' + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: vesin-torch + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + name: Build vesin-torch ${{ matrix.version }} py3-none-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 90 + + env: + VESIN_TORCH_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout vesin v${{ env.VESIN_TORCH_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: Luthaf/vesin + ref: v${{ env.VESIN_TORCH_VERSION }} + persist-credentials: false + + # setup.py's `universal_wheel` forces py3-none, so one build serves every + # interpreter. The wheel statically links gpulite (fetched by CMake) and + # dynamically links torch; none of their licences reach + # python/vesin_torch's pyproject.toml glob root, so upstream ships none. + - name: Stage the vesin and gpulite licences + run: | + cp LICENSE python/vesin_torch/LICENSE + curl -fsSL --retry 5 "https://raw.githubusercontent.com/metatensor/gpu-lite/${{ env.GPULITE_COMMIT }}/LICENSE" -o python/vesin_torch/LICENSE.gpulite + + - uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + package-dir: python/vesin_torch + output-dir: wheelhouse/ + only: cp312-manylinux_riscv64 + env: + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + CIBW_BUILD_FRONTEND: build + # The build backend (python/vesin_torch/build-backend/backend.py) adds + # cmake + torch==.* as dynamic + # build-time requirements, resolved from our registry like upstream + # resolves them from download.pytorch.org. + VESIN_TORCH_BUILD_WITH_TORCH_VERSION: ${{ env.TORCH_VERSION }} + CIBW_ENVIRONMENT: >- + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + PIP_ONLY_BINARY=cmake,torch,numpy + VESIN_TORCH_BUILD_WITH_TORCH_VERSION=${{ env.TORCH_VERSION }}.* + # vesin_torch links libtorch/libc10 (provided by the torch wheel at + # runtime, loaded RTLD_GLOBAL before vesin_torch is), same as our + # torchaudio port; excluding them keeps auditwheel from vendoring them. + CIBW_REPAIR_WHEEL_COMMAND_LINUX: >- + auditwheel repair -w {dest_dir} {wheel} + --exclude libtorch.so + --exclude libtorch_cpu.so + --exclude libtorch_python.so + --exclude libtorch_global_deps.so + --exclude libc10.so + --exclude libgomp.so.1 + # numpy is not a vesin-torch test dependency, but without it `import + # torch` warns "Failed to initialize NumPy", which the tests' + # `filterwarnings = ["error"]` turns into a collection error. + # Upstream gets numpy transitively through ase (tox optional_deps). + CIBW_TEST_REQUIRES: pytest numpy torch==${{ env.TORCH_VERSION }}.* + # {project} is the checkout root, not package-dir, since + # python/vesin_torch's CMakeLists.txt needs the sibling top-level + # vesin/ and vesin-torch/ (C++ library) directories. + # test_metatomic.py needs metatensor-torch/metatomic-torch, neither + # of which this registry carries; deselect it rather than the whole file. + CIBW_TEST_COMMAND: >- + python -c "import importlib.metadata as md; + assert {p.name for p in md.files('vesin_torch') if 'licenses' in str(p)} == {'LICENSE', 'LICENSE.gpulite'}" && + python {project}/scripts/pytest-dont-rewrite-torch.py && + pytest {project}/python/vesin_torch/tests --ignore={project}/python/vesin_torch/tests/test_metatomic.py + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: vesin-torch-${{ env.VESIN_TORCH_VERSION }}-py3-none-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish vesin-torch ${{ matrix.version }} + needs: [setup, build_wheels] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + secrets: + app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} + with: + artifact-pattern: vesin-torch-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/docs/packages/vesin-torch.yaml b/docs/packages/vesin-torch.yaml new file mode 100644 index 000000000000..45ef45cddd4b --- /dev/null +++ b/docs/packages/vesin-torch.yaml @@ -0,0 +1,5 @@ +package-name: vesin-torch +source-code: https://github.com/Luthaf/vesin/ +license: BSD-3-Clause +versions: +- version: 0.6.1