Cmake是什么
- cmake是一种自动生成makefile规则的工具,它有一套自己的语法规则来指导生成整个项目源码的编译框架。或者你可以把cmake理解成是一种抽象工具,提供了一些封装好的API接口来给使用者搭建自己需要的编译框架,它封装细节,封装复杂度,指定输入自动输出。
Cmake有什么优势
- 效率优势,如果你手动编写makefile和用cmake编写指导makefile生成,就像汇编之与C语言。
- 学习成本,相对其他自动生成makefile工具(比如Autotools)cmake语法和编译规则很简单,核心的内置命令不超过10个,常用的内置命令也不超过20个(强调命令,是因为cmake源文件中所有有效的语句都是命令)。
- 使用广泛,提到cmake总要带一下kde,因为kde使cmake名声大噪,能作为kde这样的大型软件项目的编译构建工具,cmake已经无需在向其他人证明什么,所以用的人比较多,cmake开发团队维护也比较积极,很多问题在官网的文档,wiki,邮件列表等等都可以找到答案,同时网络上也有很多高质量的文章,教程,模板等,在一些开发社区比如stackoverflow上也有一些比较优质的讨论,所以使用cmake你注定不会孤独,不会有局限性,有一大堆优秀的人帮你一起进步:)
- 其他优势,开源免费,跨平台(微软,苹果,linux都可以使用),速度快。
我为什么要用cmake
- 一句话,提高开发效率,降低开发维护成本。
- 因为项目组用到比较多的开源模块,而且还会继续增加相关开源模块,项目组核心源码的编译框架以makefile编写,所有之前或者后续加进来的模块既要适配现有的makefile框架,又要根据加进来模块的makefile规则进行调整和和修改。这样不仅修改和调整费时又费力,原来的编译框架没有为其他模块的引入预留接口,导致越改越乱,难以维护,在加之makefile一些规则很生涩。
- 我厌倦了每次修改调整都要去温习一下makefile的一些句法规则。
- 我也不想让项目组的每个成员都成为makefile编译专家(makefile学习成本比较高,没有经常用又容易忘掉)
- 我想用一些比较简单和易读的工具来重新构建整个编译框架,让后续的维护更简单,开发只专注业务价值开发,而不用被编译系统所分心。
一个对比例子
我要把下面的源文件编译成一个库
├── include
│ ├── ap.h
│ ├── arena.h
│ ├── arith.h
│ ├── array.h
│ ├── arrayrep.h
│ ├── assert.h
│ ├── atom.h
│ ├── bit.h
│ ├── chan.h
│ ├── except.h
│ ├── fmt.h
│ ├── list.h
│ ├── mem.h
│ ├── mp.h
│ ├── ring.h
│ ├── sem.h
│ ├── seq.h
│ ├── set.h
│ ├── stack.h
│ ├── str.h
│ ├── table.h
│ ├── text.h
│ ├── thread.h
│ └── xp.h
├── LICENSE
├── makefile
└── src
├── ap.c
├── arena.c
├── arith.c
├── array.c
├── assert.c
├── atom.c
├── bit.c
├── chan.c
├── except.c
├── fmt.c
├── libcii.def
├── list.c
├── mem.c
├── memchk.c
├── memcmp.c
├── memmove.c
├── mp.c
├── ring.c
├── seq.c
├── set.c
├── stack.c
├── str.c
├── strncmp.c
├── swtch.s
├── table.c
├── text.c
└── xp.c
原来手写的makefile编译规则如下
# $Id: makefile 207 2008-09-30 04:43:42Z drhanson $
A=.a
O=.o
E=
CC=cc
I=include
CFLAGS=-g -I$I
LDFLAGS=-g
LD=cc
AS=as
AR=ar ruv
RANLIB=ranlib
DIFF=diff
RM=rm -f
CUSTOM=custom.mk
EXTRAS=$(BUILDDIR)memcmp$O $(BUILDDIR)memmove$O $(BUILDDIR)strncmp$O
THREADS=$(BUILDDIR)thread$O $(BUILDDIR)swtch$O
include $(CUSTOM)
B=$(BUILDDIR)
OBJS= $Bap$O \
$Barena$O \
$Barith$O \
$Barray$O \
$Bassert$O \
$Batom$O \
$Bbit$O \
$Bchan$O \
$Bexcept$O \
$Bfmt$O \
$Blist$O \
$Bmem$O \
$Bmp$O \
$Bring$O \
$Bseq$O \
$Bset$O \
$Bstack$O \
$Bstr$O \
$Btable$O \
$Btext$O \
$Bxp$O \
all:: $Blibcii$A
$Blibcii$A:: $(OBJS) $(EXTRAS)
$(AR) $@ $(OBJS) $(EXTRAS); $(RANLIB) $@ || true
$Bap$O: src/ap.c; $(CC) $(CFLAGS) -c -o $@ src/ap.c
$Barena$O: src/arena.c; $(CC) $(CFLAGS) -c -o $@ src/arena.c
$Barith$O: src/arith.c; $(CC) $(CFLAGS) -c -o $@ src/arith.c
$Barray$O: src/array.c; $(CC) $(CFLAGS) -c -o $@ src/array.c
$Bassert$O: src/assert.c; $(CC) $(CFLAGS) -c -o $@ src/assert.c
$Batom$O: src/atom.c; $(CC) $(CFLAGS) -c -o $@ src/atom.c
$Bbit$O: src/bit.c; $(CC) $(CFLAGS) -c -o $@ src/bit.c
$Bchan$O: src/chan.c; $(CC) $(CFLAGS) -c -o $@ src/chan.c
$Bexcept$O: src/except.c; $(CC) $(CFLAGS) -c -o $@ src/except.c
$Bfmt$O: src/fmt.c; $(CC) $(CFLAGS) -c -o $@ src/fmt.c
$Blist$O: src/list.c; $(CC) $(CFLAGS) -c -o $@ src/list.c
$Bmem$O: src/mem.c; $(CC) $(CFLAGS) -c -o $@ src/mem.c
$Bmemchk$O: src/memchk.c; $(CC) $(CFLAGS) -c -o $@ src/memchk.c
$Bmp$O: src/mp.c; $(CC) $(CFLAGS) -c -o $@ src/mp.c
$Bring$O: src/ring.c; $(CC) $(CFLAGS) -c -o $@ src/ring.c
$Bseq$O: src/seq.c; $(CC) $(CFLAGS) -c -o $@ src/seq.c
$Bset$O: src/set.c; $(CC) $(CFLAGS) -c -o $@ src/set.c
$Bstack$O: src/stack.c; $(CC) $(CFLAGS) -c -o $@ src/stack.c
$Bstr$O: src/str.c; $(CC) $(CFLAGS) -c -o $@ src/str.c
$Btable$O: src/table.c; $(CC) $(CFLAGS) -c -o $@ src/table.c
$Btext$O: src/text.c; $(CC) $(CFLAGS) -c -o $@ src/text.c
$Bthread$O: src/thread.c; $(CC) $(CFLAGS) -c -o $@ src/thread.c
$Bthread-nt$O: src/thread-nt.c;$(CC) $(CFLAGS) -c -o $@ src/thread-nt.c
$Bxp$O: src/xp.c; $(CC) $(CFLAGS) -c -o $@ src/xp.c
$Bswtch$O: src/swtch.s; $(AS) -o $@ src/swtch.s
$Bmemcmp$O: src/memcmp.c; $(CC) $(CFLAGS) -c -o $@ src/memcmp.c
$Bmemmove$O: src/memmove.c; $(CC) $(CFLAGS) -c -o $@ src/memmove.c
$Bstrncmp$O: src/strncmp.c; $(CC) $(CFLAGS) -c -o $@ src/strncmp.c
$Bdouble$E: $Bdouble$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bdouble$O $Blibcii$A
$Bcalc$E: $Bcalc$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bcalc$O $Blibcii$A
$Bids$E: $Bids$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bids$O $Blibcii$A
$Bmpcalc$E: $Bmpcalc$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bmpcalc$O $Blibcii$A
$Biref$E: $Biref$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Biref$O $Blibcii$A
$Bkref$E: $Bkref$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bkref$O $Blibcii$A
$Bidents$E: $Bidents$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bidents$O $Blibcii$A
$Bwords$E: $Bwords$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bwords$O $Blibcii$A
$Bbasename$E: $Bbasename$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bbasename$O $Blibcii$A
$Bdirname$E: $Bbasename$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bbasename$O $Blibcii$A
$Bwf$E: $Bwf$O $Bgetword$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bwf$O $Bgetword$O $Blibcii$A
$Bxref$E: $Bxref$O $Bgetword$O $Blibcii$A;$(LD) $(LDFLAGS) -o $@ $Bxref$O $Bgetword$O $Blibcii$A
$Bcref$E: $Bcref$O $Binteger$O $Blibcii$A;$(LD) $(LDFLAGS) -o $@ $Bcref$O $Binteger$O $Blibcii$A
$Bsort$E: $Bsort$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bsort$O $Blibcii$A
$Bspin$E: $Bspin$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bspin$O $Blibcii$A
$Bsieve$E: $Bsieve$O $Blibcii$A; $(LD) $(LDFLAGS) -o $@ $Bsieve$O $Blibcii$A
maxalign: $Bmaxalign$E
$Bmaxalign$E
$Bmaxalign$E: misc/maxalign.c
$(CC) -o $@ misc/maxalign.c
clean::
$(RM) $B*$O
$(RM) $(EXAMPLES)
clobber:: clean
$(RM) $Blibcii$A
# DO NOT DELETE THIS LINE -- make depend depends on it.
$Bap$O: $I/assert.h $I/except.h $I/ap.h $I/fmt.h $I/xp.h $I/mem.h
$Barena$O: $I/assert.h $I/except.h $I/arena.h
$Barith$O: $I/arith.h
$Barray$O: $I/assert.h $I/except.h $I/array.h $I/arrayrep.h $I/mem.h
$Bassert$O: $I/assert.h $I/except.h
$Batom$O: $I/atom.h $I/assert.h $I/except.h $I/mem.h
$Bbit$O: $I/assert.h $I/except.h $I/bit.h $I/mem.h
$Bchan$O: $I/assert.h $I/except.h $I/mem.h $I/chan.h $I/sem.h
$Bexcept$O: $I/assert.h $I/except.h
$Bfmt$O: $I/assert.h $I/except.h $I/fmt.h $I/mem.h
$Blist$O: $I/assert.h $I/except.h $I/mem.h $I/list.h
$Bmem$O: $I/assert.h $I/except.h $I/mem.h
$Bmemchk$O: $I/assert.h $I/except.h $I/mem.h
$Bmp$O: $I/assert.h $I/except.h $I/fmt.h $I/mem.h $I/xp.h $I/mp.h
$Bring$O: $I/assert.h $I/except.h $I/ring.h $I/mem.h
$Bseq$O: $I/assert.h $I/except.h $I/seq.h $I/array.h $I/arrayrep.h $I/mem.h
$Bset$O: $I/mem.h $I/except.h $I/assert.h $I/arith.h $I/set.h
$Bstack$O: $I/assert.h $I/except.h $I/mem.h $I/stack.h
$Bstr$O: $I/assert.h $I/except.h $I/fmt.h $I/str.h $I/mem.h
$Btable$O: $I/mem.h $I/except.h $I/assert.h $I/table.h
$Btext$O: $I/assert.h $I/except.h $I/fmt.h $I/text.h $I/mem.h
$Bthread$O: $I/assert.h $I/except.h $I/mem.h $I/thread.h $I/sem.h
$Bthread-nt$O: $I/assert.h $I/except.h $I/mem.h $I/thread.h $I/sem.h
$Bxp$O: $I/assert.h $I/except.h $I/xp.h
我用cmake重写了一下,关键代码就三行
cmake_minimum_required(VERSION 3.1.0)
project(main)
#编译规则指定
aux_source_directory(./src DIR_SRCS)
add_library(main ${DIR_SRCS})
target_include_directories(main PRIVATE ./include)
cmake在编写的效率和简洁程度上可以说是暴击makefile
网友评论