From c24c9fb47b36e7c5e396b153b1cc23f5b782dae5 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 14 Oct 2026 05:53:20 +0000 Subject: [PATCH 1/3] torchmonarch: Add version 0.7.0 Build Meta's Monarch (setuptools-rust PyO3 extension over an ~850-crate Rust workspace, plus two libtorch C++ extensions) with its CPU-only tensor engine against the registry's torch 2.14.0, mirroring upstream's release builder and its macOS CPU leg. The dashboard frontend is bundled on an x86 runner, as upstream's ci.yml does, since node.js has no riscv64 release. --- .github/workflows/build-torchmonarch.yml | 193 +++++++++++++++++++++++ docs/packages/torchmonarch.yaml | 5 + 2 files changed, 198 insertions(+) create mode 100644 .github/workflows/build-torchmonarch.yml create mode 100644 docs/packages/torchmonarch.yaml diff --git a/.github/workflows/build-torchmonarch.yml b/.github/workflows/build-torchmonarch.yml new file mode 100644 index 000000000000..34b45e409570 --- /dev/null +++ b/.github/workflows/build-torchmonarch.yml @@ -0,0 +1,193 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Based on upstream's release builder and its CPU (macOS) leg: +# https://github.com/meta-pytorch/monarch/blob/v0.7.0/.github/workflows/publish_release.yml +# https://github.com/meta-pytorch/monarch/blob/v0.7.0/.github/workflows/build-dist.yml +# https://github.com/meta-pytorch/monarch/blob/v0.7.0/.github/workflows/build-macos.yml +# and the dashboard build of +# https://github.com/meta-pytorch/monarch/blob/v0.7.0/.github/workflows/ci.yml +name: Build torchmonarch wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/torchmonarch.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-torchmonarch.yml' + - 'docs/packages/torchmonarch.yaml' + push: + branches: [main] + paths: + - '.github/workflows/build-torchmonarch.yml' + - 'docs/packages/torchmonarch.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 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: torchmonarch + version: ${{ inputs.version }} + + build_frontend: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build torchmonarch ${{ matrix.version }} dashboard frontend + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + + env: + TORCHMONARCH_VERSION: ${{ matrix.version }} + + steps: + # The dashboard is an esbuild bundle: arch-independent output, and node.js has no riscv64 release. + - name: Checkout monarch v${{ env.TORCHMONARCH_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: meta-pytorch/monarch + ref: v${{ env.TORCHMONARCH_VERSION }} + persist-credentials: false + + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: '20' + + # The CSS move and index.html copy are what setup.py's build_frontend adds after + # `npm run build`; with build/index.html present it skips npm inside the container. + - name: Install and build dashboard frontend + working-directory: python/monarch/monarch_dashboard/frontend + run: | + npm ci + mkdir -p build/static/css + npm run build + mv build/static/js/main.css build/static/css/main.css + cp public/index.html build/index.html + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: torchmonarch-${{ env.TORCHMONARCH_VERSION }}-dashboard + path: python/monarch/monarch_dashboard/frontend/build + if-no-files-found: error + + build_wheels: + needs: [setup, build_frontend] + if: needs.setup.outputs.versions != '[]' + name: Build torchmonarch ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 1440 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + # Upstream ships no free-threaded build. + python: ["cp312", "cp313", "cp314"] + + env: + TORCHMONARCH_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout monarch v${{ env.TORCHMONARCH_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: meta-pytorch/monarch + ref: v${{ env.TORCHMONARCH_VERSION }} + submodules: recursive + persist-credentials: false + + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: torchmonarch-${{ env.TORCHMONARCH_VERSION }}-dashboard + path: python/monarch/monarch_dashboard/frontend/build + + # Same OOM guard build-deltalake.yml/build-daft.yml need on these runners for a + # comparably sized (~850-crate) Rust workspace. + - name: Set swap space + uses: pierotofy/set-swap-space@fc79b3f67fa8a838184ce84a674ca12238d2c761 # master + with: + swap-size-gb: 16 + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + output-dir: wheelhouse/ + only: ${{ matrix.python }}-manylinux_riscv64 + env: + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # protoc is for the tracing-perfetto-sdk-schema crate; upstream's clang-devel and + # libunwind only serve the CUDA/RDMA crates, which a CPU build does not compile. + CIBW_BEFORE_ALL_LINUX: >- + dnf install -y protobuf-compiler && + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none && + $HOME/.cargo/bin/rustup toolchain install --profile minimal + "$(sed -n 's/^channel = "\(.*\)"$/\1/p' rust-toolchain)" + # Upstream builds with `python -m build --wheel --no-isolation` against a preinstalled + # torch; ours is the newest riscv64 torch on the registry. + CIBW_BUILD_FRONTEND: "build; args: --no-isolation" + CIBW_BEFORE_BUILD: pip install torch==2.14.0 -r build-requirements.txt + # CARGO_BUILD_JOBS=2 keeps the link of the ~280 MB extension within runner memory. + CIBW_ENVIRONMENT_LINUX: >- + PATH="$PATH:$HOME/.cargo/bin" + MONARCH_VERSION=${{ env.TORCHMONARCH_VERSION }} + CARGO_BUILD_JOBS=2 + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + PIP_ONLY_BINARY=torch,numpy + # monarch.common._C and monarch.gradient._gradient_generator link libtorch, which the + # torch wheel provides at runtime; upstream's wheels do not vendor it either. + CIBW_REPAIR_WHEEL_COMMAND_LINUX: >- + auditwheel repair -w {dest_dir} {wheel} + --exclude libtorch.so + --exclude libtorch_cpu.so + --exclude libtorch_python.so + --exclude libc10.so + CIBW_TEST_REQUIRES: torch==2.14.0 pytest pytest-timeout pytest-asyncio + CIBW_TEST_SOURCES: python/tests pyproject.toml + # Upstream's wheel check (`import monarch`), plus its own CPU-runnable tests for + # the extension linkage, the C++ gradient generator, and an actor round trip. + CIBW_TEST_COMMAND: >- + python -c "import monarch" && + python -m pytest -p no:cacheprovider + python/tests/test_extension_linking.py + python/tests/test_rust_bindings_load.py + python/tests/test_grad_generator.py + python/tests/test_python_actors.py::test_stream + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: torchmonarch-${{ env.TORCHMONARCH_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish torchmonarch ${{ 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: torchmonarch-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/docs/packages/torchmonarch.yaml b/docs/packages/torchmonarch.yaml new file mode 100644 index 000000000000..e9a439c98d79 --- /dev/null +++ b/docs/packages/torchmonarch.yaml @@ -0,0 +1,5 @@ +package-name: torchmonarch +source-code: https://github.com/meta-pytorch/monarch +license: BSD-3-Clause +versions: +- version: 0.7.0 From 364394d26dffd2fb58c210e160329e7e04065ce4 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 15 Oct 2026 12:17:36 +0000 Subject: [PATCH 2/3] build-torchmonarch: install clang-devel for bindgen All three interpreters failed identically after ~3h20m of compiling, deep in the ~850-crate graph: libsqlite3-sys's build script uses bindgen, which panics with "Unable to find libclang" because clang-devel (the package providing libclang.so) is not installed. The existing comment assumed clang-devel only served the CUDA/RDMA crates a CPU build skips; libsqlite3-sys needs it too. --- .github/workflows/build-torchmonarch.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-torchmonarch.yml b/.github/workflows/build-torchmonarch.yml index 34b45e409570..caf8853e9098 100644 --- a/.github/workflows/build-torchmonarch.yml +++ b/.github/workflows/build-torchmonarch.yml @@ -131,10 +131,11 @@ jobs: only: ${{ matrix.python }}-manylinux_riscv64 env: CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} - # protoc is for the tracing-perfetto-sdk-schema crate; upstream's clang-devel and - # libunwind only serve the CUDA/RDMA crates, which a CPU build does not compile. + # protoc is for the tracing-perfetto-sdk-schema crate; clang-devel (libclang.so) is + # for bindgen, which libsqlite3-sys's build script also needs on a CPU build - not + # only the CUDA/RDMA crates upstream's own clang-devel/libunwind comment calls out. CIBW_BEFORE_ALL_LINUX: >- - dnf install -y protobuf-compiler && + dnf install -y protobuf-compiler clang-devel && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none && $HOME/.cargo/bin/rustup toolchain install --profile minimal "$(sed -n 's/^channel = "\(.*\)"$/\1/p' rust-toolchain)" From 6dc014c7084bb890c25cdea89fabc8ff2ee3aeb7 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 25 Oct 2026 18:04:04 +0000 Subject: [PATCH 3/3] build-torchmonarch: PIP_PREFER_BINARY for the test install pyarrow>=17 is a runtime dependency of the built wheel. At test-install time, pip resolves it against both pypi.org and pypi.riseproject.dev; both list 26.0.0, but only ours is a riscv64 wheel. Without a binary preference pip source-builds PyPI's sdist instead, and that needs the real Apache Arrow C++ (no FindArrow.cmake in the container), so cp313 and cp314 died in pyarrow's CMake configure. See gotcha 354. --- .github/workflows/build-torchmonarch.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-torchmonarch.yml b/.github/workflows/build-torchmonarch.yml index caf8853e9098..340e000f9413 100644 --- a/.github/workflows/build-torchmonarch.yml +++ b/.github/workflows/build-torchmonarch.yml @@ -159,6 +159,11 @@ jobs: --exclude libtorch_python.so --exclude libc10.so CIBW_TEST_REQUIRES: torch==2.14.0 pytest pytest-timeout pytest-asyncio + # torchmonarch's own `pyarrow>=17` runtime dependency resolves against both + # indexes at test-install time; without this, pip picks PyPI's sdist-only + # 26.0.0 over our riscv64 wheel of the same version and dies in pyarrow's + # CMake (no Arrow C++ in the container) - CLAUDE.md gotcha 354. + CIBW_TEST_ENVIRONMENT_LINUX: PIP_PREFER_BINARY=1 CIBW_TEST_SOURCES: python/tests pyproject.toml # Upstream's wheel check (`import monarch`), plus its own CPU-runnable tests for # the extension linkage, the C++ gradient generator, and an actor round trip.