CMake 包含路径 - 依赖于外部库的库

Posted

技术标签:

【中文标题】CMake 包含路径 - 依赖于外部库的库【英文标题】:CMake Include paths - library that depend on external library 【发布时间】:2021-10-12 15:01:35 【问题描述】:

以这个项目结构为例

project
    CMakeLists.txt
    main.cpp
    libA
         src.cpp
         CMakeLists.txt
    libB
         foo.h
         foo.cpp
         CMakeLists.txt
       

src.cppma​​in.cpp

#include "foo.h"
.
.
.

我需要 src.cpp 和 main.cpp 在它们的包含路径中包含 libB,我尝试做的是:

libB/CMakeLists.txt

add_library(libB SHARED
    src.cpp)

libA/CMakeLists.txt

add_library(libA SHARED
    foo.cpp)
target_link_libraries(libA libB)

项目/CMakeLists.txt:

add_subdirectory(libA)
add_subdirectory(libB)
add_executable(App main.cpp)
target_include_directories(App PUBLIC libB)
target_link_libraries(App libA libB)

但我得到一个错误 src.cpp:致命错误:foo.h:没有这样的文件或目录

【问题讨论】:

【参考方案1】:

在顶层:

cmake_minimum_required(VERSION 3.21)
project(project)

option(BUILD_SHARED_LIBS "Build shared libs instead of static" ON)

add_subdirectory(libA)
add_subdirectory(libB)

add_executable(App main.cpp)
target_link_libraries(App PRIVATE libA libB)

在 libA 中:

add_library(libA src.cpp)

# Use PUBLIC below if libA exposes libB's types in its API.
target_link_libraries(libA PRIVATE libB)

在 libB 中:

add_library(libB foo.cpp)
target_include_directories(
  libB PUBLIC "$<BUILD_INTERFACE:$CMAKE_CURRENT_SOURCE_DIR>"
)

PUBLICINTERFACE 目标上的属性 propagate 到它们的链接对象。因此,当我们在libB 上设置包含目录时,任何链接到它的目标都会将其源目录添加到它包含路径。

我们用$&lt;BUILD_INTERFACE:...&gt; 保护包含目录,这样如果您曾经在某个地方install() 库,它可能会在另一个CMake 构建中重复使用,它不会记住您特定文件系统的详细信息。

【讨论】:

为什么使用 target_include_directories( libB PUBLIC "$" ) 而不是 target_include_directories( libB PUBLIC "$CMAKE_CURRENT_SOURCE_DIR") ? 当您为其他消费者导出 CMake 目标时,它也会保存其所有属性。 $&lt;BUILD_INTERFACE&gt; 阻止其内容。如果我们不这样做,那么导出的目标中就会有一个类似/home/alex/projects/lib/include 的路径,这在其他人的机器上是不合适的。

以上是关于CMake 包含路径 - 依赖于外部库的库的主要内容,如果未能解决你的问题,请参考以下文章

在 CMake 中获取包含库的包含路径列表

对外部库的编译器依赖路径的组织

CMake 使 add_library 依赖于 ExternalProject_Add

共享需要外部库的 Visual Studio 项目

更改静态库的包含路径

你如何告诉 CMake 静态链接到使用 find_package 找到的包中的库?