美文网首页
[原创] Cmake初体验

[原创] Cmake初体验

作者: 赵国开 | 来源:发表于2018-01-04 16:39 被阅读0次

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

相关文章

网友评论

      本文标题:[原创] Cmake初体验

      本文链接:https://www.haomeiwen.com/subject/rbgrnxtx.html