参考: 基于VSCode和CMake实现C/C++开发 | Linux篇
语法
基本语法格式:指令(arg1 arg2 …)
- 参数使用括弧括起来
- 参数之间使用空格或者分号分开
指令是大小写无关的,参数和变量是大小写相关的
set(HELLO hello.cpp)
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_minimum_required(VERSION 2.8.3)
- project :用来定义工程名称,并可指定工程支持的语言
project(HELLOWORLD C)
set(SRC sayhello.cpp hello.cpp)
- include_directories :向工程添加多个特定的头文件搜索路径->相当于指定g++编译器的-I参数
include_directories(usr/include/myincludefolder ./include)
- link_directories:向工程添加多个特定的库文件搜索路径->相当于指定g++编译器的-L参数
link_directories(usr/lib/mylibfolder ./lib)
add_library(hello SHARED ${SRC})
- add_compile_options :添加编译参数
add_compile_options(-Wall -std=c++11 -O2)
add_executable(main main.cpp)
- target_link_libraries:为target添加需要链接的共享库->相当于指定g++编译器的-l 参数
target_link_libraries(main hello)
- add_subdirectory:向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置
add_subdirectory(src)
- aux_source_directory :发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令被用来临时自动构建源文件列表
aux_source_directory(. SRC)
add_executable(main ${SRC})
CMake常用变量
- CMAKE_C_FLAGS :gcc编译选项
- CMAKE_CXX_FLAGS:g++编译选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- CMAKE_BUILD_TYPE:编译类型(Debug,Release)
set(CMAKE_BUILD_TYPE Debug)
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编译工程
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):这种方式不推荐使用 内部构建会在同级目录下产生一大堆中间文件,和工程源文件放在一起会显得杂乱无章
cmake .
make
2、外部构建(out-of-source build) :这种方式推荐使用 该方式将编译输出文件和源文件放在不同目录中
mkdir build
cd build
cmake ..
make
实例展示
实例一
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/hello$ tree
.
├── hello
└── hello.cpp
hello.cpp内容为:
#include<iostream>
using 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)
接下来我们在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)
include_directories(include)
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
|