【问题标题】:CMake imported shared library links with relative path, breaks installCMake使用相对路径导入共享库链接,中断安装
【发布时间】:2021-02-16 10:41:40
【问题描述】:

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

我怎样才能得到一个工作安装的二进制文件?我可以通过安装步骤或 CPack 删除此库的相对路径吗?

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

.
├── build
├── CMakeLists.txt
├── hhlib-linux-64bit
│   ├── hhlib.h
│   └── hhlib.so
└── use_hydroharp.c
cmake_minimum_required (VERSION 3.19)

# These sets have no effect on the issue

# use, i.e. don't skip the full RPATH for the build tree
#SET(CMAKE_SKIP_BUILD_RPATH  FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
#SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 
# the RPATH to be used when installing
#SET(CMAKE_INSTALL_RPATH "")
# don't add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
#SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)

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 hhlib.so
    HINTS "${CMAKE_CURRENT_SOURCE_DIR}/hhlib-linux-64bit"
    )

if(HydroHarp_INCLUDEDIR AND HydroHarp_LIBRARY)
    message("Found HyroHarp library")
    # Get the containing folder for the library
    get_filename_component(HydroHarp_LIBDIR ${HydroHarp_LIBRARY} DIRECTORY)
    
    # Import the library
    add_library(HydroHarp SHARED IMPORTED)

    set_target_properties(HydroHarp PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES ${HydroHarp_INCLUDEDIR}
        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@kjhk.com")
SET(CPACK_PACKAGE_VENDOR "asdfasd")

include(CPack)

内置:

build$ cmake .. && make package

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

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

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

build$ readelf -d /usr/bin/extlink
Dynamic section at offset 0x2da8 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [../hhlib-linux-64bit/hhlib.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x1000

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

【问题讨论】:

    标签: cmake linker shared-libraries


    【解决方案1】:

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

    添加属性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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 2018-10-15
      • 2021-10-11
      • 2017-05-29
      • 1970-01-01
      相关资源
      最近更新 更多