在 hello-cmake 中,我们只用了一个单文件 main.cpp,现在开始用多文件学习编译。
一、文件树
├── CMakeLists.txt├── include│ └── Hello.h└── src├── Hello.cpp└── main.cpp
以下是上述文件树中的文件具体内容
1.1 Hello.h
/* 声明了Hello类,Hello的方法是print() */#ifndef __HELLO_H__#define __HELLO_H__class Hello {public:void print();};#endif
1.2 Hello.cpp
/* 实现了Hello::print() */#include <iostream>#include "Hello.h"void Hello::print(){std::cout << "Hello Headers!" << std::endl;}
1.3 main.cpp
#include "Hello.h"int main(int argc, char *argv[]){Hello hellObj;hellObj.print();return 0;}
1.4 CMakeLists.txt
cmake_minimum_required(VERSION 3.5) # 最低CMake版本project(hello_headers) # 工程名set(SOURCES # 创建一个变量,名为SOURCE,它包含所有的cpp文件src/Hello.cppsrc/main.cpp)# 指定源文件add_executable(hello_headers ${SOURCES}) # 用所有的源文件生成一个可执行文件,因为这里# 定义了 SOURCE 变量,所以就不需要罗列文件##等价命令 add_executable(hello_headers src/Hello.cpp src/main.cpp)# 指定头文件target_include_directories(hello_headers # 设置这个可执行文件hello_headers需要包含的PRIVATE # 库的路径${PROJECT_SOURCE_DIR}/include)
上述命令中的指令解释如下:
PROJECT_SOURCE_DIR:工程顶层目录PROJECT_BINARY_DIR:编译目录PRIVATE:指定库的范围
二、CMake解析
2.1 各种可用变量
CMake 语法指定了许多变量,可用于帮助您在项目或源代码树中找到有用的目录。 其中一些包括:
| Variable | Info |
|---|---|
| CMAKE_SOURCE_DIR | 根源代码目录,工程顶层目录。暂认为就是 PROJECT_SOURCE_DIR |
| CMAKE_CURRENT_SOURCE_DIR | 当前处理的 CMakeLists.txt 所在的路径 |
| PROJECT_SOURCE_DIR | 工程顶层目录 |
| CMAKE_BINARY_DIR | 运行 cmake 的目录。外部构建时就是build目录 |
| CMAKE_CURRENT_BINARY_DIR | The build directory you are currently in.当前所在 build 目录 |
| PROJECT_BINARY_DIR | 暂认为就是 CMAKE_BINARY_DIR |
想仔细体会一下,可以在 CMakeLists.txt 中,利用 message() 命令输出一下这些变量。
另外,这些变量不仅可以在 CMakeLists.txt 中使用,同样可以在 源代码.cpp 中使用。
2.2 源文件变量(不建议!)
创建一个包含源文件的变量,以便于将其轻松添加到多个命令中,例如 add_executable() 函数。
set(SOURCESsrc/Hello.cppsrc/main.cpp)add_executable(${PROJECT_NAME} ${SOURCES})
在 SOURCES 变量中设置特定文件名的另一种方法是使用 GLOB 命令使用通配符模式匹配来查找文件。file(GLOB SOURCES "src/*.cpp")使用*这个通配符,表示所有.cpp结尾的文件都会包含到这个SOURCES变量。
对于 modern CMake,不建议对源文件使用变量。 不建议使用 glob。
相反,通常直接在 add_xxx 函数中声明源文件。
这对于 glob 命令尤其重要,如果添加新的源文件,这些命令可能不会始终为您显示正确的结果。在 CMake 中指定源文件的最佳方法是明确列出它们。
2.3 包含目录
当您有其他需要包含的文件夹(文件夹里有头文件)时,可以使用以下命令使编译器知道它们: **target_include_directories()**。 编译此目标时,这将使用 -I 标志将这些目录添加到编译器中,例如-I /目录/路径
target_include_directories(targetPRIVATE${PROJECT_SOURCE_DIR}/include)
PRIVATE 标识符指定包含的范围。 这对库很重要,将在下一个示例中进行说明。 有关该功能的更多详细信息,请参见以下链接:https://cmake.org/cmake/help/v3.0/command/target_include_directories.html
2.4 详细输出
在前面的示例中,运行 make 命令时,输出仅显示构建状态。 要查看用于调试目的的完整输出,可以在运行 make 时添加 VERBOSE=1标志。
下面的代码是使用 VERBOSE 的命令
mkdir buildcd build/cmake ..make VERBOSE=1
没有
VERBOSE:make[ 33%] Building CXX object CMakeFiles/hello_headers.dir/src/Hello.cpp.o[ 66%] Building CXX object CMakeFiles/hello_headers.dir/src/main.cpp.o[100%] Linking CXX executable hello_headers[100%] Built target hello_headers
有
VERBOSE:make VERBOSE=1/usr/bin/cmake -S/root/CmakeTest -B/root/CmakeTest/build --check-build-system CMakeFiles/Makefile.cmake 0/usr/bin/cmake -E cmake_progress_start /root/CmakeTest/build/CMakeFiles /root/CmakeTest/build//CMakeFiles/progress.marksmake -f CMakeFiles/Makefile2 allmake[1]: Entering directory '/root/CmakeTest/build'make -f CMakeFiles/hello_headers.dir/build.make CMakeFiles/hello_headers.dir/dependmake[2]: Entering directory '/root/CmakeTest/build'cd /root/CmakeTest/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /root/CmakeTest /root/CmakeTest /root/CmakeTest/build /root/CmakeTest/build /root/CmakeTest/build/CMakeFiles/hello_headers.dir/DependInfo.cmake --color=make[2]: Leaving directory '/root/CmakeTest/build'make -f CMakeFiles/hello_headers.dir/build.make CMakeFiles/hello_headers.dir/buildmake[2]: Entering directory '/root/CmakeTest/build'[ 33%] Building CXX object CMakeFiles/hello_headers.dir/src/Hello.cpp.o/usr/bin/c++ -I/root/CmakeTest/include -MD -MT CMakeFiles/hello_headers.dir/src/Hello.cpp.o -MF CMakeFiles/hello_headers.dir/src/Hello.cpp.o.d -o CMakeFiles/hello_headers.dir/src/Hello.cpp.o -c /root/CmakeTest/src/Hello.cpp[ 66%] Building CXX object CMakeFiles/hello_headers.dir/src/main.cpp.o/usr/bin/c++ -I/root/CmakeTest/include -MD -MT CMakeFiles/hello_headers.dir/src/main.cpp.o -MF CMakeFiles/hello_headers.dir/src/main.cpp.o.d -o CMakeFiles/hello_headers.dir/src/main.cpp.o -c /root/CmakeTest/src/main.cpp[100%] Linking CXX executable hello_headers/usr/bin/cmake -E cmake_link_script CMakeFiles/hello_headers.dir/link.txt --verbose=1/usr/bin/c++ -rdynamic CMakeFiles/hello_headers.dir/src/Hello.cpp.o CMakeFiles/hello_headers.dir/src/main.cpp.o -o hello_headersmake[2]: Leaving directory '/root/CmakeTest/build'[100%] Built target hello_headersmake[1]: Leaving directory '/root/CmakeTest/build'/usr/bin/cmake -E cmake_progress_start /root/CmakeTest/build/CMakeFiles 0
