CMake笔记之PROJECT_SOURCE_DIR、CMAKE_SOURCE_DIR、CMAKE_CURRENT_BINARY_DIR对比
—— 杭州 2024-03-19 夜
code review!
文章目录
- CMake笔记之PROJECT_SOURCE_DIR、CMAKE_SOURCE_DIR、CMAKE_CURRENT_BINARY_DIR对比
- 1.三者区别
- 2.具体示例说明
- 3.CMAKE_SOURCE_DIR 和 PROJECT_SOURCE_DIR的区别
1.三者区别
下面是一个表格,简要总结了 CMAKE_CURRENT_BINARY_DIR
、CMAKE_SOURCE_DIR
和 PROJECT_SOURCE_DIR
的区别:
变量 | 描述 |
---|---|
CMAKE_CURRENT_BINARY_DIR | 指向当前处理的 CMakeLists.txt 文件对应的构建目录。对于多级目录结构的项目,每个目录的这个变量指向的都是它自己的构建目录。 |
CMAKE_SOURCE_DIR | 指向最顶层 CMakeLists.txt 文件的源码目录,即整个项目的根源码目录。在所有的 CMakeLists.txt 文件中保持不变,无论它们在源码树的何处。 |
PROJECT_SOURCE_DIR | 指向最近通过 project() 命令定义的项目的根源码目录。如果是单个项目,则与 CMAKE_SOURCE_DIR 相同。在使用 add_subdirectory 命令嵌套项目时,对于每个子项目来说,它指向的是各自的根源码目录。 |
这些变量在不同的 CMakeLists.txt 文件中的行为会有所不同,特别是在含有多个子项目的情况下。例如,在一个包含子项目的构建系统中:
root_project/ # 根项目目录
|- CMakeLists.txt # 根项目 CMakeLists.txt, 包含 project(RootProject)
|- sub_project/ # 子项目目录|- CMakeLists.txt # 子项目 CMakeLists.txt, 包含 project(SubProject)
假设我们在 root_project/build
目录中执行构建命令,每个 CMakeLists.txt 文件中变量的值将如下:
文件 | CMAKE_CURRENT_BINARY_DIR | CMAKE_SOURCE_DIR | PROJECT_SOURCE_DIR |
---|---|---|---|
root_project/CMakeLists.txt | root_project/build | root_project | root_project |
sub_project/CMakeLists.txt | root_project/build/sub_project | root_project | sub_project |
在这个例子中,CMAKE_SOURCE_DIR
在所有的 CMakeLists.txt 文件中都是相同的,因为它指向最顶层 CMakeLists.txt 文件的目录。而 PROJECT_SOURCE_DIR
在子项目的 CMakeLists.txt 中指向的是子项目的源码目录,因为 project()
命令在那里被调用。而 CMAKE_CURRENT_BINARY_DIR
则对应于每个 CMakeLists.txt 文件的当前构建目录。
2.具体示例说明
让我们假设你有一个项目的文件组织结构如下所示:
/my_project
|-- CMakeLists.txt
|-- src
| |-- CMakeLists.txt
| |-- main.cpp
|-- lib|-- utils|-- CMakeLists.txt|-- util.cpp
在这个结构中:
/my_project
是项目的根目录。/my_project/src
包含项目的主要源文件。/my_project/lib/utils
包含项目的一些实用工具函数。
现在,我们将看看如何在不同的 CMakeLists.txt
文件中使用这些变量:
- 在
/my_project/CMakeLists.txt
(顶层 CMakeLists.txt):
cmake_minimum_required(VERSION 3.0)
project(MyProject)add_subdirectory(src)
add_subdirectory(lib/utils)# CMAKE_SOURCE_DIR 在这里指向 /my_project
# PROJECT_SOURCE_DIR 在这里指向 /my_project
# CMAKE_CURRENT_BINARY_DIR 在这里指向 /my_project/build (假设在 /my_project/build 目录中运行 cmake ..)
- 在
/my_project/src/CMakeLists.txt
:
# 这个文件是 src 目录的 CMakeLists.txt# CMAKE_SOURCE_DIR 这里仍然指向 /my_project
# PROJECT_SOURCE_DIR 这里仍然指向 /my_project
# CMAKE_CURRENT_BINARY_DIR 在这里指向 /my_project/build/src
# (假设在 /my_project/build 目录中运行 cmake ..)
- 在
/my_project/lib/utils/CMakeLists.txt
:
# 这个文件是 lib/utils 目录的 CMakeLists.txt# CMAKE_SOURCE_DIR 这里仍然指向 /my_project
# PROJECT_SOURCE_DIR 这里仍然指向 /my_project
# CMAKE_CURRENT_BINARY_DIR 在这里指向 /my_project/build/lib/utils
# (假设在 /my_project/build 目录中运行 cmake ..)
如果你在 /my_project/build
目录中运行 cmake ..
命令来构建你的项目,CMake 会创建相应的构建文件在该 build
目录中。在这种情况下:
CMAKE_CURRENT_BINARY_DIR
对于每个CMakeLists.txt
文件,都指向其对应的在构建目录树中的位置,而不是源码目录树。CMAKE_SOURCE_DIR
和PROJECT_SOURCE_DIR
在所有的CMakeLists.txt
文件中始终指向项目的顶层源码目录/my_project
。
这样,无论你在项目的哪个子目录中工作,你都可以使用这些变量来引用项目中的其他文件或目录,而不必担心相对路径的问题。
3.CMAKE_SOURCE_DIR 和 PROJECT_SOURCE_DIR的区别
在 CMake 中,CMAKE_SOURCE_DIR
和 PROJECT_SOURCE_DIR
确实有细微的区别,尤其是在涉及多项目(例如,使用add_subdirectory
,或者在超级构建中)的情况下。这里是它们的具体区别:
-
CMAKE_SOURCE_DIR
指向最顶层 CMakeLists.txt 文件的目录,这个目录是整个构建树的根源码目录。不管你在哪个子目录中调用CMAKE_SOURCE_DIR
,它始终指向顶层 CMakeLists.txt 所在的目录。在单项目构建中,CMAKE_SOURCE_DIR
和PROJECT_SOURCE_DIR
是相同的。 -
PROJECT_SOURCE_DIR
指向最近一次调用project()
命令的目录。如果你在一个子目录中有另一个project()
命令(表示该子目录是一个独立的项目),那么在该子目录及其下级目录中,PROJECT_SOURCE_DIR
会指向这个子项目的根源码目录,而不是整个构建树的根源码目录。
这里是一个例子来说明这一点:
假设你有以下目录结构:
/my_super_project
|-- CMakeLists.txt # contains 'project(SuperProject)'
|-- subproject_a
| |-- CMakeLists.txt # contains 'project(ProjectA)'
|-- subproject_b|-- CMakeLists.txt # does not contain 'project()' command
这里是每个目录中这些变量的值:
-
在
/my_super_project/CMakeLists.txt
中:CMAKE_SOURCE_DIR
=/my_super_project
PROJECT_SOURCE_DIR
=/my_super_project
-
在
/my_super_project/subproject_a/CMakeLists.txt
中:CMAKE_SOURCE_DIR
=/my_super_project
PROJECT_SOURCE_DIR
=/my_super_project/subproject_a
-
在
/my_super_project/subproject_b/CMakeLists.txt
中(没有project()
命令):CMAKE_SOURCE_DIR
=/my_super_project
PROJECT_SOURCE_DIR
=/my_super_project
(因为subproject_b
没有自己的project()
命令,所以它继承了顶层项目的PROJECT_SOURCE_DIR
)
正因为这样的行为,PROJECT_SOURCE_DIR
在处理复杂项目结构时非常有用,尤其是当你需要引用当前项目的根源码目录时。这样,即使在多个子项目的设置中,每个子项目也可以有自己的根源码目录。