-
Notifications
You must be signed in to change notification settings - Fork 27
fix: Working build with static library #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
This would allow shared libraries: -add_library(hellocore ${hello_sources} )
+add_library(hellocore SHARED ${hello_sources} )
target_include_directories(hellocore PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
@@ -16,9 +16,9 @@ set_property(TARGET hellocore PROPERTY POSITION_INDEPENDENT_CODE ON)
# install targets
install(TARGETS hellocore
EXPORT helloTargets
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION src/hello
+ LIBRARY DESTINATION src/hello
+ ARCHIVE DESTINATION src/hello
)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
diff --git a/projects/hello-pybind11/src/hello/CMakeLists.txt b/projects/hello-pybind11/src/hello/CMakeLists.txt
index 19379f0..690729b 100644
--- a/projects/hello-pybind11/src/hello/CMakeLists.txt
+++ b/projects/hello-pybind11/src/hello/CMakeLists.txt
@@ -9,6 +9,12 @@ pybind11_add_module(${python_module_name} MODULE
)
target_link_libraries(${python_module_name} PRIVATE hellocore)
+if (APPLE)
+ set_target_properties(${python_module_name} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE INSTALL_RPATH "@loader_path")
+else()
+ set_target_properties(${python_module_name} PROPERTIES BUILD_RPATH_USE_ORIGIN TRUE)
+endif()
+
install(TARGETS ${python_module_name} DESTINATION src/hello)Is there a way to use the This may actually be the correct way to do it, with the only other alternative being the manual loading of the libraries required in |
|
Your RPATH handling code doesn't work in Linux. Try this. if (APPLE)
set(rpath "@loader_path")
else()
set(rpath "$ORIGIN")
endif()
set_target_properties(${python_module_name} PROPERTIES INSTALL_RPATH ${rpath})I don't think the other RPATH related options are necessary. The build RPATH will be hardcoded, but we don't really care, ctest will still run, so we don't need I wonder if we need to anything to support Windows... |
|
What you provided does work, but I think there could be more radical changes. In my mind there are two possible example projects:
What was here before seems like it was trying to do option 2. You seem more fond of option 1. I'd pick one and stick to it, and we can develop the other at some point in the future. Additional, I don't think the directory structure in this example is what we want people using. A saner structure for option 1 is below, which looks a lot like the regular C version. A saner structure that I've seen for option 2. |
Thanks! I was originally running in a docker container, but when I did the shared lib testing, I was just on macOS directly.
I was mostly focused on just getting this to work, but fully agree, there are two paths, and currently we seem to be somewhere in the middle. I think option 1 is what is more "hello-world" like, and what would the the most helpful for a newcomer. Option 2 is also very useful to have, though, but more complex and tricky. Should you install CMake files, for example? I'd rather think you should, so a user could access the installed package with CMake. See PyBind11, which does not install cmake files with the package, and therefore can't be accessed from CMake from the Python install. I could duplicate the folder then do one for each? Focusing on option 1 first?
You really need to have at least one level of nesting for the python folder. While there are a few (2?) people who like flat over nested for simple projects, I don't think it's even a discussion for packages that have compiled pieces - you have to keep the package folder out of the top level. If you have it at the top level, then tools like pytest cannot be run from the top level directory reliably, since they may pick up @ktbarrett I can give you access to my fork if you'd like to help. |
I ran into this recently, it's quite annoying.
I've also run into this recent as well; you've convinced me. Certainly option 1 is the best place to start, and I'm willing to help. |
This is just a little too "extra" for what is supposed to be an example of how to use scikit-build with a pybind11 project.
This is supposed to be a Python extension module, why are we using ctest?
Unnecessary for a simple example.
thewtex
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@ktbarrett did just as much to clean it up further, if not more. :) |
|
I am too late for the review since @thewtex pinged me 3 hours ago, and I wasn't watching this repo. There are a couple of things that I think were not "too extra" to have. We disagree on what is the sweet point in complexity for an example, but it's completely fine for me if you want to simplify it, especially if you fix the bug importing the library doing so! From: baca405 From: 9059c15 About not exporting, and not installing targets... well, I thought scikit-build was mainly a But, as I said earlier, thanks for fixing this! |
|
I didn't notice the merging of init and body, I would rather have them separate since that's really how projects are supposed to be designed with PyBind11. I think the exporting and installing targets was mostly talking about adding shared/static libraries and then, if you don't expect someone to link (without Python) to your libraries in your wheel, you don't need it. I do want to have a new, separate example that has the complex parts of this done correctly (but is not broken). I think by splitting it into "simple, just shows the important parts" and "here's what a real-world-like example looks like" would be ideal. I (or @ktbarrett) could start a PR in the near future with a |
|
Not sure if the strategy to trim down a more complete example to a "simple" version, to then wait for you or @ktbarrett to start a PR in the near future with an If you don't need static libraries in your wheel, you can use this PR: Add cmake_target option on scikit-build, or a manifest introduced in this PR to exclude them. That could be introduced in the |
|
Well, my PR originally mostly fixed things, and that sat here for exactly a month. Then I merged @ktbarrett's simplifications and it got merged in a day. ;) I think an example labeled "hello" tends to imply a simple example, there needs to be a simple example, and the complex one had lots of issues, so having something correct. Also, if you are writing a binding to your own library or a header only library, you build the target yourself, so have full control over what is produced (but the two PRs above are fantastic to have!). I'll be revisiting scikit-build integration soon, after working on PyBind11's CMake. I can take the first commit, maybe add 1-2 of the non-simplification changes, rename it, and put that into a PR for the time being, then just update it later when needed, would that be more sustainable? |
|
Though, if we wait, @ktbarrett may have a better example (and I might be able to fix the missing CMake config files issue in PyBind11) |
|
@phcerdan With the simple example, the idea was that the extension module - and by extension (:rofl:) the choice of pybind11 and scikit-build for building that extension module - is an implementation detail. In that case distributing things unrelated to the use of the Python library is unfitting of such an example. This mirrors the other examples in this repo that don't "appear" as anything more than Python packages. I believe the first pybind11 example in the project should be similar to them and not a totally different project architecture. Such a project architecture is not typical either, in fact it's fairly unsupported. At least that was my train of thought. Certainly there are use cases where supporting both the C++ and the Python wrapper in the same project are advantageous, and pip/pypi can be used as an effective distribution for both Python libraries and C libraries. I am working (well eventually) on such a project. I have a mostly finalized an example project that explicitly does this. Whether I move that example into this repo (and maybe remove some bits), or fix and rename this project from the 2nd or 3rd commit, I don't particularly mind.
In what way?
That would be awesome. It also might be advantageous for CMake as distributed by SciKit to default searching the Python package installation prefix for CMake packages. Or should they go in |
|
@phcerdan I apologize for merging so quickly -- I should have provided more time for your review. 😞 @henryiii @ktbarrett hopefully you can help to keep us moving forward and address the issues @phcerdan mentioned either in improvements to this example or an advanced-pybind11. Regarding CMake configuration exports and C++ header installations; yes, there is work to be done in Python wheels and CMake discovery to make these useful. However, scikit-build + conda should also work for generating a conda package. The headers in a conda package go into their standard platform locations. CMake can then find them with standard methods for building against a project. There are also tools like conda-press that can help with the distribution of shared library dependencies. Maybe an advance-pybind11 example would help. Additionally, there is an effort to auto-generate pybind11 bindings, autopybind11. This would make another good example for a larger library.
@henryiii this sounds quite helpful all around! |
|
No worries at all @thewtex, thanks for pointing to autopybind11, looks good! |
Fixes #5
The example as it stands does not work, and even has invalid Python syntax in it. This fixes it and does minor standardization in structure. The min version is CMake 3.14, which is fine because you can get 3.17 with pip on most platforms, and the old example required at least 3.11 anyway, even though it lied about it (besides not working).
I've added PEP 518 support, so it should work out of the box on a recent pip, no other requirements. Added a README.
I did not remove the configure and version code in CMake, even though a) it's overkill for a basic example, and b) it's not synchronized with the version in Python in any way, making it unnecessary in a Python example.
I'd like to make this a shared library and see if I can get it to work there too.