I am trying to force a Python3 non-universal wheel I'm building to be a platform wheel, despite not having any native build steps that happen during the distribution-packaging process.
The wheel will include an OS-specific shared library, but that library is built and copied into my package directory by a larger build system that my package knows nothing about. By the time my Python3 package is ready to be built into a wheel, my build system has already built the native shared library and copied it into the package directory.
This SO post details a solution that works for the now-deprecated setup.py approach, but I'm unsure how to accomplish the same result using the new and now-standard build / pyproject.toml system:
mypackage/
mypackage.py # Uses platform.system and importlib to load the local OS-specific library
pyproject.toml
mysharedlib.so # Or .dylib on macOS, or .dll on Windows
Based on the host OS performing the build, I would like the resulting wheel to be manylinux, macos, or windows.
I build with python3 -m build --wheel, and that always emits mypackage-0.1-py3-none-any.whl.
What do I have to change to force the build to emit a platform wheel?
Update 2 Sept 2023:
-C=--build-option=--plat {your-platform-tag}no longer works, so I added my preferred replacement to the end of the list.==========
OK, after some research and reading of code, I can present a bit of information and a few solutions that might meet other people's needs, summarized here:
Firstly,
pyproject.tomlis not mutually exclusive fromsetup.py.setuptoolswill complain about deprecation if you create a distribution package viapython3 setup.py ...and nopyproject.tomlfile is present.However,
setup.pyis still around and available, but it's a mistake to duplicate project configuration values (name,version, etc). So, put as much as your package will allow inside yourpyproject.tomlfile, and usesetup.pyfor things like overriding theDistributionclass, or overriding thebdist_wheelmodule, etc.As far as creating platform wheels, there are a few approaches that work, with pros and cons:
bdist_wheelcommand class insetup.pyas described here and setself.root_is_pureto False in thefinalize_optionsoverride. This forces the python tag (e.g.cp39) to be set, along with the platform tag.Distributionclass insetup.pyas described here and overridehas_ext_modules()to simply return True. This also forces the python and platform tags to be set.-C=--build-option=--plat {your-platform-tag}to the build invocation (for my case that'spython -m build -w -n, for example). This leaves the Python tag untouched but you have to supply your own tag; there's no way to say "use whatever the native platform is". You can discover the exact platform tag with the commandwheel.bdist_wheel.get_platform(pathlib.Path('.'))after importing thepathlibandwheel.bdist_wheelpackages, but that can be cumbersome becausewheelisn't a standard library package.mypkg-py3-none-any.whltomypkg-py3-none-macosx_13_0_x86_64.whl- it appears that the platform tag is only encoded into the filename, and not any of the package metadata that's generated during the distribution-package process.wheelpackage utility to update the tags, to turn the pure wheel into a platform wheel.python -m wheel tags --platform-tag macosx_13_0_x86_64 mypkg-py3-none-any.whlwill emit a new platform wheel with the tags you want.In the end I chose the final options because it required the least amount of work- no
setup.pyfiles need to be introduced solely to accomplish this, and the build logs make it clear that a platform wheel (not a pure wheel) is being created.