【问题标题】:How to handle header-only thirdparties with CMake?如何使用 CMake 处理仅包含标头的第三方?
【发布时间】:2020-03-04 23:45:56
【问题描述】:

在一个项目中,我们使用ExternalProject_add 来管理常规第三方并推动他们的下载和构建过程(一些来自常规 URL,另一些来自 git 存储库)

最近,我发现需要添加一个额外的第三方。到目前为止,它是我们唯一拥有的仅包含标头的第三方。有兴趣的可以kvasir_mpl

但是,当我尝试使用 target_link_librarieskvasir_mpl 时,CMake 始终将其视为常规库,最终构建失败:

[ 83%] 链接 CXX 可执行应用程序
/usr/bin/ld: 找不到 -lkvasir_mpl

我设计了一个最小的例子来重现这个问题:

./CMakeLists.txt:

cmake_minimum_required( VERSION 3.7.0 )

project( Test CXX )

add_subdirectory( kvasir )
add_subdirectory( app )

./app/CMakeLists.txt:

project( App CXX )

add_executable( app main.cpp )

target_link_libraries( app kvasir_mpl )

kvasirmpl/CMakeLists.txt:

cmake_minimum_required( VERSION 3.7.0 )

project( KvasirMpl )

include( ExternalProject )

ExternalProject_Add(
    3rdparty_kvasirmpl

    GIT_REPOSITORY https://github.com/kvasir-io/mpl
    GIT_TAG origin/development
    INSTALL_COMMAND ""
    BUILD_COMMAND "" )

请注意,如果我使用关键字签名target_link_libraries( app INTERFACE kvasir_mpl ),我的问题就解决了。但是在我们的实际用例中,target_link_libraries 是通过自定义 CMake 函数运行的,并且可以将任何内容从常规库文件传递到 CMake 目标,从而迫使我们使用普通签名。

有没有办法让普通签名在这种情况下工作?

【问题讨论】:

  • 它只带有标题。这些包含在您的源代码中,并将与它们一起编译。没有要链接的库,因此您也不需要target_link_libraries。只需确保在包含路径中找到标头即可。
  • 在这种情况下,target_link_libraries 确保将标头添加到正确的构建/安装界面。如果我理解正确,它仍然是强制性的。
  • 错误的重复...我不是要创建接口目标,而是要让 CMake 管理下载,然后创建接口目标。我所指的第三方已经做了stackoverflow.com/questions/5957134/… 中提到的事情

标签: c++ cmake linker


【解决方案1】:

在 kvasirmpl/CMakeLists.txt 中,添加以下行:

add_library(kvasir_mpl INTERFACE)
target_include_directories(kvasir_mpl PUBLIC <includedirs>)
set_target_properties(kvasir_mpl PROPERTIES LINKER_LANGUAGE CXX)

这告诉 CMake 有一个不是由 CMake(接口)构建的库,与该库链接时包含的目录是什么...您还可以添加额外的编译标志等。 必须指定链接器语言,因为 CMake 希望知道它是 C 还是 C++,并且不会在仅标头库中扣除它。

【讨论】:

  • 重点是使用 ExternalProject_add 自动执行该步骤,最终将添加目标 kvasir_mpl(由 kvasir::mpl 库定义)
猜你喜欢
  • 1970-01-01
  • 2022-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-03
  • 2019-05-14
  • 2022-10-15
  • 2017-08-17
相关资源
最近更新 更多