【问题标题】:Shared Libraries not linking together after installation with CMake使用 CMake 安装后共享库未链接在一起
【发布时间】:2021-10-11 15:13:11
【问题描述】:

我在使用 Google 测试时遇到了一个相当奇怪的问题。

在我的项目中,我使用externalProject_add 来下载谷歌测试并将它们添加到我的项目中。在我的功能中,我相信我要求构建项目,然后安装到特定目录中:

ExternalProject_Add(gTest_download
  URL ${GTEST_url}
  URL_HASH ${GTEST_hash}
  UPDATE_COMMAND ""
  BUILD_COMMAND cmake --build . --target install
  CMAKE_CACHE_ARGS
    -DCMAKE_C_COMPILER:PATH=${Compiler_C}
    -DCMAKE_CXX_COMPILER:PATH=${Compiler_CXX}
    -DBUILD_SHARED_LIBS:BOOL=ON
    -DCMAKE_INSTALL_PREFIX:PATH=<BINARY_DIR>/installation
)

然后我可以告诉程序所有源文件都在哪里:

ExternalProject_Get_Property(gTest_download BINARY_DIR)

set(gTest_LIBRARY_DIR ${BINARY_DIR}/installation/lib CACHE INTERNAL "Google Test Binary Dir")
set(gTest_INCLUDE_DIR ${BINARY_DIR}/installation/include CACHE INTERNAL "Google Test Include Dir")

但是,当我尝试使用 protobufs 运行 cmake 测试时,出现运行时错误:

./Protobuf_test: error while loading shared libraries: libgmock.so.1.11.0: cannot open shared object file: No such file or directory

这太奇怪了,因为我知道我专门告诉程序在同一个 externalProject_add 文件中的哪里可以找到库:

set(gTest_LIBRARIES 
  ${gTest_LIBRARY_DIR}/${prefix}gmock${suffix}
  ${gTest_LIBRARY_DIR}/${prefix}gmock_main${suffix}
  ${gTest_LIBRARY_DIR}/${prefix}gtest${suffix}
  ${gTest_LIBRARY_DIR}/${prefix}gtest_main${suffix}
  CACHE INTERNAL "Google Test Libraries"
)

其中${prefix} 是“lib”,${suffix} 是“.lib”。我确保通过target_link_libraries(Protobuf_test ${gTest_LIBRARIES} ${protobuf_LIBRARIES}) ex:

将它们正确链接到我的 CMakeLists.txt 文件中
CUSTOM_PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDS ${CMAKE_CURRENT_LIST_DIR} hello.proto)

include_directories(
  ${protoBuf_INCLUDE_DIR}
  ${gTest_INCLUDE_DIR}
  ${CMAKE_CURRENT_LIST_DIR}
)

add_executable(Protobuf_test protobuf_test.cc ${PROTO_SRCS} ${PROTO_HDS})

add_dependencies(Protobuf_test 
  gTest_download 
  protoBuf_download
)

target_link_libraries(Protobuf_test 
  ${gTest_LIBRARIES} 
  ${protoBuf_LIBRARIES}
)

add_test(NAME testing_protobuf COMMAND Protobuf_test)

所以我进入位于d/linuxBuild/lib/src/gTest_download-build/installation/lib 的安装文件夹并确认它存在于那里。然后我运行ldd libgmock.so 并得到以下输出:

libgtest.so.1.11.0 => not found

我也觉得很奇怪。 gtest 在同一目录中!这怎么可能?所以我在 gmock_main 上运行了 ldd:

libgmock.so.1.11.0 => not found
libgtest.so.1.11.0 => not found

所以现在我有两个库位于同一目录中,但是找不到它们。感到困惑的是,我决定去最初应该​​安装和复制库的地方。所以两个文件夹:d/linuxBuild/lib/src/gTest_download-build。然后我进入该文件夹的 lib 文件夹并验证库是否存在。然后我在 gmock 上运行相同的 ldd 命令:

libgtest.so.1.11.0 => /mnt/d/linuxBuild/lib/src/gTest_download-build/lib/libgtest.so.1.11.0 (0x00007fb651729000)

我对此感到困惑,再次在 gmock_main 上运行它:

libgmock.so.1.11.0 => /mnt/d/linuxBuild/lib/src/gTest_download-build/lib/libgmock.so.1.11.0 (0x00007f58b0db3000)
libgtest.so.1.11.0 => /mnt/d/linuxBuild/lib/src/gTest_download-build/lib/libgtest.so.1.11.0 (0x00007f58b0c9c000)

很抱歉这个冗长的问题,但我需要知道这里发生了什么?为什么当我安装库时,链接会相互断开,并且与原始安装路径中的位置相比,它们不知道它们的位置?他们的符号链接断开了吗?我在 CMake 构建中做错了什么吗?我在这个问题上摸不着头脑,因为我以前从未遇到过这个问题。任何建议将不胜感激。

【问题讨论】:

  • 不是按要求回答您的问题,但FetchContent() 使用起来更简单,因为您只需执行target_link_libraries(target gmock_main) 并让cmake 处理其他所有事情。
  • @Frank 有没有一个可靠的例子,你知道我可以看看?如果有更好的解决方案,我个人很乐意从 externalproject_add 继续前进。

标签: linux cmake linker


【解决方案1】:

忘记 externalProject_add 并使用 FetchContent / FetchContent_MakeAvailable,尤其是在处理 CMake 就绪项目时:

详情请见https://cmake.org/cmake/help/latest/module/FetchContent.html

include(FetchContent)

FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        release-1.11.0
)

FetchContent_MakeAvailable(googletest)

# ...

target_link_libraries(Protobuf_test  
PRIVATE
  gmock_main
  ${protoBuf_LIBRARIES}
)

这样,您将链接到gmock_main 目标,它将正确设置您的库、包含和任何间接依赖项,就像通过add_subdirectory()find_package() 添加的任何cmake 项目一样.

【讨论】:

  • FetchContent 是否适用于所有外部项目?就像我可以在任何谷歌环境中使用这种相同的格式?还是像 ZLib 之类的其他东西?
  • 如果项目在存储库的根目录中有一个CMakeLists.txt,它本质上等同于add_subdirectory(),但还有一些其他选项。我添加到答案中的链接应该涵盖了您。示例部分已经涵盖了 Protobufs :)。
  • 如果您要发布一个库,您需要小心允许用户使用find_package 覆盖您的 FetchContent 依赖项。通常情况下,您应该先尝试,如果失败则回退到 FC。
猜你喜欢
  • 1970-01-01
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-04
  • 1970-01-01
相关资源
最近更新 更多