install(IMPORTED_RUNTIME_ARTIFACTS) doesn't check for symlinks
The CMake version used was 3.22.2 on Linux.
Our project currently uses another non-CMake build system generator, but we offer a CMake package for users that want to use CMake. When building our project using Make and shared libraries, the libraries are built and placed in the same place as the source and get a symbolic link in a lib
directory in the root of project like so:
$ ls -al lib
libOpenDDS_Dcps.so -> ../dds/libOpenDDS_Dcps.so.3.20.0-dev*
libOpenDDS_Dcps.so.3.20.0-dev -> ../dds/libOpenDDS_Dcps.so.3.20.0-dev*
...
The CMake package tries to find these libraries using find_library
on the lib
directory and uses add_library(IMPORTED)
on ones it can find. The issue is if a user would try to use install(IMPORTED_RUNTIME_ARTIFACTS)
on these imported libraries it copies the symlink instead of the actual library file. This would work if the symlinks were absolute and the original files stuck around, but since they are relative they don't work at all. Even if they were absolute, it seems like it defeats the purpose of install(IMPORTED_RUNTIME_ARTIFACTS)
.
I can workaround this by using get_filename_component(REALPATH)
on the paths from find_library
in the package, but it'd be nice if CMake handled this case better or at least noted this in the documentation for install(IMPORTED_RUNTIME_ARTIFACTS)
. I personally can't think of a reason why someone would want to install symlinks (either absolute or relative) like this, so if that's the case maybe all symlinks should be either be resolved or cause an error.
I have provided an example that recreates the issue using two CMake projects. lib_to_import
simulates our non-CMake main project. import_user
simulates a user of our CMake package. Instructions to recreate issue:
cd install-imported-symlink/lib_to_import
cmake -S . -B build && cmake --build build
cd ../import_user
cmake -S . -B build && cmake --build build && cmake --install build --prefix prefix
Then running LD_LIBRARY_PATH=prefix/lib ./prefix/bin/import_user
fails because prefix/lib/liblib_to_import.so
is an invalid relative symlink:
./prefix/bin/import_user: error while loading shared libraries: liblib_to_import.so: cannot open shared object file: No such file or directory
Running the second configure step again with -DSYMLINK_WORKAROUND=TRUE
runs get_filename_component(REALPATH)
on the path. Reinstalling results in the actual library being installed.
$ LD_LIBRARY_PATH=prefix/lib ./prefix/bin/import_user
Hello!