CMake快速入门教程
前言
Make工具因遵循不同的规范和标准,执行的Makefile的格式也是不同。主流的Make工具包括:
- GNU Make
- QT的qmake
- 微软的 MS nmake
- BSD的 pmake
每个平台都有自己的工具,则带来了很大的平台兼容性问题。CMake是一种跨平台的编译工具。
准备阶段:
- 安装cmake
- 编写CMake配置文件CMakeLists.txt
基本流程:
- 执行
cmake PATH或者ccmake PATH命令,将CMakeLists.tx文件转化为所需要的Makefile文件。其中PATH为CMAKLISTs.txt所在的目录 - 执行make命令,编译原码生成可执行程序,或者库文件
单目录,单文件
一个简单的样例:
# CMake的最低版本要求
cmake_minimum_required (VERIONS 2.8)
# 项目信息
project(Demo)
# 指定生成目标
add_executable(Demo demo.cc)
语法规则:
- 命令、空格、注释组成
- 命令是不区分大小写的
- 符号
#后面内容为注释 - 参数之间使用
空格分隔
单目录,多文件
在实际项目中,一般不会只有一个demo.cc源码文件,常为一个目录下多个源文件。假设目录结构如下:
./Demo
|-- main.cc
|-- foo.cc
|-- foo.h
此时的CMakeLists.txt内容可以更新为如下:
# CMake的最低版本要求
cmake_minimum_required (VERIONS 2.8)
# 项目信息
project(Demo)
# 指定生成目标
add_executable(Demo demo.cc foo.cc)
即只需要在add_executable里把依赖的foo.cc源文件添加进来即可。
但引入另一个问题:新增的源文件越来越多,总不能一个个手动加进来吧?
cmake中有 aux_source_directory命令,会查找指定目录下所有源文件,并存放到指定的变量名中:
# CMake的最低版本要求
cmake_minimum_required (VERIONS 2.8)
# 项目信息
project(Demo)
# 查找当前目录下所有源文件
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
多目录,多文件
针对一个项目中包含了多了层级目录,且每个目录下都包含一些源文件。若目录结构如下:
./Demo
|-- main.cc
|-- utils
|-- foo.cc
|-- foo.h
我们需要分别在Demo和utils目录下各自编写一个CMakeLists.txt文件。
为了方便,可以先将utils目录里的文件编译成静态库,再由main函数调用。
根目录中的CMakeLists.txt
# CMake的最低版本要求,如果不满足则报错
cmake_minimum_required (VERIONS 2.8 FATAL_ERROR)
# 项目信息
project(Demo)
# 添加 math 子目录
add_subdirectory(utils)
# 指定生成目标
add_executable(Demo main.cc)
# 添加链接库
target_link_libraries(Demo utils)
add_subdirectory表示会处理子目录下的CMakeLists.txt和源代码target_link_libraries表示main执行文件需要链接一个名为utils的链接库
utils目录中的CMakeLists.txt
# 查找当前目录下的所有源文件、并保存到 DIR_LIB_SRCS 变量中
aux_source_directory(. DIR_LIB_SRCS)
# 生成链接库
add_library(utils ${DIR_LIB_SRCS})
add_library会将所有源文件编译为静态链接库
其他编译选项
如下是一个项目的CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(Demo)
# 定一个开关选项,支持cmake时通过 -DUSE_MYUTILS=OFF 指定
option(USE_MYUITLS "whether use customized math" ON)
# 自定义分支逻辑
if(USE_MYUITLS)
include_directories("{PROJECT_SOURCE_DIR}/utils")
add_subdirectory(utils)
set(EXTRA_LIBS ${EXTRA_LIBS} utils)
endif(USE_MYUITLS)
# 查找目录下所有源文件
aux_source_directory(. DIR_SRCS)
# 添加执行文件
add_executable(Demo ${DIR_SRCS})
# 链接静态库
target_link_libraries(Demo ${EXTRA_LIBS})
关于option的生效机制,这里详细解释下。如main.cc中的代码:
#include <stdio.h>
#include <stdlib.h>
#include "config.h" // 此头文件是cmake自动生成的
#ifdef USE_PYUTILS
#include "utils/foo.h"
#else
#include <foo.h> // 假设标准库有foo.h头文件
#endif
为了打通CMakeLists.txt一键便携式配置,我们需要编写一个config.h.in文件:
#cmakedefine USE_MYUTILS
这样,在执行cmake命令时,就可以根据配置的参数,自动生成option相关的头文件。若指定-DUSE_MYUTILS=ON时,config.h中的内容为:
#define USE_MYUTILS
若为OFF时,则config.h的内容为:
/* #undef USE_MYUTILS */
安装和测试
camke支持安装和测试,通过在生成Makefile后,使用make install和make test来执行。
接上述样例,首先在utils/CMakeLists.txt中加上如下内容:
# 指定utils库的安装路径
install(TARGETS utils DESTINATION bin)
install(FILES utils.h DESTINATION include)
在Demo/CMakeLists.txt添加如下内容:
# 指定安装路径
install(TARGETS Demo DESTINATION bin)
install(FILES "${PROJECT_BINARY}/config.h" DESTINATION include)
原理 & 流程:
- cmake编译产出的
Demo文件和库libUtils.o文件将会被复制到/usr/local/bin中 - 头文件
utils.h和config.h则会被赋值到/use/local/include中 - 可以通过
CMKAE_INSTALL_PREFIX修改默认安装的根目录/usr/local
关于测试,CMake提供一个称为CTest的测试工具,通过add_test命令添加:
# 启用测试
enable_testing()
# 测试程序是否成功运行, arg*为函数接收的参数
add_test(test_run Demo arg1 arg2)
add_test(test_usage Demo)
set_tests_properties(test_usage PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .....")
add_test(test_result Demo 10 2)
# 测试输出的结果是否包含字符串 "is 100"
set_tests_properties(test_result PROPERTIES PASS_REGULAR_EXPRESSION "is 100")
支持gdb
CMake支持gdb的方式很简单,只需指定Debug模式下开启-g,一个简单的样例如下:
set(CMAKE_BUILD_TYPE "Debug")
# debug模式下编译选项
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
# release模式下编译选项
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
小结
CMake的语法主要以命令、空格、参数来组成
可以通过
set(<variable> <value>)设置变量的值if语法
if(<condition>)
<commands>
elseif(<condition>) # optional block, can be repeated
<commands>
else() # optional block
<commands>
endif()
for语法
# usage 1:
foreach(<loop_var> <items>)
<commands>
endforeach() # usage 2:
foreach(<loop_var> RANGE <stop>)
while语法
while(<condition>)
<commands>
endwhile()
附录:
CMake快速入门教程的更多相关文章
- CMake快速入门教程-实战
http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/ http://blog.csdn.net/dbzhang800/article/detai ...
- 转:CMake快速入门教程-实战
CMake快速入门教程:实战 收藏人:londonKu 2012-05-07 | 阅:10128 转:34 | 来源 | 分享 0. 前言一个多月 ...
- CMake快速入门教程:实战
转自http://blog.csdn.net/ljt20061908/article/details/11736713 0. 前言 一个多月前,由于工程项目的需要,匆匆的学习了一下cmake的使 ...
- [转]CMake快速入门教程:实战
转自http://blog.csdn.net/ljt20061908/article/details/11736713 0. 前言 一个多月前,由于工程项目的需要,匆匆的学习了一下cmake的使 ...
- 专为设计师而写的GitHub快速入门教程
专为设计师而写的GitHub快速入门教程 来源: 伯乐在线 作者:Kevin Li 原文出处: Kevin Li 在互联网行业工作的想必都多多少少听说过GitHub的大名,除了是最大的开源项目 ...
- EntityFramework6 快速入门教程
EntityFramework6 快速入门教程 不得不说EF在国内实在是太小众,相关的技术文章真实屈指可数,而且很多文章都很旧了,里面使用的版本跟如今的EF6差别还是比较大.我刚开始弄这个的时候真是绕 ...
- Apple Watch开发快速入门教程
Apple Watch开发快速入门教程 试读下载地址:http://pan.baidu.com/s/1eQ8JdR0 介绍:苹果为Watch提供全新的开发框架WatchKit.本教程是国内第一本A ...
- 指示灯组与3个复位按钮的介绍Arduino Yun快速入门教程
指示灯组与3个复位按钮的介绍Arduino Yun快速入门教程 1.4.2 指示灯组 指示灯组的放大图如图1.5所示. 图1.5 指示灯组 各个指示灯对应的功能如下: q RX:对应于0号端口, ...
- 游戏控制杆OUYA游戏开发快速入门教程
游戏控制杆OUYA游戏开发快速入门教程 1.2.2 游戏控制杆 游戏控制杆各个角度的视图,如图1-4所示,它的硬件规格是本文选自OUYA游戏开发快速入门教程大学霸: 图1-4 游戏控制杆各个角度的 ...
- Query 快速入门教程
Query 快速入门教程 http://www.365mini.com/page/jquery-quickstart.htm#what_is_jquery jquery常用方法及使用示例汇总 http ...
随机推荐
- 探秘Kubernetes:在本地环境中玩转容器技术
在云计算时代,Kubernetes 已成为云原生技术的真正基石.它是应用程序容器的编排动力源,可跨多个集群自动部署.扩展和运行容器.Kubernetes 不仅仅是一个流行词,它还是一种模式转变,是现代 ...
- MySQL索引Innodb存储引擎
MySQL索引优化 一.基础理解 MySQL语句的查询效率主要和索引树的高度有关,想要降低查询的次数提高查询的速度,减少直接对磁盘的I/O流的次数,就要让索引树的高度越低越好. 索引的定义:索引是帮助 ...
- Spring Bean 的一生
Spring Bean 的一生包括其从创建到消亡的整个过程: 实例创建 => 填充 => 初始化 => 使用 => 销毁. 这里需要注意的是,从 bean 实例的创建到可以使用 ...
- 关于 ThreadLocalRandom 随机数生成器
ThreadLocalRandom 线程安全随机数获取. 示例随机整数:java.util.concurrent.ThreadLocalRandom.current().nextInt(); 线程Th ...
- #线段树#洛谷 4269 [USACO18FEB]Snow Boots G
题目传送门 分析 模型转换一下,能通过当且仅当最长的无法通过段小于 \(d\),(这点应该是此题的精华吧) 那么按照最大深度从小到大排序,双指针在线段树上删除无法通过段,求最长区间即可 代码 #inc ...
- #Kruskal,可撤销并查集#CF891C Envy
题目 给出一个 \(n\) 个点 \(m\) 条边的无向图,每条边有边权,共 \(Q\) 次询问, 每次给出 \(k_i\) 条边,问这些边能否同时在一棵最小生成树上. 分析 考虑最小生成树选择的边权 ...
- #插头dp#洛谷 5074 HDU 1693 Eat the Trees
题目 给出 \(n*m\) 的方格,有些格子不能铺线, 其它格子必须铺,可以形成多个闭合回路. 问有多少种铺法? \(n,m\leq 12\) 分析 设 \(dp[n][m][S][0/1]\) 表示 ...
- 直播预告丨OpenHarmony标准系统多媒体子系统之视频解读
5月19日(周四)晚上19点,OpenHarmony开源开发者成长计划知识赋能第五期"掌握OpenHarmony多媒体的框架原理"的第五节直播课,即将开播! 深开鸿资深技术专家胡浩 ...
- OpenHarmony开源开发者成长计划 | 知识赋能第六期预告—从零上手OpenHarmony智能家居项目
OpenAtom OpenHarmony(以下简称"OpenHarmony")开源开发者成长计划项目自 2021 年 10 月 24 日上线以来,在开发者中引发高度关注. 成长计划 ...
- C 语言文件处理全攻略:创建、写入、追加操作解析
C 语言中的文件处理 在 C 语言中,您可以通过声明类型为 FILE 的指针,并使用 fopen() 函数来创建.打开.读取和写入文件: FILE *fptr; fptr = fopen(filena ...