CMake教程
CMake教程
CMakeLists.txt
| |
CMake 2.x 一般方便删除多余文件,新建Build文件夹用来生成文件
| |
CMake 3.x
| |
基础知识
简单项目
| |
- 指定了项目所需的CMake的最低版本
- 强制设置将CMake行为匹配到对应版本
1# cmake_minimum_required(VERSION 3.10)指定版本 3.10
| |
projectName:项目名称
LANGUAGES:项目编程语言:C、CXX、JAVA、…多种语言空格分开;默认C和CXX3.0版本之前不支持
LANGUAGES关键字,project(hello CXX)
1# project(hello)hello项目
可执行文件
| |
为一组源文件创建一个可执行文件
1# add_executable(test main.cpp)为main.cpp构建test可执行文件
定义库
| |
STATIC | SHARED | MODULE:静态库,动态库,动态加载库
cmake -DBUILD_SHARED_LIBS=YES /path/to/source:-D选项设置是否构建为动态库,否则为静态库。
set(BUILD_SHARED_LIBS YES):要在add_library()命令之前设置,(灵活性较差)
1add_library(collector src1.cpp)
目标链接
考虑A库依赖于B库,因此将A链接到B
| |
小总结 1
目标名称与项目名称无关,最好将项目名称和可执行文件名称分开
命名库的目标时,不要用lib作为名称的开头或结尾。lib会自动成为前缀
尽量避免直接将库指定 STATIC 或 SHARED
目标在调用 target_link_libraries() 时需要指定 PRIVATE 、 PUBLIC 和/或 INTERFACE
变量
基本变量
| |
将所有变量都作为字符串处理,给定多个值,这些值将用 分号连接在一起。可以使用转义字符表示引号
\"
1 2 3 4 5set(myVar a b c) # myVar = "a;b;c" set(myVar a;b;c) # myVar = "a;b;c" set(myVar "a b c") # myVar = "a b c" set(myVar a b;c) # myVar = "a;b;c" set(myVar a "b c") # myVar = "a;b c"
环境变量
| |
只会影响当前的CMake实例,很少用到
缓存变量
| |
布尔缓存变量使用optio()代替set()
| |
调试变量和诊断
| |
处理字符串
查找和替换操作、正则表达式匹配、大小写转换、删除空格和其他常见字符串操作
查找
| |
1 2 3 4 5 6 7et(longStr abcdefabcdef) set(shortBit def) string(FIND ${longStr} ${shortBit} fwdIndex) string(FIND ${longStr} ${shortBit} revIndex REVERSE) message("fwdIndex = ${fwdIndex}, revIndex = ${revIndex}") # 输出 fwdIndex = 3, revIndex = 9 # 代表子字符串被找到,第一次找到的时候索引为3;最后一次找到的索引为9
替换
| |
将使用 replaceWith 替换输入字符串中每个 matchString ,并将结果存储在 outVar
正则表达式
| |
列表
| |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18set(myList a b c) # Creates the list "a;b;c" list(LENGTH myList len) message("length = ${len}") list(GET myList 2 1 letters) message("letters = ${letters}") list(APPEND myList d e f) message("myList (first) = ${myList}") list(INSERT myList 2 X Y Z) message("myList (second) = ${myList}") list(FIND myList d index) message("index = ${index}") # 输出 length = 3 letters = c;b myList (first) = a;b;c;d;e;f myList (second) = a;b;X;Y;Z;c;d;e;f index = 6
数学表达式
| |
第一个参数必须使用关键字 EXPR ,而 mathExpr 定义要计算的表达式,结果将存储在 outVar 中
1 2 3 4 5 6set(x 3) set(y 7) math(EXPR z "(${x}+${y}) / 2") message("result = ${z}") # 输出 result = 5
控制流
if()
| |
循环
| |
子目录
add_subdirectory()
| |
允许项目将另一个目录引入到构建中
CMAKE_SOURCE_DIR:源的最顶层目录(最顶层CMakeLists.txt所在位置)
CMAKE_BINARY_DIR:构建的最顶层目录 就是build
CMAKE_CURRENT_SOURCE_DIR:当前处理的CMakeLists.txt文件的目录
CMAKE_CURRENT_BINARY_DIR:当前处理的CMakeLists.txt文件对应的构建目录
include()
参考阅读
CMake的链接选项:PRIVATE,INTERFACE,PUBLIC - 知乎 (zhihu.com)
An Introduction to Modern CMake
vscode 插件 : clangd
Make命令
python版本的makefile: SCons
make规则:“目标"是必需的,不可省略;“前置条件"和"命令"都是可选的,但是两者之中必须至少存在一个。
每条规则就明确两件事:构建目标的前置条件是什么,以及如何构建。
| |
文本文件的编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32// functions.h #ifndef _FUNCTIONS_H_ #define _FUNCTIONS_H_ void printhello(); int factorial(int n); #endif // factorial.cpp #include "functions.h" int factorial(int n){ if(n == 1) return 1; else return n * factorial(n - 1); } //printhello.cpp #include <iostream> #include "functions.h" using namespace std; void printhello(){ int i; cout << "Hello world!" << endl; } //main.cpp #include <iostream> #include "functions.h" using namespace std; int main(){ printhello(); cout << "This is main: " << endl; cout << "This factorial of 5 is: " << factorial(5) << endl; return 0; }正常编译
1 2g++ *.cpp -o hello ./hello写
makefile文件,管理工程,实现自动化编译(.o)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61# VERDION 1 hello: main.cpp printhello.cpp factorial.cpp g++ -o hello main.cpp printhello.cpp factorial.cpp # VERDION 2 CXX = g++ TARGET = hello OBJ = main.o printhello.o factorial.o $(TARGET): $(OBJ) $(CXX) -o $(TARGET) $(OBJ) main.o: main.cpp $(CXX) -c main.cpp printhello.o: printhello.cpp $(CXX) -c printhello.cpp factorial.o: factorial.cpp $(CXX) -c factorial.cpp # VERDION 3 CXX = g++ TARGET = hello OBJ = main.o printhello.o factorial.o CXXFLAGS = -c -Wall # Wall 打开警告信息 $(TARGET): $(OBJ) $(CXX) -o $@ $^ %.o: %.cpp $(CXX) $(CXXFLAGS) $< -o $@ .PHONY: clean clean: rm -f *.o $(TARGET) # VERDION 4 CXX = g++ TARGET = hello SRC = $(wildcard *.cpp) OBJ = $(patsubst %.cpp, %.o, $(SRC)) CXXFLAGS = -c -Wall $(TARGET): $(OBJ) $(CXX) -o $@ $^ %.o: %.cpp $(CXX) $(CXXFLAGS) $< -o $@ # 想看某些宏的时候在make加上-E即可 $(CXX) $(CXXFLAGS) -E $< | \ grep -ve '^#' | \ clang-format - > $(basename $@).i .PHONY: clean clean: rm -f *.o $(TARGET) # del -f *.o $(TARGET).exe # windows下要想在Makefile中通过命令行删除中间文件,需要将rm替换为del使用
make命令执行makefile文件中的指令集1make在当前目录下执行
main程序1 2./hello make clean
常用指令
| |