【发布时间】:2021-12-27 10:48:50
【问题描述】:
我已经阅读和观看了一些关于 CMake 的视频,大家建议不要使用include_directories,而是使用target_include_directories。但我不明白这个建议背后的真正原因是什么?
【问题讨论】:
标签: cmake
我已经阅读和观看了一些关于 CMake 的视频,大家建议不要使用include_directories,而是使用target_include_directories。但我不明白这个建议背后的真正原因是什么?
【问题讨论】:
标签: cmake
有3个主要原因
目标是将包含目录的可见性降至最低。如果在执行include_directories 之后使用add_subdirectory,则从子目录或子目录的后代创建的所有目标都可以看到使用include_directories 添加的包含目录。
subdir/CMakeLists.txt
add_library(subdir_lib ...)
...
CMakeLists.txt
add_subdirectory(subdir)
...
include_directories(some_include_dir)
对
include_directories(some_include_dir)
...
add_subdirectory(subdir)
这两个CMakeLists.txt 文件之间的区别可能很难看出,尤其是如果这两个命令之间有很多逻辑;这使得这种逻辑难以维护。
使用target_include_directories 还可以更轻松地提供将库与所需的包含目录链接的目标。通过include_directories 添加的包含目录不能用于自动链接目标,但使用target_include_directories(... PUBLIC ...) 这很容易实现。 include_directories 不适用于从不在包含该命令的子目录中创建的目录创建的目标。
A
B 需要库A; B 的公共标头使用公共包括来自 A
C 不使用A 或B
文件系统:
.
|---A
| |---include
| | |---- A
| | |---- a.hpp
| |
| |--- a.cpp
|
|---B
| |---include
| | |---- B
| | |---- b.hpp
| |
| |--- b.cpp
|
|---C
| |---include
| | |---- C
| | |---- c.hpp
| |
| |--- c.cpp
|
|---CMakeLists.txt
现在您需要授予B,而不是C 访问A 的标头。使用target_link_libraries 这很简单,但是使用include_directories 你需要注意add_subdirectorys 在CMakeLists.txt 中的顺序
CMakeList.txt
add_subdirectory(A)
add_subdirectory(B)
add_subdirectory(C)
A/CMakeLists.txt
add_library(A ...)
target_include_directories(A PUBLIC include)
B/CMakeLists.txt
add_library(B ...)
target_include_directories(B PUBLIC include)
target_link_libraries(B PUBLIC A) # quite simple to provide access to A's include dir to linking libs using PUBLIC here, if required
C/CMakeLists.txt
add_library(C ...)
target_include_directories(C PUBLIC include)
现在假设您要将目录A 重命名为AB。您需要做的就是重命名文件系统上的目录并将CMakeLists.txt 中的add_subdirectory(A) 替换为add_subdirectory(AB)。
或者假设您想将库B 和C 用作更大项目的一部分:如果您使用target_include_directories 而不是include_directories,您需要做的就是添加包含顶级@ 的目录987654361@ 使用 add_subdirectory 并且您需要做的就是使用 target_link_libraries(NewTarget PRIVATE B C) 来访问所有必需的包含目录,而不是这样做
add_subdirectory(OriginalProject)
include_directories(OriginalProject/B/include)
include_directories(OriginalProject/C/include)
include_directories(OriginalProject/A/include) # did you remember this one is needed by B?
add_executable(NewTarget ...)
【讨论】: