tttapa / py-build-cmake

Modern, PEP 517 compliant build backend for creating Python packages with extensions built using CMake.
https://pypi.org/project/py-build-cmake
MIT License
38 stars 6 forks source link

Using --prefix during install overrides CMAKE_INSTALL_PREFIX #10

Closed cimes-isi closed 1 year ago

cimes-isi commented 1 year ago

I was exploring a project setup where we might build both a native application and a shared object library, the latter of which both the native binary and Python code can use (e.g., with ctypes or cffi). One problem was that the native binary couldn't find the library at runtime since the library installation path is not on LD_LIBRARY_PATH (or DYLD_LIBRARY_PATH on macos). I wasn't able to figure out how to configure the rpath properly for the installed binary since the actual install location was different than what I could derive from CMAKE_INSTALL_PREFIX, though admittedly my experience with this is limited.

My suspicion is that using --prefix with cmake makes this impossible. Is there a reason to not set -DCMAKE_INSTALL_PREFIX=/full/path/prefix with the initial cmake build command instead? Also note that CMake 3.21 introduced the --install-prefix option.

Cheers.

tttapa commented 1 year ago

I'm not sure I fully understand the issue. The path passed using the --prefix flag is the path of a temporary build folder that is deleted after the package has been built, and is different from the eventual installation path, so it is of no use for setting the rpath of the binaries.

You probably want to use a relative rpath, using the $ORIGIN token (see e.g. man ld). Then the path shouldn't depend on the installation prefix.

For Windows systems, you'll still have to make sure that the folder with the DLLs is in the PATH (or place them in the same folder as the binaries).

cimes-isi commented 1 year ago

I'm not sure we're referring to the same "prefix". I'm referring to the --prefix flag that is passed to the cmake --install command here, not the prefix key used here, which I think you might be referring to.

I did briefly look at using $ORIGIN but couldn't make it work. As I said I was only experimenting / exploring options, and I don't have a lot of experience with rpath. I was also testing on macos, which may behave differently.

Even ignoring the rpath problems, I think the core concern is that the user's CMakeLists.txt file(s) can't determine the installation prefix b/c it's overridden by using --prefix with cmake --install.

Thanks.

tttapa commented 1 year ago

I'm not sure we're referring to the same "prefix". I'm referring to the --prefix flag that is passed to the cmake --install command here, not the prefix key used here, which I think you might be referring to.

I'm also referring to the --prefix flag of the cmake --install invocation.

I think the core concern is that the user's CMakeLists.txt file(s) can't determine the installation prefix b/c it's overridden by using --prefix with cmake --install.

What I was trying to say is that you cannot rely on the installation prefix to be meaningful, so you shouldn't determine it inside of the CMakeLists.txt file.
For example, when running py-build-cmake in verbose mode, you'll see cmake --install commands like this:

[['cmake',
  '--install',
  '/tmp/build-via-sdist-kq29t8de/package-1.0.0/.py-build-cmake_cache/cp39-cp39-linux_x86_64',
  '--prefix',
  '/tmp/tmpkc6i6xs8/staging',
  '--config',
  'RelWithDebInfo',
  '--component',
  'python']]

Passing the prefix using -DCMAKE_INSTALL_PREFIX wouldn't change the fact that '/tmp/tmpkc6i6xs8/staging' is not a meaningful path to keep track of in your CMakeLists.txt file, and it should definitely not be hard-coded in the resulting binaries. As soon as the py-build-cmake build is complete, the /tmp/tmpkc6i6xs8/ folder is destroyed.

cimes-isi commented 1 year ago

I see, I was thinking in terms of a source build/install, I overlooked the staging needed for creating a portable binary wheel. Thanks for clarifying, I'll close the issue.