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
和CXX
3.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()
命令之前设置,(灵活性较差)
1
add_library(collector src1.cpp)
目标链接
考虑A库依赖于B库,因此将A链接到B
|
|
小总结 1
目标名称与项目名称无关,最好将项目名称和可执行文件名称分开
命名库的目标时,不要用lib作为名称的开头或结尾。lib会自动成为前缀
尽量避免直接将库指定 STATIC 或 SHARED
目标在调用 target_link_libraries() 时需要指定 PRIVATE 、 PUBLIC 和/或 INTERFACE
变量
基本变量
|
|
将所有变量都作为字符串处理,给定多个值,这些值将用 分号连接在一起。可以使用转义字符表示引号
\"
1 2 3 4 5
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" set(myVar a "b c") # myVar = "a;b c"
环境变量
|
|
只会影响当前的CMake实例,很少用到
缓存变量
|
|
布尔缓存变量使用optio()
代替set()
|
|
调试变量和诊断
|
|
处理字符串
查找和替换操作、正则表达式匹配、大小写转换、删除空格和其他常见字符串操作
查找
|
|
1 2 3 4 5 6 7
et(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 18
set(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 6
set(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 2
g++ *.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
# 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 $@ .PHONY: clean clean: rm -f *.o $(TARGET) # del -f *.o $(TARGET).exe # windows下要想在Makefile中通过命令行删除中间文件,需要将rm替换为del
使用
make
命令执行makefile
文件中的指令集1 2
make # make VERBOSE=1 查看make具体指令
在当前目录下执行
main
程序1 2
./hello make clean
|
|