At the moment I am dealing with some RPATH and runtime linking problem where I need help:
Situation:
I have a small application MyApp that links against a shared library MyLibrary. The MyLibrary library uses a PKCS11 shared library from SafeNet to communicate with a PKCS11 USB token. The shared library from this SDK is located in /opt/safenet/protecttoolkit5/ptk/lib/libcryptoki.so. The following CMake file is used to create a working application:
cmake_minimum_required(VERSION 3.13.0)
project(myapp)
# Find the PKCS11 middleware and include it by default
include_directories("/opt/safenet/protecttoolkit5/ptk/include")
link_directories("/opt/safenet/protecttoolkit5/ptk/lib")
# Move all libraries and executables into the same directory so SO/DDL resolvement isn't a problem anymore
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
# Define the shared library that uses the cryptoki library
add_library(MyLibrary SHARED)
target_sources(MyLibrary PRIVATE MyLibrary.cpp)
target_link_libraries(MyLibrary PUBLIC cryptoki)
install(TARGETS MyLibrary LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
# Define the application that uses MyLibrary
add_executable(MyApp MyApp.cpp)
target_link_libraries(MyApp MyLibrary)
install(TARGETS MyApp RUNTIME DESTINATION bin)
And ldd shows the following dependencies which contains the /opt/safenet/protecttoolkit5/ptk/lib/libcryptoki.so:
acme@acme:~/Workspace/cmaketest/build$ ldd ./output/MyApp
linux-vdso.so.1 (0x00007ffdc326e000)
libMyLibrary.so => /home/acme/Workspace/cmaketest/build/output/libMyLibrary.so (0x00007f275575d000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f2755573000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f2755559000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2755384000)
libcryptoki.so => /opt/safenet/protecttoolkit5/ptk/lib/libcryptoki.so (0x00007f275500e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2754eca000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2755769000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f2754ebe000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2754eb8000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2754e96000)
Problem:
The application works like expected, but the problem is: The PKCS11 middleware is interchangable via symlink, which in our case is located in /lib/libcryptoki (and points to /usr/lib/libeToken.so - the USB PKCS11 middleware).
For testing, I don't want to use the middleware in /opt/safenet/protecttoolkit5/ptk/lib/libcryptoki.so, but the one in /lib/libcryptoki.so - but because the RPATH is set, the library in /opt/safenet/protecttoolkit5/ptk/lib/libcryptoki.so is used. How can I point CMake to use this library for runtime (In our Debian build later, we strip away these information anyway, but we need to test/debug the application before packaging)
What I tried:
1.) Disabling RPATH or just strip the RPATH away:
set(CMAKE_SKIP_RPATH TRUE)
This works, but then MyApp can't find MyLibrary although they are located together in the same output directory:
acme@acme:~/Workspace/cmaketest/build$ ldd ./output/libMyLibrary.so
linux-vdso.so.1 (0x00007ffc7bfbf000)
libcryptoki.so => /lib/libcryptoki.so (0x00007f87c2ae1000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f87c2914000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f87c28fa000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f87c28d8000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f87c28d2000)
libpcsclite.so.1 => /lib/x86_64-linux-gnu/libpcsclite.so.1 (0x00007f87c28c4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f87c26ed000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f87c25a9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f87c2e50000)
acme@acme:~/Workspace/cmaketest/build$ ldd ./output/MyApp
linux-vdso.so.1 (0x00007fff8b3c7000)
libMyLibrary.so => not found
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fef18b78000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fef18b5e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fef18989000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fef18845000)
/lib64/ld-linux-x86-64.so.2 (0x00007fef18d69000)
2.) Remove the link_directories, so CMake picks up the shared library /lib/libcryptoki.so. The problem is, that CMake follows the symlink and then the ldd dependency libcryptoki becomes libeToken - the middleware becomes hardcoded:
acme@acme:~/Workspace/cmaketest/build$ ldd ./output/MyApp
linux-vdso.so.1 (0x00007ffce2ff5000)
libMyLibrary.so => /home/acme/Workspace/cmaketest/build/output/libMyLibrary.so (0x00007f0285b07000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f028591d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f0285903000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f028572e000)
libeToken.so.10 => /lib/libeToken.so.10 (0x00007f02853e3000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f028529f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0285b13000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f028527b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0285275000)
libpcsclite.so.1 => /lib/x86_64-linux-gnu/libpcsclite.so.1 (0x00007f0285267000)
Question:
- Any ideas how I can make attempt 1 working? Or tell CMake not to follow the symlink? Aka use library from X, but set RPATH Y?
- Best without having the need to set LD_LIBRARY_PATH and/or strip the information away manually.