Search code examples
cmakeinstallationrpmcpackrpath

cpack (creating RPM) ignores CMAKE_INSTALL_RPATH (sets RPATH to empty string - rather than an explicit value)


I'm trying a fairly simple experiment using cpack. The aim is to create an RPM installer (using cpack) with a trivial executable which uses an external 3rd party shared library (called libSomeSharedLib.so).

The structure I'd like the RPM to install is

opt
|_cmakeFindPackageTest
  |_bin
    |_cmakeFindPackageTest (an executable)
  |_lib
    |_libSomeSharedLib.so (the shared library)

I want the executable's RPATH to be /opt/cmakeFindPackageTest/lib (to ensure it uses the installed shared lib).

The full CMakeLists.txt is pasted at the bottom, but note the following properties are SET

 15 SET(CMAKE_INSTALL_PREFIX "/opt/cmakeFindPackageTest")
 16 SET( INSTALL_DIR_BIN ${CMAKE_INSTALL_PREFIX}/bin )
 17 SET( INSTALL_DIR_LIB ${CMAKE_INSTALL_PREFIX}/lib )
 18 
 19 SET(CMAKE_INSTALL_RPATH "\${INSTALL_DIR_LIB}")
 20 SET(CMAKE_SKIP_BUILD_RPATH TRUE)
 21 SET(CMAKE_SKIP_INSTALL_RPATH FALSE)

To my understanding, lines 17,19,20 should cause cpack to set the executable's RPATH to /opt/cmakeFindPackageTest/lib

HOWEVER...

when I build the project (from clean) and run cpack to generate an RPM I see this in the output

bash-4.2$ cpack -V -G RPM
CPack: Enable Verbose
... irrelevant looking output ommitted ...
CPack Verbose: Set runtime path of "/local/bfarnham/workspace/OPC-UA/CMake_examples/cmakeFindPackageTest/build/_CPack_Packages/Linux/RPM/cmakeFindPackageTest-0.0.0-Linux/opt/cmakeFindPackageTest/bin/cmakeFindPackageTest" to ""

RPATH gets set to empty! Eh? Checked with readelf - sure enough

bash-4.2$ readelf -d ./_CPack_Packages/Linux/RPM/cmakeFindPackageTest-0.0.0-Linux/opt/cmakeFindPackageTest/bin/cmakeFindPackageTest | grep --context=1 -i RPATH
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: []
 0x000000000000000c (INIT)               0x400848

So, finally, the question: how do I get cpack to set the RPATH of this executable in the RPM ?

================ full CMakeLists.txt ================

  1 cmake_minimum_required( VERSION 3.0 )
  2 project( cmakeFindPackageTest CXX )
  3 set (CMAKE_CXX_STANDARD 11)
  4 
  5 list( INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake )
  6 message( STATUS "CMAKE_MODULE_PATH [${CMAKE_MODULE_PATH}]" )
  7 find_package( SomeSharedLib 1.0 REQUIRED MODULE )
  8 message( STATUS "SomeSharedLib_INCLUDE_DIR [${SomeSharedLib_INCLUDE_DIR}]  SomeSharedLib_LIBRARY [${SomeSharedLib_LIBRARY}]" )
  9 
 10 add_executable( cmakeFindPackageTest src/main.cpp )
 11 target_link_libraries( cmakeFindPackageTest SomeSharedLib::SomeSharedLib )
 12 
 13 # =============================== INSTALL DETAILS BELOW THIS POINT ==========================
 14 
 15 SET(CMAKE_INSTALL_PREFIX "/opt/cmakeFindPackageTest")
 16 SET( INSTALL_DIR_BIN ${CMAKE_INSTALL_PREFIX}/bin )
 17 SET( INSTALL_DIR_LIB ${CMAKE_INSTALL_PREFIX}/lib )
 18 
 19 SET(CMAKE_INSTALL_RPATH "\${INSTALL_DIR_LIB}")
 20 SET(CMAKE_SKIP_BUILD_RPATH TRUE)
 21 SET(CMAKE_SKIP_INSTALL_RPATH FALSE)
 22 SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
 23 
 24 SET(CPACK_PACKAGE_NAME cmakeFindPackageTest )
 25 SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "test")
 26 SET(CPACK_PACKAGE_VENDOR "TEST_VENDOR")
 27 SET(CPACK_PACKAGE_RELOCATABLE FALSE)
 28 SET(CPACK_PACKAGE_VERSION_MAJOR "0")
 29 SET(CPACK_PACKAGE_VERSION_MINOR "0")
 30 SET(CPACK_PACKAGE_VERSION_PATCH "0")
 31 
 32 install( TARGETS 
 33   cmakeFindPackageTest
 34   RUNTIME DESTINATION ${INSTALL_DIR_BIN} )
 35 
 36 install( FILES
 37   ${SomeSharedLib_LIBRARY}
 38   DESTINATION ${INSTALL_DIR_LIB} )
 39   
 40 include( CPack )

Solution

  • I fixed this by explicitly setting the INSTALL_RPATH property value for the executable target. So, the addition of the set_target_properties line after the call to install

    install( TARGETS 
      cmakeFindPackageTest
      RUNTIME DESTINATION ${INSTALL_DIR_BIN} )
    set_target_properties( cmakeFindPackageTest PROPERTIES INSTALL_RPATH "/opt/cmakeFindPackageTest/lib" )
    

    From the cmake/cpack documentation it seemed like setting the CMAKE_INSTALL_RPATH variable should have worked. The CMAKE_INSTALL_RPATH docs read

    The rpath to use for installed targets.

    A semicolon-separated list specifying the rpath to use in installed targets (for platforms that support it). This is used to initialize the target property INSTALL_RPATH for all targets.