简介
CMake是跨平台的 免费和开源软件,用于使用独立于编译器的方法构建自动化、测试、打包和安装软件。CMake 本身并不是一个构建系统;它生成另一个系统的构建文件。它支持目录层次结构和依赖于多个库的应用程序。它与原生构建环境结合使用,例如Make、Qt Creator、Ninja、Android Studio、Apple 的Xcode和Microsoft Visual Studio。(摘自Wiki)
CMakeLists.txt
常用命令
cmake要求最低版本(选择性添加)
1
cmake_minimum_required(VERSION 3.0.0)
编译工程名
1
2
3
4project(xxx)
//会自动创建两个变量,PROJECT_SOURCE_DIR和PROJECT_NAME
//${PROJECT_SOURCE_DIR}:本CMakeLists.txt所在的文件夹路径
//${PROJECT_NAME}:本CMakeLists.txt的project名称给部分文件或路径组合起别名, 通过${变量}获取变量内容
1
set(变量 文件名/路径/...)
设置c / c++ 编译编译参数
1
2
3set (CMAKE_C_FLAGS "-Wall -O2")
set (CMAKE_CXX_FLAGS "-Wall -std=C++11")
add_compile_options( -Wall ) //该命令译选项是针对所有编译器的(包括c和c++编译器)为当前路径以及子目录的源文件加入由-D引入的define flag
1
add_definitions(-DFOO -DDEBUG ...)
对子文件夹进行cmake编译
1
add_subdirectory(子文件夹名)
打印信息
1
2message() //直接添加打印的内容和变量即可,不需要双引号
message("PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}")帮助信息
1
1. 查看cmake默认变量 cmake --help-variable-list
判断语句
用法:根据某个宏确定编译内容。比较字符串,相同返回true
1 | if (CPU_PLATFORM_BIT STREQUAL "64") |
编译目标
二进制文件
1 | add_executable(目标文件名字xxx 源文件) |
动态 / 静态库
将指定的源文件生成链接文件,然后添加到工程中去
1 | add_library(<name> [STATIC | SHARED | MODULE] |
链接/路径
头文件路径
添加头文件的查找路径, 相当于命令行的 -l 参数
1 | include_directories(../thirdparty/comm/include) |
链接库路径
添加需要链接的库文件目录, 相当于命令行 -L 参数
1 | link_directories("/home/server/third/lib") |
链接库
将目标文件与库文件进行链接
1 | target_link_libraries(<target> [item1] [item2] [...] [[debug|optimized|general] <item>] ...) |
安装(Install)
- 详情参考:https://cmake.org/cmake/help/v3.22/command/install.html
- 作用:用于定义安装规则,安装内容包括可执行文件,静态库,动态库以及文件,目录,脚本等
- 使用方法:make install
- 目标安装路径:${CMAKE_INSTALL_PREFIX}指定,默认/usr/local
目标文件安装
目标文件指的是我们通过 add_executable / add_library 得到的二进制文件或者库,只有这些文件才可以通过该命令装载到相应的位置
- 可执行文件:RUNTIME
- 动态库:LIBRARY
- 静态库:ARCHIVE
1 | install(TARGETS targets... [EXPORT <export-name>] |
普通文件安装
普通文件即需要导出的头文件、依赖的三方库等等,该命令同时可以指定导出文件的权限(默认644)
1 | install(<FILES|PROGRAMS> files... |
目录安装
参数介绍:
- DIRECTORY:后面连接的是所在Source目录的相对路径(结尾是否是”/“对拷贝结果有一定影响)
- PATTERN:使用正则表达式进行过滤
- PERMISSIONS:指定PATTERN过滤后的文件权限。
1 | install(DIRECTORY dirs... |
Q&A
Q: 编译参数添加了-lpthread 参数, 但是还是报undefined reference to `pthread_create’
A : 需要使用target_link_libraries( target thread) 在这里链接thread库
Q: 如果在多级的目录下编译, 始终找不到问题报 undefine的问题 ?
A : 看一下是不是链接的库或目标文件格式不同, 一个c 一个c++ , 这样就会导致找不到符号错误
Q: undefined reference to `typeinfo for xxxBase_class’ ?
A: 基类的构造和析构函数需要加{ }; 否则就会报这个问题
Makefile
基本
PHYON
.PHONY 在 makefile 中表示定义伪目标。所谓伪目标,就是它不代表一个真正的文件名,在执行 make 时可以指定这个目标来执行其所在规则定义的命令
赋值语句
=
最基本的赋值方式,语句与在文中的位置无关,系统自动推导将最终的赋值作为变量的值
1
2
3
4
5str=123
target:
@echo $(str)
str=456
# 最终结果:456:=
覆盖式赋值。如果变量在之前定义赋值过,本次的值将更新变量。该符号赋值只能推导该符号位置之前的值
1
2
3
4
5str:=$(str1)123
str1=456
target:
@echo $(str)
# 最终结果:123(将str默认为空字符)?=
如果当前变量在之前被赋值过,则此次赋值不执行,否则执行
1
2
3
4
5str=123
str?=456
target:
@echo $(str)
# 最终结果 123+=
追加赋值。旧值保持不变,将新值黏贴到旧值后面
1
2
3
4
5str=123
str+=456
target:
@echo $(str)
# 最终结果:123 456
通配符
通配符 | 使用说明 |
---|---|
* | 匹配0个或者是任意个字符 |
? | 匹配任意一个字符 |
[] | 我们可以指定匹配的字符放在 “[]” 中 |
% | 匹配任意个字符 |
自动化变量
自动化变量 | 说明 |
---|---|
$@ | 表示规则的目标文件名。如果目标是一个文档文件(Linux 中,一般成 .a 文件为文档文件,也成为静态的库文件), 那么它代表这个文档的文件名。在多目标模式规则中,它代表的是触发规则被执行的文件名。 |
$% | 当目标文件是一个静态库文件时,代表静态库的一个成员名。 |
$< | 规则的第一个依赖的文件名。如果是一个目标文件使用隐含的规则来重建,则它代表由隐含规则加入的第一个依赖文件。 |
$? | 所有比目标文件更新的依赖文件列表,空格分隔。如果目标文件时静态库文件,代表的是库文件(.o 文件)。 |
$^ | 代表的是所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的只能是所有的库成员(.o 文件)名。 一个文件可重复的出现在目标的依赖中,变量 $ 只记录它的第一次引用的情况。就是说变量 $ 会去掉重复的依赖文件。 |
$+ | 类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合。 |
$* | 在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的部分(当文件名中存在目录时, “茎”也包含目录部分)。 |
特殊函数
添加前缀
- 函数名:addprefix( )
- 语法:$(addprefix PREFIX/,${NAME…})
- 函数功能:为“NAMES…”中的每一个文件名添加前缀“PREFIX”。参数“NAMES…”是空格分割的文件名序列,将“PREFIX”添加到此序列的每一个文件名之前。
- 返回值:以单空格分割的添加了前缀“PREFIX”的文件名序列。
1 | $(addprefix src/,foo bar) |
过滤器
- 函数名:filter( )
- 语法:$(filter SUFFIX…,$(SOURCES))
- 作用:保留字串 “ $(SOURCES)” 中所有符合模式 “ SUFFIX ” 的单词
1 | sources := main.c AT.txt |
打印
用于Makefile的Debug,打印分为三个等级:info、warning、error
1 | $(info SRC = $(SRC)) |