Add support for building Python wheels for Linux & MacOS#1103
Add support for building Python wheels for Linux & MacOS#1103
Conversation
.github/workflows/wheels.yaml
Outdated
| CIBW_BUILD: cp310-macosx_{x86_64,arm64} cp310-manylinux_x86_64 | ||
| # NOTE: Many combinations of OS, arch, and Python version can be built | ||
| # depending on your patience. For example: | ||
| # CIBW_BUILD: cp3{10,11,12}-macosx_{x86_64,arm64} cp3{9,10,11,12}-manylinux_x86_64 |
There was a problem hiding this comment.
Which combinations should we build for in CI? It's only a matter of patience and not exceeding Github's CI job timeout.
Maybe:
- Linux cp3{10,11,12} to support Ubuntu 22.04+
- Mac OS cp12 to match the latest Python version in Brew
There was a problem hiding this comment.
Maybe also Linux cp39? Some Noetic environments still use Python 3.9 iirc.
There was a problem hiding this comment.
In particular, I know that the RoboStack conda channel (https://robostack.github.io/index.html) uses 3.9 for Noetic.
There was a problem hiding this comment.
cp38 and I believe ISAAC Sim is tied to cp37 may be worthwhile targets... but that may be pushing the amount of time we have on the CI job.
There was a problem hiding this comment.
cp37-cp312 might be possible. I think the default Github CI limit is 6hrs. I'll hold off until we're done with reviews and then test it out in CI to avoid making the builds take forever during the review process.
There was a problem hiding this comment.
Given #1103 (review), is now the time to test the wider range of Python versions?
There was a problem hiding this comment.
Yep, I enabled for: cp3{10,11,12}-macosx_{x86_64,arm64} cp3{7,8,9,10,11,12}-manylinux_x86_64. Seems to only take about 2hrs on CI, so plenty of time to spare.
|
|
||
| set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") | ||
| set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") | ||
|
|
There was a problem hiding this comment.
This might break some existing expectations, but it also makes it easier for the setup.py script to find the resulting binaries.
Perhaps to allow setup.py to override these, they could be wrapped in if(NOT DEFINED ...) checks?
There was a problem hiding this comment.
Also want to make sure this doesn't break / interfere with #1101
|
|
||
| if sys.platform.startswith("darwin"): | ||
| # TODO: Move these out to configuration | ||
| cmake_args += ["-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@16/bin/clang++"] |
There was a problem hiding this comment.
I don't have a Mac machine to test changing this, but this path probably shouldn't be hardcoded. Maybe someone can experiment with setting this via an environmental variable in before_build.sh? Maybe brew provides a method for identifying this path?
There was a problem hiding this comment.
I have a Mac to test against, I'll see what needs to be changed here.
| if sys.platform.startswith("darwin"): | ||
| # TODO: Move these out to configuration | ||
| cmake_args += ["-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@16/bin/clang++"] | ||
| cmake_args += ["-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0"] |
There was a problem hiding this comment.
Not sure how to correctly set this value.
There was a problem hiding this comment.
This is typically set to the lowest supported OS version. The host OS needs to have the SDK for that version. Do you need to set this at all?
There was a problem hiding this comment.
Without it I was seeing lots of dylib was built for newer macOS version than being linked warnings on the macos-13 Github runner. Maybe it's OK to leave it as-is until someone has a chance to verify that it does indeed build with a lower version.
| @@ -1,2 +1 @@ | |||
| from ompl import util | |||
There was a problem hiding this comment.
This change "avoids" the major issue on Mac I mention in the PR description, but doesn't solve it if the user imports ompl.util or other packages themselves.
I didn't notice any negative side effects from removing this.
|
Thanks very much for this! I want to tag kylc/ompl-wheels#1 here - I think the critical issue is not only an issue for macOS. |
|
Thanks a ton for making a PR for this! I would like to make sure #1100 gets merged first as I believe it fixes some of the issues for MacOS and modern Linux systems. |
|
Thanks for testing it out @wbthomason, apologies for not noticing your post earlier. It seems like there is some odd behavior depending on the ordering of imports. For example, if I Removing the import change here seems to resolve the issue for me, but I thought it was causing some issues on MacOS relating to py-converters already being registered. For now I've reverted this change and I guess we'll see. If you want to test updated wheels then you can find them on my OMPL fork after CI finishes running: https://github.com/kylc/ompl/tree/build-wheels Regarding the libboost shared library issue, can you provide some more details about your Linux setup? Did you build the wheels locally or install from the CI job? It seems odd that it's looking for 1.78 since we build a much more recent version and link to that in the CI job. Maybe you can unzip the whl you installed and see which libboost shared libraries are bundled in there? For example, if I unzip the latest build, I see that |
|
I unfortunately deleted the actual
I'll try re-installing and (assuming the issue repros) unzipping/checking with |
|
I did a bit more digging here - I found the original So, there's still a bug with the library loading, but I don't think it's related to this PR - at the least, I definitely don't think that it should block this. I can still reproduce the original |
52914ec to
cef11bf
Compare
|
That's good to hear @wbthomason. Still odd that Python doesn't somehow give priority to shared libs distributed in the wheel over an old one on the system path somewhere. The |
|
Before finishing this PR, I'd like to get these issues with building on Ubuntu 20/22 fixed, will require a modest reversion of some of the CMake logic to pull in the old versions of libraries: It would also be nice to get the PR which fixes compilation for modern builds/Apple M-series chips in as well: #1100, but that can wait until after. |
cef11bf to
4dc9fa7
Compare
|
Sorry about the kerfuffle, didn't realize this was set to use the M1 branch as base - that's merged now after some additional testing. |
|
@kylc @wbthomason @mamoll are there any outstanding comments on this pull? If not, let's rebase and merge in. |
7e21cc7 to
33d1e0f
Compare
|
The build is currently broken on
I just pushed up a few changes to only upload wheels for builds on the main branch, fix some issues with the Brew steps on MacOS, and specify pygccxml==2.2.1. |
|
Great! I rebased and enabled builds for all the Python versions we discussed in the comments above. Ship it! |
|
All of them seem to fail since about a month, do you have any idea why? |
|
Hey @simonschmeisser. I've noticed that and have a fix sitting on my fork at https://github.com/kylc/ompl, but haven't had time to open a PR. I'll get around to it this weekend I think. |
* Modify native build for better MacOS support. * Add wheel generation scripts and CI jobs. * Don't remove ompl.util import from ompl.base. * Don't delete tag every time. * Only tag prerelease if on main branch. * Don't auto-update brew. * Specify pygccxml==2.2.1. * Build all the Python versions!
* Modify native build for better MacOS support. * Add wheel generation scripts and CI jobs. * Don't remove ompl.util import from ompl.base. * Don't delete tag every time. * Only tag prerelease if on main branch. * Don't auto-update brew. * Specify pygccxml==2.2.1. * Build all the Python versions!
This PR adds support for building Python wheels for the OMPL package, along with Github CI workflows to do so automatically. The result is that users can install the OMPL Python bindings, with precompiled OMPL shared libraries and all dependencies, like this:
pip install https://github.com/ompl/ompl/releases/download/prerelease/ompl-1.6.0-cp310-cp310-manylinux_2_28_x86_64.whlAlong with just about any CPython version from the cibuildwheel table, supported build targets are:
manylinux_2_28_x86_64)x86_64andarm64)This is done using the cibuildwheel package to automate building for various operating systems, CPU architectures, and Python versions. On Linux, the official manylinux Docker images are used to ensure glibc backwards compatibility in accordance with standard PyPA packaging rules.
Usage
Users can build wheels locally by installing
cibuildwheeland invoking it from theompl/root directory like this:Correct format of the
CIBW_BUILDvariable can be found in the cibuildwheel docs. If cross-compiling on MacOS, you must also setOMPL_BUILD_ARCHto the target architecture, e.g.arm64.Note that
cibuildwheelwill make changes to your local system on MacOS. On Linux it uses Docker to containerize the build, but on MacOS the commands are performed on the host system. Be careful!Changes
NOTE: I don't have access to a MacOS development machine, so it's entirely possible that some of the Mac-specific changes below aren't required. Additional testing on that platform would be appreciated.
py-bindings/setup.pyis modified to invoke CMake and build the OMPL shared libraries. This allows thecibuildwheeltool (or users) topip install .to build locally..githubto automatically run wheel build jobs on new commits.CMakeLists.txtchanges:setup.pyto find the resulting shared libraries${PYTHON_LIBRARIES}in accordance with PEP513 recommendations; it will be loaded at runtime anyway.-undefined suppress -flat_namespaceto prevent the linker complaints about missing Python symbols (due to the above)._LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION=1to bring back some deprecated stdlib types which are removed in recent XCode versions (see Xcode 15 Release Notes).Known Issues
CRITICAL: On MacOS, there seems to be some issue with multiple definitions of the same symbol. This can be observed by importing multiple OMPL namespaces and watching for a warning to the effect, e.g.
import ompl.base; import ompl.util. These symbols aren't compatible with each other even though it is plain to see that they refer to the same thing. This breaks some Python code with cryptic errors like "expected argument LogLevel, got LogLevel".RuntimeWarning: to-Python converter for ompl::msg::LogLevel already registered; second conversion method ignored.Future work
pip install ompl(or similar).universal2wheels for MacOS, which bundle both x86_64 and arm64 compatible binaries into a single wheel.