强制导入的目标使用.so文件的绝对路径,即使它位于项目根目录的子文件夹中

Cor*_*sto 5 linker cmake dynamic-linking

我有以下目录结构

.
??? 3rdparty
?   ??? liba
?       ??? include
?       ?   ??? liba.hpp
?       ??? lib
?           ??? liba.so
??? cmake
?   ??? FindLiba.cmake
??? CMakeLists.txt
??? source
    ??? CMakeLists.txt
    ??? main.cpp
Run Code Online (Sandbox Code Playgroud)

liba是一个商业的,开放源代码的第三方库。不幸的是,该库的供应商未为其库提供CMake配置,因此我编写了自己的find模块:

# cmake/FindLiba.cmake

# - Try to find liba
# Once done, this will define
#
#  Liba_FOUND - system has liba
#  Liba_INCLUDE_DIRS - the liba include directories
#  Liba_LIBRARIES - link these to use liba

# Include dir
find_path(Liba_INCLUDE_DIR
  NAMES liba.hpp
)

# Finally the library itself
find_library(Liba_LIBRARY
  NAMES a
)

include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set Liba_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(Liba  DEFAULT_MSG
                                  Liba_LIBRARY Liba_INCLUDE_DIR)

mark_as_advanced(Liba_INCLUDE_DIR Liba_LIBRARY)

set(Liba_INCLUDE_DIRS ${Liba_INCLUDE_DIR})
set(Liba_LIBRARIES ${Liba_LIBRARY})

if (NOT TARGET Liba::Liba) 
    add_library(Liba::Liba SHARED IMPORTED) 
    set_target_properties(Liba::Liba PROPERTIES
        IMPORTED_LOCATION ${Liba_LIBRARIES} 
        INTERFACE_INCLUDE_DIRECTORIES ${Liba_INCLUDE_DIR}
    )
endif()
Run Code Online (Sandbox Code Playgroud)

由于main.cpp使用了此库,CMakeLists.txt因此source文件夹中的如下所示:

find_package(Liba REQUIRED)

add_executable(main main.cpp)

# VERSION 1
target_link_libraries(main PRIVATE Liba::Liba)

# VERSION 2
target_link_libraries(main PRIVATE ${Liba_LIBRARIES})
target_include_directories(main PRIVATE ${Liba_INCLUDE_DIRS})
Run Code Online (Sandbox Code Playgroud)

要构建我使用的全部内容cmake -Bbuild -H. -DCMAKE_PREFIX_PATH=${PWD}/3rdparty/liba && cmake --build build

我遇到的问题如下:在版本1中,已编译的二进制build/source/main链接指向../3rdparty/liba/liba.so,可以在的输出中看到ldd

ldd build/source/main
    [...]
    ../3rdparty/liba/lib/liba.so => not found
    [...]
Run Code Online (Sandbox Code Playgroud)

使用版本2时,main链接不liba.so带相对路径,但rpath似乎已设置为仍可找到:

ldd build/source/main
    [...]
    liba.so => /home/manuel/development/demo/3rdparty/liba/lib/liba.so (0x00007f2a4c3f3000)
    [...]
Run Code Online (Sandbox Code Playgroud)

第二版本是优选的,因为与版本1可执行可以运行仅在当前工作目录是buildcmake3rdparty或者source,否则的共享库无法找到。特别是,我不能仅./build/source/main在项目构建后就运行。

有趣的是,这似乎只是一个问题,因为liba它位于项目子树中。当我移出liba项目目录并相应地调整CMAKE_PREFIX_PATH时,它也可以正常工作。但是我想将其保留在当前位置,以便它成为git存储库的一部分,并main.cpp使用它进行版本控制。

有没有一种方法可以将导入的目标配置为Liba仅将其添加到target_link_libraries导致CMake的行为与添加时相同的方式${Liba_LIBRARIES}