目录
- 语法
- 一些重要指令
- CMake常用变量
- CMake编译工程
- 编译流程
- 两种构建方式
- 实例展示
参考:
基于VSCode和CMake实现C/C++开发 | Linux篇
基本语法格式:指令(arg1 arg2 …)
- 参数使用括弧括起来
- 参数之间使用空格或者分号分开
指令是大小写无关的,参数和变量是大小写相关的
set(HELLO hello.cpp) # 将hello.cpp 作为一个名为 HELLO 的变量
add_executable(hello main.cpp hello.cpp)
ADD_EXECUTABLE(hello main.cpp ${HELLO})
变量使用 方 式 取 值 , 但 是 在 I F 控 制 语 句 里 面 直 接 使 用 变 量 名 , 例 如 : ‘ I F ( H E L L O ) ‘ 而 不 是 ‘ I F ( {}方式取值,但是在IF控制语句里面直接使用变量名,例如:`IF(HELLO)`而不是`IF( 方式取值,但是在IF控制语句里面直接使用变量名,例如:‘IF(HELLO)‘而不是‘IF({HELLO})`
一些重要指令- cmake_minimum_required : 用来指定CMake的最小版本要求
# CMake最小版本要求为2.8.3 cmake_minimum_required(VERSION 2.8.3)
- project :用来定义工程名称,并可指定工程支持的语言
project(HELLOWORLD C)
- set :显示的定义变量
# 定义SRC变量,其值为sayhello.cpp hello.cpp set(SRC sayhello.cpp hello.cpp)
- include_directories :向工程添加多个特定的头文件搜索路径->相当于指定g++编译器的-I参数
# 将usr/include/myincludefolder 和 ./include 添加到头文件搜索路径 include_directories(usr/include/myincludefolder ./include)
- link_directories:向工程添加多个特定的库文件搜索路径->相当于指定g++编译器的-L参数
# 将usr/lib/mylibfolder 和 ./lib 添加到库文件搜索路径 link_directories(usr/lib/mylibfolder ./lib)
- add_library :生成库文件
# 通过变量 SRC 生成 libhello.so 共享库
add_library(hello SHARED ${SRC})
- add_compile_options :添加编译参数
# 添加编译参数 -Wall -std=c++11 -O2 add_compile_options(-Wall -std=c++11 -O2)
- add_executable:生成可执行文件
# 编译main.cpp生成可执行文件main add_executable(main main.cpp)
- target_link_libraries:为target添加需要链接的共享库->相当于指定g++编译器的-l 参数
# 将hello动态库链接到可执行文件main上 target_link_libraries(main hello)
- add_subdirectory:向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置
# 添加src子目录,src中需要有一个CMakeLists.txt add_subdirectory(src)
- aux_source_directory :发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令被用来临时自动构建源文件列表
# 定义SRC变量,其值为当前目录下所有的源代码文件
aux_source_directory(. SRC)
# 编译SRC变量所代表的源代码文件,生成main可执行文件
add_executable(main ${SRC})
CMake常用变量
- CMAKE_C_FLAGS :gcc编译选项
- CMAKE_CXX_FLAGS:g++编译选项
# 在编译选项后追加-std=c++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- CMAKE_BUILD_TYPE:编译类型(Debug,Release)
# 设定编译类型为debug,调试时需要选择debug set(CMAKE_BUILD_TYPE Debug) # 设定编译类型为release,发布时需要选择release set(CMAKE_BUILD_TYPE Release)
- CMAKE_BINARY_DIR、PROJECT_BINARY_DIR 、_BINARY_DIR
这三个变量指代的内容是一致的
如果是 in source build,指的是工程顶层目录
如果是out-of-source编译,指的是工程编译发生的目录
- CMAKE_SOURCE_DIR、PROJECT_SOURCE_DIR、_SOURCE_DIR
这三个变量指代内容一致,不管采用何种编译方式,都是工程顶层目录
在in source build时,与CMAKE_BINARY_DIR等变量一致
- CMAKE_C_COMPILER:指定C编译器
- CMAKE_CXX_COMPILER:指定C++编译器
- EXECUTABLE_OUTPUT_PATH:可执行文件输出的存放路径
- LIBRARY_OUTPUT_PATH:库文件输出的存放路径
CMake目录结构:项目主目录存在一个CMakeLists.txt文件
一般有两种方式设置编译规则:
1、包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeList.txt通过add_subdirectory添加子目录即可
2、包含源文件的子文件夹未包含CMakeLists.txt文件,子目录编译规则体现在主目录的CMakeLists.txt中
在linux下使用CMake构建C/C++工程的流程如下:
- 手写CMakeLists.txt文件
- 执行命令cmake PATH生成Makefile(PATH是顶层CMakeLists.txt所在的目录)
- 执行命令make进行编译
1、内部构建(in-source build):这种方式不推荐使用
内部构建会在同级目录下产生一大堆中间文件,和工程源文件放在一起会显得杂乱无章
# 内部构建 # 在当前目录下,编译本目录的CMakeLists.txt,生成Makefile文件和其他文件 cmake . # 执行make命令,生成target make
2、外部构建(out-of-source build) :这种方式推荐使用
该方式将编译输出文件和源文件放在不同目录中
# 外部构建 # 1、在当前目录下,创建build文件夹 mkdir build # 2、进入build文件夹 cd build # 3、编译上级目录的CMakeList.txt ,生成Makefile和其他文件 cmake .. # 4、执行make,生成目标文件 make实例展示
实例一
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/hello$ tree . ├── hello └── hello.cpp
hello.cpp内容为:
#includeusing namespace std; int main() { cout << "hello world!" << endl; return 0; }
我们进入目录,然后输入:
code . 这样就能打开vscode了
我们要给这个最简单的cpp程序写一个CMakeLists.txt
CMakeLists.txt一般处于项目的顶层目录,此处就在文件夹下了
一般来说,在vscode中写cmakelists的话会有只能提示的,如果你装了插件的话
# 指定最低版本要求 cmake_minimum_required(VERSION 3.0) # 指定项目名称 project(HELLO) # 指定生成的可执行文件的名字 源文件 add_executable(hello_cmake hello.cpp) ## 此时等价于 g++ hello.cpp -o hello_cmake
接下来我们在vscode的终端里面进行外部构建并编译
我们在终端下使用tree命令看看文件结构:
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/hello$ tree . ├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.16.3 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── a.out │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── tmp │ │ │ └── CompilerIdCXX │ │ │ ├── a.out │ │ │ ├── CMakeCXXCompilerId.cpp │ │ │ └── tmp │ │ ├── cmake.check_cache │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── CMakeOutput.log │ │ ├── CMakeTmp │ │ ├── hello_cmake.dir │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── CXX.includecache │ │ │ ├── DependInfo.cmake │ │ │ ├── depend.internal │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── hello.cpp.o │ │ │ ├── link.txt │ │ │ └── progress.make │ │ ├── Makefile2 │ │ ├── Makefile.cmake │ │ ├── progress.marks │ │ └── TargetDirectories.txt │ ├── cmake_install.cmake │ ├── hello_cmake │ └── Makefile ├── CMakeLists.txt ├── hello └── hello.cpp
此时发现可执行文件是在build文件夹下的
实例二
此处用到的实例请参考:
gcc 编译器使用指南
此时工程结构如下:
. ├── include │ └── swap.h ├── main.cpp ├── sharemain ├── src │ ├── libswap.a │ ├── libswap.so │ ├── swap.cpp │ └── swap.o └── staticmain
然后写cmakelists.txt
cmake_minimum_required(VERSION 3.0) project(SWAP) # 与 -Iinclude 命令对应 include_directories(include) # 此命令相当于 g++ main.cpp src/swap.cpp -Iinclude -o main_cmake add_executable(main_cmake main.cpp src/swap.cpp)
然后执行cmake、make:
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST$ mkdir build dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST$ cd build/ dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST/build$ cmake .. -- The C compiler identification is GNU 9.3.0 -- The CXX compiler identification is GNU 9.3.0 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /home/dyy/Desktop/GCCTEST/build dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST/build$ make Scanning dependencies of target main_cmake [ 33%] Building CXX object CMakeFiles/main_cmake.dir/main.cpp.o [ 66%] Building CXX object CMakeFiles/main_cmake.dir/src/swap.cpp.o [100%] linking CXX executable main_cmake [100%] Built target main_cmake dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST/build$ ./main_cmake before 10 20 after 20 10



