Skip to content

Add riscv64 build, make Linux wheel build matrix more explicit - #288

Merged
hudson-ai merged 3 commits into
guidance-ai:mainfrom
threexc:tgamblin/riscv64
Feb 23, 2026
Merged

Add riscv64 build, make Linux wheel build matrix more explicit#288
hudson-ai merged 3 commits into
guidance-ai:mainfrom
threexc:tgamblin/riscv64

Conversation

@threexc

@threexc threexc commented Feb 19, 2026

Copy link
Copy Markdown
Contributor

maturin supports riscv64 cross build, but the arch string and the target toolchain for rustc don't exactly match up (this is also the case for other architectures like ppc64le and x86). To make the riscv64 addition consistent with the others, change the platform list so that arch and target are distinct fields.

Note that this is being done on behalf of the RISE Project to improve Python ecosystem support on riscv64 platforms.

@hudson-ai

Copy link
Copy Markdown
Contributor

Hey @threexc thank you for the contribution! General approach looks good -- would you mind merging or rebasing on the new changes in main?

@threexc

threexc commented Feb 20, 2026

Copy link
Copy Markdown
Contributor Author

Hey @threexc thank you for the contribution! General approach looks good -- would you mind merging or rebasing on the new changes in main?

Should be OK now. Please let me know if there are any other issues.

@hudson-ai

Copy link
Copy Markdown
Contributor

Ran the workflow on my fork and hit some issues.

error: unable to find or provide libc for target 'riscv64-linux.4.19...6.5.7-gnu.2.17'
info: zig can provide libc for related target riscv64-linux-gnu
info: zig can provide libc for related target riscv64-linux-musl

I was thinking that we can just skip --zig for riscv64, e.g. by adding a boolean field to each matrix entry:

platform:
  - runner: ubuntu-latest
    target: x86_64-unknown-linux-gnu
    arch: x86_64
    zig: true
  - runner: ubuntu-latest
    target: riscv64gc-unknown-linux-gnu
    arch: riscv64
    zig: false

and updating the args line:

args: --release --out dist ${{ matrix.python-version != '3.14t' && matrix.platform.zig && '--zig' || '' }}

I tried this out, but I ran into another issue

💥 maturin failed
  Caused by: Error ensuring manylinux_2_17 compliance
  Caused by: Your library is not manylinux_2_17 (aka manylinux2014) compliant because it has unsupported architecture: riscv64

Might have to make a different choice than manylinux: auto for maturin?

@threexc

threexc commented Feb 22, 2026

Copy link
Copy Markdown
Contributor Author

Ran the workflow on my fork and hit some issues.

error: unable to find or provide libc for target 'riscv64-linux.4.19...6.5.7-gnu.2.17'
info: zig can provide libc for related target riscv64-linux-gnu
info: zig can provide libc for related target riscv64-linux-musl

I was thinking that we can just skip --zig for riscv64, e.g. by adding a boolean field to each matrix entry:

platform:
  - runner: ubuntu-latest
    target: x86_64-unknown-linux-gnu
    arch: x86_64
    zig: true
  - runner: ubuntu-latest
    target: riscv64gc-unknown-linux-gnu
    arch: riscv64
    zig: false

and updating the args line:

args: --release --out dist ${{ matrix.python-version != '3.14t' && matrix.platform.zig && '--zig' || '' }}

I tried this out, but I ran into another issue

💥 maturin failed
  Caused by: Error ensuring manylinux_2_17 compliance
  Caused by: Your library is not manylinux_2_17 (aka manylinux2014) compliant because it has unsupported architecture: riscv64

Might have to make a different choice than manylinux: auto for maturin?

Thanks for catching that. I've modified the patch to set manylinux: 2_39 for riscv64.

Make the Linux matrix more explicit by distinguishing between the
'target' and the 'arch', which are not always the same. This pattern is
better suited to architectures where they don't match.

Also explicitly set a boolean flag for 'zig', since not all
architectures may support it.

Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
Skip zig to avoid this error:

|error: unable to find or provide libc for target 'riscv64-linux.4.19...6.5.7-gnu.2.17'
|info: zig can provide libc for related target riscv64-linux-gnu
|info: zig can provide libc for related target riscv64-linux-musl

Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
@threexc

threexc commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

@hudson-ai I think I misread your reply the first time around. I've fixed things up now. Notably, I've added manylinux: 2_39 since that's the version supporting riscv64. The docs seem unclear about whether this works for all architectures though, so if that's the case I'll be explicit about it for each architecture.

Testing here: threexc#2

Comment thread .github/workflows/wheels.yml
@hudson-ai

Copy link
Copy Markdown
Contributor

@threexc it's still not working due to some linker issues. Please see the workflow run here:
https://github.com/hudson-ai/llguidance/actions/runs/22317382312/job/64566147286

@hudson-ai

Copy link
Copy Markdown
Contributor

Annoyingly, it's not trivial to run the right workflow from a fork; you may have to add a workflow-dispatch trigger (please remove before we actually merge...) and possibly even run it from the command-line, like gh workflow run wheels.yml --ref tgamblin/riscv64-test -R threexc/llguidance

@hudson-ai

hudson-ai commented Feb 23, 2026

Copy link
Copy Markdown
Contributor

@threexc I got it working with the following configuration.

