【问题标题】:Include headers with a library in CMake在 CMake 中包含带有库的标头
【发布时间】:2017-09-23 18:01:52
【问题描述】:

我的项目中有两个实用程序库。我正在寻找为库编写 CMake 配置的最佳方式。

/my_project
 --> CMakeLists.txt
 --> main.cpp
 --> /utils
      --> CMakeLists.txt
      --> common.h
      --> /base_c
           --> CMakeLists.txt
           --> base_c.c
           --> base_c.h
      --> /base_cpp
           --> CMakeLists.txt
           --> base_cpp.cpp
           --> base_cpp.hpp

我当前的 CMake 文件:

/my_project/CMakeLists.txt

cmake_minimum_requared(VERSION 3.8)
project(my_project)

add_subdirectory(utils)

add_executable(main main.c)
target_link_libraries(main utils base_c base_cpp)

/my_project/utils/CMakeLists.txt

add_subdirectory(base_c)
add_subdirectory(base_cpp)

add_library(utils)
target_sources(utils PUBLIC common.h)

/my_project/utils/base_c/CMakeLists.txt

add_library(base_c base_c.c)
target_sources(base_c PUBLIC base_c.h)

/my_project/utils/base_cpp/CMakeLists.txt

add_library(base_cpp base_cpp.cpp)
target_sources(base_cpp PUBLIC base_cpp.hpp)

find_library(BASEC base_c ../base_c)
target_link_libraries(base_cpp BASEC)

问题是base_cpp 找不到来自base_c 的包含。我应该如何修复配置?

我设法让它与target_include_directories(base_cpp PRIVATE ../base_c) 一起工作,但根据INTERFACE_INCLUDE_DIRECTORIES documentation 的说法,这很丑陋,不应该是必要的。

【问题讨论】:

  • INTERFACE_INCLUDE_DIRECTORIES 的文档如何暗示不需要target_include_directories?我很好奇你是如何在没有include_directoriestarget_include_directories 的情况下编译单个库的。
  • @Tsyvarev 我可能完全错了。你能解释一下我如何使用图书馆的INTERFACE_INCLUDE_DIRECTORIES吗?
  • 你在 CMake 之后使用哪个构建系统?生成文件? Visual Studio 项目?你能检查一下哪些目录实际上是作为包含目录传递的那些文件吗?

标签: c++ cmake


【解决方案1】:

正如@Anedar 所提到的,要解决这种情况,需要在库CMakeLists.txt 中使用target_include_directoriesPUBLICINTERFACE 选项。这填充了库目标的INTERFACE_INCLUDE_DIRECTORIES,由target_link_libraries 在消费端使用。

我的工作配置:

/my_project/CMakeLists.txt

cmake_minimum_requared(VERSION 3.8)
project(my_project)

add_subdirectory(utils)

add_executable(main main.c)
target_link_libraries(main utils base_c base_cpp)

/my_project/utils/CMakeLists.txt

add_subdirectory(base_c)
add_subdirectory(base_cpp)

add_library(utils)
target_sources(utils PUBLIC common.h)
target_include_directories(utils INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

/my_project/utils/base_c/CMakeLists.txt

add_library(base_c base_c.c)
target_sources(base_c PUBLIC base_c.h)
target_include_directories(base_c INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

/my_project/utils/base_cpp/CMakeLists.txt

add_library(base_cpp base_cpp.cpp)
target_sources(base_cpp PUBLIC base_cpp.hpp)
target_include_directories(base_cpp INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

target_link_libraries(base_cpp base_c)

【讨论】:

    【解决方案2】:

    target_include_directories) 是您要查找的内容,但不是 PRIVATE 选项。

    根据 target_include_directories() documentation PRIVATE 选项用于仅用于该目标的目录,INTERFACE 用于仅由依赖目标使用的目录,PUBLIC 用于两者。

    我建议在 /my_project/utils/base_c/CMakeLists.txt 中使用

    target_include_directories(base_c INTERFACE ${CMAKE_CURRENT_LIST_DIR})
    

    这样,您将包含目录“链接”到它所属的目标,并且依赖于它的所有目标都会自动包含该目录。

    此外,您可能希望将公共标头移动到它们自己的子文件夹/my_project/utils/base_c/base_c/,然后将它们包含为#include "base_c/base_c.h"。这为 headers 引入了一种“命名空间”,防止来自不同项目的具有相同名称的 headers 产生歧义。

    【讨论】:

    • 我需要在base_cpp 的消费端做任何事情吗?目前find_library 返回BASEC-NOTFOUND
    • 你不需要 find_library 在同一个项目中。只需使用target_link_libraries(base_cpp base_c)
    • 好的,我做到了,但它无法解析标题。也许我需要target_include_directories(base_cpp <something>)
    • @voddan: it can't resolve the headers. - 看起来您的代码以意想不到的方式包含标题。使用新的 CMake 代码和实际错误消息更新您的问题帖子。
    • 这是一个正确的答案,但解释是关闭的,所以我需要它的时候没有得到它:(
    猜你喜欢
    • 2022-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    相关资源
    最近更新 更多