Change CMake RPATH for a single library while keeping others

428 Views Asked by At

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.
0

There are 0 best solutions below