Note the before-script that explicitly installs and sets the linker. I also made the matrix a lot more explicit.

  linux:
    runs-on: ${{ matrix.platform.runner }}
    needs: [sdist]
    strategy:
      matrix:
        platform:
          - runner: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            arch: x86_64
            zig: true
            manylinux: auto
          - runner: ubuntu-latest
            target: i686-unknown-linux-gnu
            arch: x86
            zig: true
            manylinux: auto
          - runner: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            arch: aarch64
            zig: true
            manylinux: auto
          - runner: ubuntu-latest
            target: riscv64gc-unknown-linux-gnu
            arch: riscv64
            zig: false
            manylinux: 2_39
            before-script: 'sudo apt-get install -y gcc-riscv64-linux-gnu && mkdir -p ~/.cargo && printf "[target.riscv64gc-unknown-linux-gnu]\nlinker = \"riscv64-linux-gnu-gcc\"\n" >> ~/.cargo/config.toml'
        python:
          - version: '3.12'
            zig: true
          - version: '3.14t'
            zig: false
        exclude:
          - platform:
              arch: riscv64
            python:
              version: '3.14t'
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python.version }}
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist ${{ matrix.python.zig && matrix.platform.zig && '--zig' || '' }}
          sccache: 'true'
          manylinux: ${{ matrix.platform.manylinux }}
          before-script-linux: ${{ matrix.platform.before-script || '' }}
      - name: Upload wheels
        uses: actions/upload-artifact@v6
        with:
          name: wheels-linux-${{ matrix.platform.arch }}-${{ matrix.python.version }}
          path: dist

@hudson-ai

Copy link
Copy Markdown
Contributor

Note that I excluded the (3.14t, riscv64) pair, which failed seemingly due to some PyO3 weirdness: https://github.com/hudson-ai/llguidance/actions/runs/22318409028/job/64569802785

@ngoldbaum maybe you know what's going on here and can chime in?

@riedgar-ms

Copy link
Copy Markdown
Contributor

My concern with this is that we don't actually have RISC-V runners to validate on. If we merge, we should make it very clear that this arch is provided as-is.

@ngoldbaum

Copy link
Copy Markdown
Contributor
> 📦 Wheel is eligible for a higher priority tag. You requested manylinux_2_39 but this wheel is eligible for manylinux_2_34
📦 Built wheel for abi3 Python ≥ 3.9 to dist/llguidance-1.5.1-cp39-abi3-manylinux_2_39_riscv64.whl
⚠️ Warning: CPython 3.14t at /opt/hostedtoolcache/Python/3.14.3/x64-freethreaded/bin/python3.14 does not yet support abi3 so the build artifacts will be version-specific.

Looks like a maturin bug, you shouldn't be getting an abi3 wheel. I opened PyO3/maturin#3034.

@hudson-ai

Copy link
Copy Markdown
Contributor

Looks like a maturin bug, you shouldn't be getting an abi3 wheel. I opened PyO3/maturin#3034.

Got it. Thanks a bunch!

@threexc

threexc commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

@threexc I got it working with the following configuration.

Note the before-script that explicitly installs and sets the linker. I also made the matrix a lot more explicit.

  linux:
    runs-on: ${{ matrix.platform.runner }}
    needs: [sdist]
    strategy:
      matrix:
        platform:
          - runner: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            arch: x86_64
            zig: true
            manylinux: auto
          - runner: ubuntu-latest
            target: i686-unknown-linux-gnu
            arch: x86
            zig: true
            manylinux: auto
          - runner: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            arch: aarch64
            zig: true
            manylinux: auto
          - runner: ubuntu-latest
            target: riscv64gc-unknown-linux-gnu
            arch: riscv64
            zig: false
            manylinux: 2_39
            before-script: 'sudo apt-get install -y gcc-riscv64-linux-gnu && mkdir -p ~/.cargo && printf "[target.riscv64gc-unknown-linux-gnu]\nlinker = \"riscv64-linux-gnu-gcc\"\n" >> ~/.cargo/config.toml'
        python:
          - version: '3.12'
            zig: true
          - version: '3.14t'
            zig: false
        exclude:
          - platform:
              arch: riscv64
            python:
              version: '3.14t'
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python.version }}
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist ${{ matrix.python.zig && matrix.platform.zig && '--zig' || '' }}
          sccache: 'true'
          manylinux: ${{ matrix.platform.manylinux }}
          before-script-linux: ${{ matrix.platform.before-script || '' }}
      - name: Upload wheels
        uses: actions/upload-artifact@v6
        with:
          name: wheels-linux-${{ matrix.platform.arch }}-${{ matrix.python.version }}
          path: dist

Thank you! I hadn't gotten around to trying your suggestions yet. Do you want to make an extra commit to fix and squash the changes, or do you want me to submit that?

@hudson-ai

Copy link
Copy Markdown
Contributor

@threexc I'm happy to push a commit and squash. Sorry if I stepped on your toes here. Just eager to merge in before doing a release :)

@hudson-ai

Copy link
Copy Markdown
Contributor

Workflow is green: https://github.com/hudson-ai/llguidance/actions/runs/22322576909

@riedgar-ms you ok with me merging if I note the untested riscv support in the changelog upon the next release?

@riedgar-ms riedgar-ms left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK with the 'untested' note

@hudson-ai
hudson-ai merged commit 5b9b77b into guidance-ai:main Feb 23, 2026
5 checks passed
@threexc

threexc commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

@hudson-ai no problem! I'm just happy to see RISC-V support :)

Thank you everyone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants