cpack(创建 RPM)忽略 CMAKE_INSTALL_RPATH(将 RPATH 设置为空字符串 - 而不是显式值)
cpack (creating RPM) ignores CMAKE_INSTALL_RPATH (sets RPATH to empty string - rather than an explicit value)
我正在尝试使用 cpack 进行一个相当简单的实验。目的是用一个简单的可执行文件创建一个 RPM 安装程序(使用 cpack),该可执行文件使用外部第 3 方共享库(称为 libSomeSharedLib.so)。
我希望 RPM 安装的结构是
opt
|_cmakeFindPackageTest
|_bin
|_cmakeFindPackageTest (an executable)
|_lib
|_libSomeSharedLib.so (the shared library)
我希望可执行文件的 RPATH 为 /opt/cmakeFindPackageTest/lib
(以确保它使用已安装的共享库)。
完整的CMakeLists.txt粘贴在底部,但注意以下属性是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)
根据我的理解,第 17、19、20 行应该导致 cpack 将可执行文件的 RPATH 设置为 /opt/cmakeFindPackageTest/lib
然而...
当我构建项目(从干净的)和 运行 cpack 生成 RPM 时,我在输出中看到了这个
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 设置为空! 嗯?使用 readelf 检查 - 果然如此
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
所以,最后,问题是:如何让 cpack 在 RPM 中设置此可执行文件的 RPATH?
================满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 )
我通过显式设置可执行目标的 INSTALL_RPATH
属性 值来修复此问题。因此,在调用 install
之后添加 set_target_properties
行
install( TARGETS
cmakeFindPackageTest
RUNTIME DESTINATION ${INSTALL_DIR_BIN} )
set_target_properties( cmakeFindPackageTest PROPERTIES INSTALL_RPATH "/opt/cmakeFindPackageTest/lib" )
从 cmake/cpack 文档来看,设置 CMAKE_INSTALL_RPATH
变量似乎应该有效。 CMAKE_INSTALL_RPATH 文档读取
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.
这不是答案;而是上述修复的附录...
通过上述修复,cpack 生成一个 RPM,其中包含一个具有正确 RPATH 的可执行文件。但是,RPM 是 'broken':安装失败 - 尽管 RPM 包含所需的共享库,但似乎 cpackRPM 不知何故没有在生成的 RPM 中为其提供相应的属性。这样安装失败
bash-4.2$ sudo yum install cmakeFindPackageTest-0.0.0-Linux.rpm
Loaded plugins: changelog, fastestmirror, kernel-module, langpacks, protectbase, tsflags, versionlock
Examining cmakeFindPackageTest-0.0.0-Linux.rpm: cmakefindpackagetest-0.0.0-1.x86_64
Marking cmakeFindPackageTest-0.0.0-Linux.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package cmakefindpackagetest.x86_64 0:0.0.0-1 will be installed
--> Processing Dependency: libSomeSharedLib.so()(64bit) for package: cmakefindpackagetest-0.0.0-1.x86_64
Loading mirror speeds from cached hostfile
211 packages excluded due to repository protections
--> Finished Dependency Resolution
Beginning Kernel Module Plugin
Finished Kernel Module Plugin
Error: Package: cmakefindpackagetest-0.0.0-1.x86_64 (/cmakeFindPackageTest-0.0.0-Linux)
Requires: libSomeSharedLib.so()(64bit)
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest
bash-4.2$
这通过指示 cpack 安装第 3 方库而不是 FILE
而是 PROGRAM
来解决。 CMakeLists.txt的关键块是
22 install( PROGRAMS
23 ${SomeSharedLib_LIBRARY}
24 DESTINATION ${INSTALL_DIR_LIB} )
下面粘贴了完整的 CMakeLists.txt 文件。这将创建一个 RPM,其中可执行 RPATH 设置为安装站点 lib 目录,和 共享库 在 RPM 安装期间被正确识别 为共享库(即解决了 'Requires: libSomeSharedLib.so' 失败)
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 SET(CMAKE_INSTALL_PREFIX "/opt/cmakeFindPackageTest" )
14 SET(INSTALL_DIR_BIN ${CMAKE_INSTALL_PREFIX}/bin)
15 SET(INSTALL_DIR_LIB ${CMAKE_INSTALL_PREFIX}/lib)
16
17 install( TARGETS
18 cmakeFindPackageTest
19 RUNTIME DESTINATION ${INSTALL_DIR_BIN} )
20 set_target_properties( cmakeFindPackageTest PROPERTIES INSTALL_RPATH "${INSTALL_DIR_LIB}" )
21
22 install( PROGRAMS
23 ${SomeSharedLib_LIBRARY}
24 DESTINATION ${INSTALL_DIR_LIB} )
25
26 SET(CPACK_PACKAGE_NAME cmakeFindPackageTest )
27 SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "test")
28 SET(CPACK_PACKAGE_VENDOR "TEST_VENDOR")
29 SET(CPACK_PACKAGE_RELOCATABLE FALSE)
30 SET(CPACK_PACKAGE_VERSION_MAJOR "0")
31 SET(CPACK_PACKAGE_VERSION_MINOR "0")
32 SET(CPACK_PACKAGE_VERSION_PATCH "0")
33
34 include( CPack )
35 #include (${PROJECT_SOURCE_DIR}/CMakeEpilogue.cmake)
我正在尝试使用 cpack 进行一个相当简单的实验。目的是用一个简单的可执行文件创建一个 RPM 安装程序(使用 cpack),该可执行文件使用外部第 3 方共享库(称为 libSomeSharedLib.so)。
我希望 RPM 安装的结构是
opt
|_cmakeFindPackageTest
|_bin
|_cmakeFindPackageTest (an executable)
|_lib
|_libSomeSharedLib.so (the shared library)
我希望可执行文件的 RPATH 为 /opt/cmakeFindPackageTest/lib
(以确保它使用已安装的共享库)。
完整的CMakeLists.txt粘贴在底部,但注意以下属性是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)
根据我的理解,第 17、19、20 行应该导致 cpack 将可执行文件的 RPATH 设置为 /opt/cmakeFindPackageTest/lib
然而...
当我构建项目(从干净的)和 运行 cpack 生成 RPM 时,我在输出中看到了这个
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 设置为空! 嗯?使用 readelf 检查 - 果然如此
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
所以,最后,问题是:如何让 cpack 在 RPM 中设置此可执行文件的 RPATH?
================满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 )
我通过显式设置可执行目标的 INSTALL_RPATH
属性 值来修复此问题。因此,在调用 install
set_target_properties
行
install( TARGETS
cmakeFindPackageTest
RUNTIME DESTINATION ${INSTALL_DIR_BIN} )
set_target_properties( cmakeFindPackageTest PROPERTIES INSTALL_RPATH "/opt/cmakeFindPackageTest/lib" )
从 cmake/cpack 文档来看,设置 CMAKE_INSTALL_RPATH
变量似乎应该有效。 CMAKE_INSTALL_RPATH 文档读取
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.
这不是答案;而是上述修复的附录...
通过上述修复,cpack 生成一个 RPM,其中包含一个具有正确 RPATH 的可执行文件。但是,RPM 是 'broken':安装失败 - 尽管 RPM 包含所需的共享库,但似乎 cpackRPM 不知何故没有在生成的 RPM 中为其提供相应的属性。这样安装失败
bash-4.2$ sudo yum install cmakeFindPackageTest-0.0.0-Linux.rpm
Loaded plugins: changelog, fastestmirror, kernel-module, langpacks, protectbase, tsflags, versionlock
Examining cmakeFindPackageTest-0.0.0-Linux.rpm: cmakefindpackagetest-0.0.0-1.x86_64
Marking cmakeFindPackageTest-0.0.0-Linux.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package cmakefindpackagetest.x86_64 0:0.0.0-1 will be installed
--> Processing Dependency: libSomeSharedLib.so()(64bit) for package: cmakefindpackagetest-0.0.0-1.x86_64
Loading mirror speeds from cached hostfile
211 packages excluded due to repository protections
--> Finished Dependency Resolution
Beginning Kernel Module Plugin
Finished Kernel Module Plugin
Error: Package: cmakefindpackagetest-0.0.0-1.x86_64 (/cmakeFindPackageTest-0.0.0-Linux)
Requires: libSomeSharedLib.so()(64bit)
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest
bash-4.2$
这通过指示 cpack 安装第 3 方库而不是 FILE
而是 PROGRAM
来解决。 CMakeLists.txt的关键块是
22 install( PROGRAMS
23 ${SomeSharedLib_LIBRARY}
24 DESTINATION ${INSTALL_DIR_LIB} )
下面粘贴了完整的 CMakeLists.txt 文件。这将创建一个 RPM,其中可执行 RPATH 设置为安装站点 lib 目录,和 共享库 在 RPM 安装期间被正确识别 为共享库(即解决了 'Requires: libSomeSharedLib.so' 失败)
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 SET(CMAKE_INSTALL_PREFIX "/opt/cmakeFindPackageTest" )
14 SET(INSTALL_DIR_BIN ${CMAKE_INSTALL_PREFIX}/bin)
15 SET(INSTALL_DIR_LIB ${CMAKE_INSTALL_PREFIX}/lib)
16
17 install( TARGETS
18 cmakeFindPackageTest
19 RUNTIME DESTINATION ${INSTALL_DIR_BIN} )
20 set_target_properties( cmakeFindPackageTest PROPERTIES INSTALL_RPATH "${INSTALL_DIR_LIB}" )
21
22 install( PROGRAMS
23 ${SomeSharedLib_LIBRARY}
24 DESTINATION ${INSTALL_DIR_LIB} )
25
26 SET(CPACK_PACKAGE_NAME cmakeFindPackageTest )
27 SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "test")
28 SET(CPACK_PACKAGE_VENDOR "TEST_VENDOR")
29 SET(CPACK_PACKAGE_RELOCATABLE FALSE)
30 SET(CPACK_PACKAGE_VERSION_MAJOR "0")
31 SET(CPACK_PACKAGE_VERSION_MINOR "0")
32 SET(CPACK_PACKAGE_VERSION_PATCH "0")
33
34 include( CPack )
35 #include (${PROJECT_SOURCE_DIR}/CMakeEpilogue.cmake)