我读过和看过一些关于CMake的视频,每个人都建议不要使用include_directories
,而应该使用target_include_directories
。但我不明白这个建议背后的真正原因是什么?
发布于 2021-12-27 12:16:08
有三个主要原因
的一部分。
限制包含dirs的范围
目标是将包含目录的可见性降到最低。如果在执行add_subdirectory
之后使用include_directories
,则从子you或子you的后代创建的所有目标都会看到与include_directories
一起添加的包含目录。
subdir/CMakeLists.txt
add_library(subdir_lib ...)
...
CMakeLists.txt
add_subdirectory(subdir)
...
include_directories(some_include_dir)
vs
include_directories(some_include_dir)
...
add_subdirectory(subdir)
两个CMakeLists.txt
文件之间的区别可能很难看出,特别是当两个命令之间有大量的逻辑时;这使得这种逻辑很难维护。
重组的“遗传”/Ease
使用target_include_directories
还可以更容易地提供将库与所需的包含dirs链接起来的目标。通过include_directories
添加的目录不能自动链接目标,但是使用target_include_directories(... PUBLIC ...)
很容易实现这一点。include_directories
不会处理从包含命令的子目录中创建的目录中创建的目标。
示例项目
A
B
B
需要库A
;B
的公共标题不使用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
,您需要注意CMakeLists.txt
中add_subdirectory
的顺序
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
。您所需要做的就是在文件系统上重命名dir,并在add_subdirectory(A)
中用add_subdirectory(AB)
替换CMakeLists.txt
。
或者,假设您希望使用库B
和C
作为更大项目的一部分:如果使用target_include_directories
而不是include_directories
,只需使用add_subdirectory
添加包含toplevel CMakeLists.txt
的目录,只需使用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 ...)
https://stackoverflow.com/questions/70494485
复制相似问题