MacOS CMake doesnt seem to produce relative RPATH
I've built libspatialindex as follows:
git clone https://github.com/libspatialindex/libspatialindex
cd libspatialindex
cmake .
make install
Then I move the produced dylib files to another directory during the CI pipeline of RTree and the checks fail with:
OSError: dlopen(/usr/local/miniconda/envs/test/lib/python3.8/site-packages/rtree/lib/libspatialindex_c.dylib, 6): Library not loaded: @rpath/libspatialindex.6.dylib
E Referenced from: /usr/local/miniconda/envs/test/lib/python3.8/site-packages/rtree/lib/libspatialindex_c.dylib
E Reason: image not found
Even though an ls of the folder that contains the libspatialindex_c.dylib (visible as the list of filenames right above the error in the build log) contains the file:
libspatialindex.6.1.1.dylib
libspatialindex.6.dylib
libspatialindex.dylib
libspatialindex_c.6.1.1.dylib
libspatialindex_c.6.dylib
libspatialindex_c.dylib
Going back and forth with test prints in the GitHub Actions log is not my favorite debug environment and I have no Mac device to reproduce so I can't investigate further.
Assuming it's because of moving the dylib files after they've been linked, could it be possible to switch to something that's relative to their current directory ... like ./libspatialindex.6.dylib? :) That shouldn't cause any regression or issues because well currently they can't be moved and are always linked in the same folder, switching from @rpath/libspatialindex*.dylib to ./libspatialindex*.dylib atleast makes it possible to move them together.
Maybe a possibility is to use @loader_path instead of @rpath?
I don't have a mac, but perhaps something like this might work? This is what PROJ (and presumably PDAL) have, so may work here too.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f024fdd..95bba8d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,6 +43,9 @@ if(WIN32 AND NOT CMAKE_VERSION VERSION_LESS "3.15")
cmake_policy(SET CMP0092 NEW)
endif()
+set(CMAKE_SKIP_BUILD_RPATH FALSE)
+set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
+set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if(APPLE)
set(CMAKE_MACOSX_RPATH ON)
endif()
From the name CMAKE_INSTALL_RPATH_USE_LINK_PATH I'd assume this sets the @rpath to where it was linked rather than to where it's installed, but when installed by setuptools in Python the libraries are moved both after linking and installation. So I'll give it a try but have no high hopes.
@loader_path also doesn't seem to be a good fit: It would change depending on where the libraries are loaded from. We could add a PYTHON_BIN_DEP flag to the CMake build that lets us optionally build with @loader_path. When we're used as a python dependency we are always in ./bin/ compared to where ctypes tries to load us from so @loader_path/bin/ should always point to the location of the files.
I guess the problem we're dealing with is that libraries on MacOS really don't want to be moved around :)
I guess the problem we're dealing with is that libraries on MacOS really don't want to be moved around :)
Yes, this is why Conda does huge contortions to relocate stuff.
Since libspatialindex only ever needs to find libraries in its own directory I think the best way to go is to set MACOSX_RPATH=FALSE and INSTALL_NAME_DIR=. which will hopefully then produce library load instructions like this: LC_LOAD_DYLIB ./libspatialindex.*.dylib. This is assuming that we can't add "." -- the current directory -- to the @rpath list. If that's also possible we can stick with rpath on MacOS.
Since none of us own Mac devices we best inspect which load instructions are baked into the libraries using otool -l during the CI. I can get around to doing this in a few weeks.