【问题标题】:CMake: Including static libraries and resolving transitive dependenciesCMake:包括静态库和解决传递依赖
【发布时间】:2021-07-07 19:35:47
【问题描述】:

我有一个项目,我需要在其中使用 NAG 库 (libnagc_nag.a) 并使用 CMake 构建项目。在我的系统上,NAG 安装在/usr/lib/NAG26。库的目录是/usr/lib/NAG26/cll6i261d/lib

还有我的项目将使用的头文件 (nag.h, nag_stdlib.h, nagf08.h, nagx04.h)。以下是我的 CMakeLists.txt

cmake_minimum_required(VERSION 3.20)

project(AnyProject VERSION 1.0)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

configure_file(AnyProject.h.in AnyProject.h)

find_library(LIB_TO_INCLUDE nagc_nag "/usr/lib/NAG26/cll6i261d/lib")

find_path(LIB_INCLUDES nag.h "/usr/lib/NAG26/cll6i261d/include")
find_path(LIB_INCLUDES nag_stdlib.h "/usr/lib/NAG26/cll6i261d/include")
find_path(LIB_INCLUDES nagf08.h "/usr/lib/NAG26/cll6i261d/include")
find_path(LIB_INCLUDES nagx04.h "/usr/lib/NAG26/cll6i261d/include")

add_executable(AnyProject ${PROJECT_SOURCE_DIR}/main.cpp)

target_include_directories(AnyProject PUBLIC ${LIB_INCLUDES})
target_include_directories(AnyProject PUBLIC
                           ${PROJECT_BINARY_DIR}
                           )

target_link_libraries(AnyProject ${LIB_TO_INCLUDE})

我有几个问题

  1. 上面的CMakeLists.txt在构建的时候会报错:
/usr/bin/ld: warning: libifcoremt.so.5, needed by /usr/lib/NAG26/cll6i261d/lib/libnagc_nag.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libsvml.so, needed by /usr/lib/NAG26/cll6i261d/lib/libnagc_nag.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libimf.so, needed by /usr/lib/NAG26/cll6i261d/lib/libnagc_nag.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libirc.so, needed by /usr/lib/NAG26/cll6i261d/lib/libnagc_nag.so, not found (try using -rpath or -rpath-link)
/usr/lib/NAG26/cll6i261d/lib/libnagc_nag.so: undefined reference to `__gtq'
/usr/lib/NAG26/cll6i261d/lib/libnagc_nag.so: undefined reference to `for_f90_index'
/usr/lib/NAG26/cll6i261d/lib/libnagc_nag.so: undefined reference to `for_close'
/usr/lib/NAG26/cll6i261d/lib/libnagc_nag.so: undefined reference to `__intel_sse4_strspn'
.
.
.

我了解 CMake 无法找出传递依赖关系。文件 libsvml.so, libimf.so, libirc.so, libifcoremt.so.5 与添加到 target_include_directories 的 libnagc_nag.a and libnagc_nag.so 位于同一目录中。如何解决这个问题?我想我不应该在这里明确地包含传递依赖关系,或者我应该这样做吗?

  1. 有没有办法不指定我希望链接的 *.a 库的确切路径并让 CMake 为我找到它?对于我的系统,我知道 NAG 安装在哪里,但对于其他系统,我不知道它安装在哪里。如何让上面的 CMakeLists.txt 更便携?

  2. 有没有办法从一个目录中包含所有(必要的)头文件,而不是一个一个地包含它们(如果它们太多,这将是乏味的)?。

我是第一次使用 CMake,所以我的问题可能没有很好地形成。对于上述问题的任何一般性建议将不胜感激。

【问题讨论】:

    标签: cmake


    【解决方案1】:

    已添加到 target_include_directories。如何解决?

    target_include_directories 添加#include 目录。 target_link_directories 添加库搜索路径。将路径添加到库搜索路径。

    有没有办法不指定我希望链接的 *.a 库的确切路径并让 CMake 为我找到它?

    不,CMake 必须知道库的路径。

    您可以将目录添加到target_link_directories,并在链接时让编译器在库搜索路径中搜索您的库。

    如何让上面的 CMakeLists.txt 更便携?

    为了让你的 CMake 更便携,降低所需的最低版本,即使有 CMake 2.8 的机器仍然有。 CMake 会自行检查指定版本的可移植性。就个人而言,我坚持使用 CMake 3.11,但没有任何理由。

    有没有办法从一个目录中包含所有(必要的)头文件,而不是一个一个地包含它们(如果它们太多,这将是乏味的)?

    CMake 不包含 C 头文件。

    在 C 编程语言中,创建一个 #includes 所有文件的标头,然后将该标头包含在您的 C 源文件中。

    任何一般性建议

    用同一个变量调用多个find_path是没有意义的——新的调用被忽略了,因为CMake缓存变量已经存在了。

    好吧,重新阅读有关 CMake 和一些 CMake 介绍以及对 C 编译阶段的介绍 - 关于编译和链接。您可能想研究 CMake IMPORTED 库和最有可能的 ExternalProject_Add 实用程序。

    如果您知道头文件或库文件在那里,那么搜索它们是没有意义的。如果您不确定它是否存在,请搜索东西,以便在没有“东西”的环境之间移植。就像某些环境没有 unistd.h - 所以你可以在 CMake 中检查它,然后以不同的方式编译代码来处理这种情况 - 实现可移植性。

    关于上述问题将不胜感激。

    在这种情况下,我只会使用一个 INTERFACE 库,这样看起来不错:

    add_library(nag INTERFACE)
    set(nag_path /usr/lib/NAG26/cll6i261d)
    target_include_directories(nag INTERFACE "${nag_path}"/include)
    target_link_directories(nag INTERFACE "${nag_path}"/lib)
    target_link_libraries(nag INTERFACE ifcoremt svml imf irc)
    
    target_link_libraries(AnyProject PRIVATE nag)
    

    但也许为每个 ifcoremt svml imf irc 创建一个 IMPORTED 库会是更好的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-20
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-13
      • 2023-03-03
      相关资源
      最近更新 更多