在 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.cpp
src/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(SOURCES
src/Hello.cpp
src/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(target
PRIVATE
${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 build
cd 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.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/root/CmakeTest/build'
make -f CMakeFiles/hello_headers.dir/build.make CMakeFiles/hello_headers.dir/depend
make[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/build
make[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_headers
make[2]: Leaving directory '/root/CmakeTest/build'
[100%] Built target hello_headers
make[1]: Leaving directory '/root/CmakeTest/build'
/usr/bin/cmake -E cmake_progress_start /root/CmakeTest/build/CMakeFiles 0