pypa / cibuildwheel

🎡 Build Python wheels for all the platforms with minimal configuration.
https://cibuildwheel.pypa.io
Other
1.86k stars 237 forks source link

Requesting better error message for `Build failed because a pure Python wheel was generated.` #2038

Closed jamesbraza closed 6 days ago

jamesbraza commented 2 weeks ago

Description

I am trying to test usage of cibuildwheel==2.21.2 on my Mac (macOS Sonoma v14.5) locally, and am following https://cibuildwheel.pypa.io/en/stable/setup/#local

export CIBW_BEFORE_ALL='uname -a'
cibuildwheel --debug-traceback

It successfully makes the wheelhouse directory and builds, but then outputs:

Error:
Build failed because a pure Python wheel was generated.

If you intend to build a pure-Python wheel, you don't need cibuildwheel - use
`pip wheel -w DEST_DIR .` instead.

If you expected a platform wheel, check your project configuration, or run
cibuildwheel with CIBW_BUILD_VERBOSITY=1 to view build logs.

Traceback (most recent call last):
  File "/path/to/.venv/lib/python3.12/site-packages/cibuildwheel/__main__.py", line 49, in main
    main_inner(global_options)
  File "/path/to/.venv/lib/python3.12/site-packages/cibuildwheel/__main__.py", line 184, in main_inner
    build_in_directory(args)
  File "/path/to/.venv/lib/python3.12/site-packages/cibuildwheel/__main__.py", line 351, in build_in_directory
    platform_module.build(options, tmp_path)
  File "/path/to/.venv/lib/python3.12/site-packages/cibuildwheel/macos.py", line 527, in build
    raise errors.NonPlatformWheelError()
cibuildwheel.errors.NonPlatformWheelError:
Build failed because a pure Python wheel was generated.

I see this error was added as part of https://github.com/pypa/cibuildwheel/issues/255. I have figured out this validation was added because one should use build --wheel.

For me, I am actually just trying to test out cibuildwheel locally on my Mac, and I actually can't figure out how to use it 😓

So this issue is halfway a request halfway a question:

Build log

No response

CI config

No response

henryiii commented 2 weeks ago

If you are building Pure Python wheels, you can use pipx run build, uv build, pip wheel ., or some other tools can build as well. The wheel is just some Python files, so it's not a "Mac" wheel, just a general Python one.

If you want to test cibuildwheel, you need some compiled code in your wheel. See https://learn.scientific-python.org/development/guides/packaging-compiled/ for some help getting started adding compiled code to a project. That also has guides on making both pure and compiled wheels in CI.

Better docs is a good idea, though.

jamesbraza commented 2 weeks ago

Oh I see, so I fundamentally misunderstood cibuildwheel's use case because I have no compiled code in my package. So I can just use a "pure" wheel.

I guess then the error message could say:

Build failed because a pure Python wheel was generated, without compiled code cibuildwheel is unnecessary.

Feel free to leave this open to expand this error message, or close this out

henryiii commented 2 weeks ago

I think that would be a good snippet to add (without compiled code cibuildwheel is unnecessary).

FWIW, if you are using GHA, hynek/build-and-inspect-python-package@v2 is great. See how we build and release cibuildwheel itself, for example: https://github.com/pypa/cibuildwheel/blob/main/.github/workflows/release.yml

jamesbraza commented 2 weeks ago

I started using https://github.com/henryiii/check-sdist in pre-commit last night, and have this as my Publish CI:

  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: curl -LsSf https://astral.sh/uv/install.sh | sh
      - run: uv sync
      - run: |-
          uv build --sdist --wheel --out-dir dist/ .
          uv publish
        env:
          UV_PUBLISH_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}

Seeing this, would you advise to go from check-sdist, uv build, and uv publish to just hynek/build-and-inspect-python-package@v2? It seems like a nice upgrade to me

henryiii commented 2 weeks ago

You can still run check-sdist. That doesn't even need to be in your publish pipeline, it's a check.

There's an official setup-uv action, which also does some caching.

I think currently uv publish is a bit behind the pypa action when it comes to trusted publishers, though I could be wrong, I think they are working on it. Ah, I think it's supported, interesting! They don't support attestations yet, though. (Though, to be fair, PyPI doesn't upload them yet, just checks to make sure they are valid during the upload).

I'd still use the build-and-inspect step, as it does some checks, and it also uses uv internally, so it's fast.

I'd recommend the two-stage structure you see there, for security reasons having as little happen in the publish job is nice.

Trusted publishing is recommended over using a token.

jamesbraza commented 1 week ago

Hi @henryiii thanks for all the advice, I am in the midst of rolling out hynek/build-and-inspect-python-package@v2 across our code base. I realized pairing hynek/build-and-inspect-python-package@v2 with pypa/gh-action-pypi-publish@release/v1, one doesn't even need astral-sh/setup-uv. Thanks for sharing about trusted publishing, I will look into it.