CPack Debian Packaging and RUNPATH/RPATH for dependencies picked up from IMPORTED_RUNTIME_ARTIFACTS


I’m trying to get cmake to package my Linux executable (+ dependent libraries) as a deb package.
The executable should live in /opt/foo/bin and the libraries it depends on should live in /opt/foo/lib.

However, I’m having problems with the executable finding dependent/transitive libraries in /opt/foo/lib when the libraries are picked up from IMPORTED_RUNTIME_ARTIFACTS.

I first tried setting the RUNPATH of the executable to point to /opt/foo/lib:

cmake_minimum_required( VERSION 3.24 )

add_executable(myprogram myprogram.cpp)
target_link_libraries(myprogram PUBLIC libraryA)

set(CMAKE_INSTALL_PREFIX "/opt/foo" CACHE PATH "Default install path" FORCE)

# set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") # I tried setting this but it doesn't seem to do anything?

install(TARGETS myprogram
# Automatically pick up non system dependencies
    POST_EXCLUDE_REGEXES "^/lib" "^/usr/lib"

# Set runpath of my program to the libdir


but I notice that all transitive dependencies do not get picked up when I try to launch myprogram since this only sets the RUNPATH of the executable. (The libraries that libraryA depends on, even though they are successfully placed in /opt/foo/lib from install(RUNTIME_DEPENDENCY_SET ...))
In my case, the dependent libraries which are pulled into /opt/foo/lib are and

I then tried to set the RPATH instead of RUNPATH of my program, as I read that when the RPATH of the executable is set, the dynamic linker will use that to find all transitive dependencies as well.

# append to previous code
target_link_options(myprogram PRIVATE -Wl,--disable-new-dtags)

But I then encountered this issue (c++ - Binary with RPATH not finding transitive dependencies if one of them has RUNPATH - Stack Overflow) where transitive libraries of a dependent libraries with a RUNPATH set cannot be found. When I try to launch my program, I see that cannot be found, even though it exists in /opt/foo/lib and the RPATH of myprogram points there.

In this case, my libraryA directly links to the library, but has its RUNPATH set to when I installed it on my build machine (/usr/local/GTSAM). itself has a dependency on another library (this is the transitive dependency that cannot be found, even though both were successfully picked up and placed in /opt/foo/lib). When I inspect the library on the install machine: readelf -d /opt/foo/lib/ I see that the runpath still points to /usr/local/GTSAM (which does not exist on the install machine).

  1. In the end, I gave up on trying to set RPATH/RUNPATH and packaged a foo.conf file to /etc/ to point to /opt/foo/lib but I think that’s a bad solution as it also exposes my bundled libraries to other programs on the install machine - is there a cleaner solution?
  2. Is it possible to get cmake to overwrite the RUNPATH’s of all dependencies installed during install(RUNTIME_DEPENDENCY_SET ...) to whatever CMAKE_INSTALL_RPATH is set to? I think such a solution would be the the nicest.
    I was looking around and it may be possible using CPACK_PRE_BUILD_SCRIPTS + patchelf, so that I don’t have to force an RPATH, and just ensure that every library/executable in my package has their RUNPATH point to /opt/foo/lib

Thank you!