CMake 使用相对路径导入共享库链接,破坏安装

Ric*_*ins 5 linker cmake shared-libraries

我有一个供应商库,需要包含在我的项目的安装程序中,我正在使用INSTALL(FILES ...). 该库与源代码一起存储,问题是链接路径(由 readelf 显示)是相对的,并且该前缀在安装过程中不会被删除,因此动态链接器不是搜索hhlib.so它的../hhlib-linux-64bit/hhlib.so.

\n

如何获得可用的已安装二进制文件?我可以获取安装步骤或 CPack 来删除该库的相对路径吗?

\n

我已将问题简化为一个简单的示例:

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 hhlib-linux-64bit\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 hhlib.h\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 hhlib.so\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 use_hydroharp.c\n
Run Code Online (Sandbox Code Playgroud)\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 hhlib-linux-64bit\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 hhlib.h\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 hhlib.so\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 use_hydroharp.c\n
Run Code Online (Sandbox Code Playgroud)\n

内置:

\n
cmake_minimum_required (VERSION 3.19)\n\n# These sets have no effect on the issue\n\n# use, i.e. don\'t skip the full RPATH for the build tree\n#SET(CMAKE_SKIP_BUILD_RPATH  FALSE)\n# when building, don\'t use the install RPATH already\n# (but later on when installing)\n#SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) \n# the RPATH to be used when installing\n#SET(CMAKE_INSTALL_RPATH "")\n# don\'t add the automatically determined parts of the RPATH\n# which point to directories outside the build tree to the install RPATH\n#SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)\n\nenable_language(C)\n# Find the header files\nfind_path(HydroHarp_INCLUDEDIR\n    NAMES hhlib.h\n    PATHS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"\n    )\n# Find the shared library\nfind_library(HydroHarp_LIBRARY\n    NAMES hhlib.so\n    HINTS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"\n    )\n\nif(HydroHarp_INCLUDEDIR AND HydroHarp_LIBRARY)\n    message("Found HyroHarp library")\n    # Get the containing folder for the library\n    get_filename_component(HydroHarp_LIBDIR ${HydroHarp_LIBRARY} DIRECTORY)\n    \n    # Import the library\n    add_library(HydroHarp SHARED IMPORTED)\n\n    set_target_properties(HydroHarp PROPERTIES\n        INTERFACE_INCLUDE_DIRECTORIES ${HydroHarp_INCLUDEDIR}\n        IMPORTED_LOCATION ${HydroHarp_LIBRARY}\n    )\n    # copy  the library when installing\n    install(FILES ${HydroHarp_LIBRARY} TYPE LIB)\n\nelse()\n    message(WARNING "Failed to find HydroHarp")\nendif()\n\nproject(extlink)\nadd_executable(${PROJECT_NAME} use_hydroharp.c)\ntarget_link_libraries(${PROJECT_NAME} PRIVATE HydroHarp)\n\n# install the library\ninstall(TARGETS ${PROJECT_NAME}\n    RUNTIME DESTINATION bin\n    )\n\nset(CPACK_GENERATOR DEB CACHE INTERNAL "")\n\nSET(CPACK_PACKAGE_CONTACT "asdaksd@kjhk.com")\nSET(CPACK_PACKAGE_VENDOR "asdfasd")\n\ninclude(CPack)\n
Run Code Online (Sandbox Code Playgroud)\n

该程序使用相对路径引用共享库(这对于构建树来说很好,但由于 RUNPATH 而不需要):

\n
build$ cmake .. && make package\n
Run Code Online (Sandbox Code Playgroud)\n

make install在它仍然存在并且 RUNPATH 已被删除之后:

\n
build$ readelf -d extlink\nDynamic section at offset 0x2da8 contains 29 entries:\n  Tag        Type                         Name/Value\n 0x0000000000000001 (NEEDED)             Shared library: [../hhlib-linux-64bit/hhlib.so]\n 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]\n 0x000000000000001d (RUNPATH)            Library runpath: [/code/hhlib-linux-64bit:]\n 0x000000000000000c (INIT)               0x1000\n...\n
Run Code Online (Sandbox Code Playgroud)\n

我正在使用 CMake 3.16.3 在 Ubuntu 20.04 上构建,但也使用最新的 CMake 版本 3.19.4 进行了测试\n起初我认为这个问题提供了解决方案,但这些 RPATH 变量的组合没有解决问题。

\n

Ric*_*ins 6

在我最喜欢的尖叫枕头上发出一声美妙而漫长的尖叫后,我有了另一个想法:

添加该属性IMPORTED_NO_SONAME会删除有问题的路径,但链接器无法找到它 - 即使该路径明确包含在 中LINK_DIRECTORIES,为什么?因为供应商库不遵循命名约定!

将库重命名为libhh.so并添加set_target_properties(HydroHarp PROPERTIES IMPORTED_NO_SONAME TRUE)可以解决该问题。别问我为什么。

完整的工作 CMakeLists.txt:

cmake_minimum_required (VERSION 3.19)
enable_language(C)

# Find the header files
find_path(HydroHarp_INCLUDEDIR
    NAMES hhlib.h
    PATHS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"
    )
# Find the shared library
find_library(HydroHarp_LIBRARY
    NAMES hh # <-- Note removed .so so standard extensions are searched
    HINTS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"
    )

if(HydroHarp_INCLUDEDIR AND HydroHarp_LIBRARY)
    message("Found HyroHarp library")
    # Import the library
    add_library(HydroHarp SHARED IMPORTED)

    set_target_properties(HydroHarp PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES ${HydroHarp_INCLUDEDIR}
        IMPORTED_NO_SONAME TRUE # <-- This lib wasn't built with an SONAME
        IMPORTED_LOCATION ${HydroHarp_LIBRARY}
    )
    # copy  the library when installing
    install(FILES ${HydroHarp_LIBRARY} TYPE LIB)

else()
    message(WARNING "Failed to find HydroHarp")
endif()

project(extlink)
add_executable(${PROJECT_NAME} use_hydroharp.c)
target_link_libraries(${PROJECT_NAME} PRIVATE HydroHarp)

# install the library
install(TARGETS ${PROJECT_NAME}
    RUNTIME DESTINATION bin
    )

set(CPACK_GENERATOR DEB CACHE INTERNAL "")

SET(CPACK_PACKAGE_CONTACT "asdaksd@adssd.com")
SET(CPACK_PACKAGE_VENDOR "asdfasd")

include(CPack)
Run Code Online (Sandbox Code Playgroud)