cmake构建工具,cma软件可用于计算机
现代软件构建系统在CMake中的应用-程序是生命-博客频道-CSDN。网
现代软件构造系统CMake的使用介绍
分类:
【Linux】
2009-10-29 15:39
313人阅读
评论(1)
收集
报告目录(?)[ ]
现代软件构造系统使用介绍CMake介绍CMake的主要优点:在安装CMake之前,CMake入门级库是依靠静态库来构建程序库的。参考摘要:完整的源代码获取,讲解现代软件构造系统的使用。CMake简介由九天雁翎(JTIANLING)撰写-blog..net/vagrxie
讨论新闻组和文档
前言第一次看到CMake是在Eclipse中编译toolchain的选项,但一直没怎么关注。然后我又重新认识了CMake。像许多人一样,这是通过KDE的源代码。上次在KDE查看右键菜单编辑的时候,接触到了KDE的源代码。自然,我需要KDE的构建系统CMake,但我只是使用了它,并没有在意,直到我看到《通向KDE4之路》系列文章0755。再版的Linux Eden更好,但是不完整。其他很多版本没有图片,阅读乐趣就少了。KDECN的版本有完整的文章,但没有图片。)我对KDE4从autotools工具链到CMake的转变印象深刻,有了一探究竟的想法。毕竟我在学习autotools系列工具的时候,根本没有任何意图。公司里也没有使用类似工具的氛围。一般都是通过简单的模板手工编写makefile,然后通过bash脚本管理整个项目的顺序依赖等事情-_-!呵呵,虽然说实话,因为毕竟公司的工程改动不大,而且当时也是以移植Windows server程序为主,所以足够了。而且,如果不是因为没有工作的闲暇时间,我真的没有时间去学这些东西。
CMake的主要优势:1。易于使用:KDE作为开源世界最大的项目之一,经常吃螃蟹,体验先进技术的先锋力量(因为项目管理需求)。svn在使用上是领先的(在文章《通向KDE4之路(八):CMake,新的KDE构建系统》中有描述),而且非常成功。然后其他开源项目开始跟进。目前svn基本上是开源界的标准设备。(虽然也有其他迁移趋势,见我的原文章《通向KDE4之路》)。目前开源界的标准构建系统是autotools,这也是KDE3使用的构建系统。然而,随着KDE项目的扩大,它慢慢不足以使用。根据《分布式的,新一代版本控制系统mercurial的介绍及简要入门》的作者所说,“只有少数所谓的‘编译专家’才能彻底熟悉整个KDE编译系统”。当然,使用CMake的目的是为了改变这种现象,改变后的效果是“事实可以说明,你们KDE编译器专家以后可以少死一些脑细胞,大家可以轻松构建自己的项目,让项目运行起来。”这个评价让我感到兴奋。
2.效率高:以下是《通向KDE4之路》的原文“CMake搜索依赖对象的速度比的快好几倍”。/configure”。用CMake构建kdelibs4比用自动工具构建KDE 3.5.6要少花40%的时间,可能是因为CMake不使用libtool来组织工具链。在UNIX平台上,CMake使用的工具链是这样的:cmake make,然后你可以看看KDE 3.5.6的构建工具链:AUTOMAKE AUTOCONF libtool make sh perl M4.哥们,对比一下。”
这是。
055-79000供你参考,KDE4迁移到CMake的经验。提出了很多优点。
每次你学到新的东西,都很有趣。虽然一开始会花时间去学习,但实践证明,由于它们有着不同于旧东西的优点,最终会为我节省更多的时间。Python、Bash、Vim、Mercurial、Autohotkey等众多工具的学习经历告诉我是这样的。这也是我一次又一次学习新事物的动力。
CMake将CMake安装为一个跨平台的开源构建系统,它有Windows和Linux下的版本。
Windows版本一如既往的有自动安装包。看到右边的链接了吗,http://www.cmake.org/cmake/resources/software.html.
但是因为我用的是kubuntu 9.04,所以安装Linux版本太容易了,apt-get install cmake。不过因为是Kubuntu,一般都已经安装好了,我们也不用再费心安装了。
比如在使用CMake之前,我以前用Linux写程序的时候,经常会自己创建一个Makefile(虽然我用bash自动生成原始的Makefile和cpp文件),如下面的示例测试项目所示:
obj=test.o
测试:$(obj)
g -g -o测试$(obj)
$(obj) : test.cpp test.h
g -g -c测试。假的:干净
清洁:
-rm测试$(obj)
有了这样的Makefile,test.cpp,test.h就可以正常编译了,我只需要在编译的时候使用make命令。例如,例如test.cpp,test . h test . h的内容如下:
test.cpp:
1:#包含stdlib.h
2:#包含stdio.h
3:
4: int main(int argc,char* argv[])
5: {
6: printf(Hello World!/n’);
7:
8:getchar();
9:退出(0);
10: }
11:
Test.h:(目前无意义,纯为演示)1:#包含iostream
2:使用命名空间std
3:
这样我只需要make,然后就可以生成测试程序,然后就可以调试或者看到运行结果了,还可以通过make clean清理环境,基本上就是一个简单的Makefile文件的例子。但是这个过程有一个问题,就是每次添加一个文件,总是需要再次手动编辑Makefile。例如,在下面的例子中,我添加了一个类,然后需要相应地更改Makefile。
添加一个类,2个文件:
Out.cpp:
#包含“Out.h”
void COut:print()
{
printf(Hello World!);
}
Out.h:
#ifndef __OUT_H__
#define __OUT_H__
#包含stdio.h
using命名空间std
COut类
{
公共:
static void print();
};
#endif
test.cpp:
#包含stdlib.h
#包含stdio.h
#包含“Out.h”
int main(int argc,char* argv[])
{
COut:print();
getchar();
退出(0);
}
此时,需要手动更改Makefile,它变成如下形式:
makefile:
obj=test.o
objOut=Out.o
测试:$(obj)$(objOut)
g -g -o测试$(obj)$(objOut)
$(obj) : test.cpp test.h
g -g -c测试
$(objOut) : Out.cpp Out.h
g -g -c Out.cpp。假的:干净
清洁:
-rm测试$(obj)$(objOut)
此外,每个文件更改都需要手动更改。其实手动改有更好的方法。makefile提供了一些传递%的简单方法。$ Slt,$ @自动通过后缀匹配的方法,(见Makefile写的相关教程)。但实际上,每次文件更改时,对Makefile的手动更改仍然是必不可少的。更重要的是,文件之间的依赖关系不能简单的人工判断,比如上面这个简单的例子。其实我并没有添加test.cpp对Out.o的依赖在这种情况下,链接或者编译的时候经常会出现问题,导致最简单的方法就是直接重新编译链接。在我之前的公司,基本都是靠这种方式。其实这些弊端都可以通过CMake甚至自动工具来解决。另外,以上只是最简单的情况。实际上,一个真实规模的程序至少要包含大量的库,库依赖等东西都得自己手动编写makefile时考虑。经常会有很多未实现的功能,甚至有人说你大概知道你写的库的功能在哪里没有实现。当存在未实现的系统功能时,通常很难找到哪个库丢失了。反复的链接和分析真的很烦。这种重复枯燥的工作自然不应该由程序员来做,浪费生命。再者,在分发源代码的时候,如何保证别人的机器配置和你的一样?gcc所在的目录,各种库所在的目录,没办法强行指定-_-!这不是一个简单复杂的问题,而是一个执行的问题。更重要的是,相同的源代码允许不同的编辑工具。有人习惯vim,有人习惯emacs,有人喜欢eclipse。如何协调它们?当然,同一个公司可以制定统一的规定,但是开源世界的规则太多了,不现实。让我们比较一下CMake使用的解决方案。
CMake CMake入门依赖于CMakeLists.txt文件来生成项目。其实写cmakelists.txt就像用make的时候写Makefile一样。但是CMake station的高度相对更高,所以虽然还是要写一个配置文件,但是CMakefile的编写要比Makefile容易很多。最后CMake实际上是通过生成makefile来管理项目的(其实CMake可以生成多种项目文件,甚至支持eclipse和VC-_-!)
例如,在上面简单的HelloWorld示例中,我们只需要编写一个CMakeLists.txt文件,如下所示:
项目(测试)
set(CMAKE_CXX_FLAGS -g -Wall )
set(SRC_LIST test.cpp)
add_executable(测试{ SRC _ LIST })
保存文件,然后就可以通过在原项目中添加子目录(或者其他目录)来隔离CMakefile和以后编译的中间文件对源程序的干扰(这个很高明)。我印象特别深刻的是VS自动创建文件,涉及到源代码管理的时候总是要处理。(当然,如果用VSS管理更好,我对mercurial感到厌烦)
众所周知,我们使用自动工具来构建编译软件。/configure make make安装
声明,在redhat9时代,你用不了百胜,你也没少用。我甚至直接设置为ml的别名。
现在我们使用CMake的方法是
第一种./make make安装
当然,这个命令没有太大的不同。而且,我们这里没有安装-_-啊!
在子目录(我将其命名为build)中,运行cmake./,
然后出现很多信息:
jtianling @ jtianling-laptop:~/test/cmaketest 2/build $ cmake./
-C编译器标识是GNU
CXX编译器标识是GNU
-检查正在工作的C编译器:/usr/bin/gcc
-检查工作的C编译器:/usr/bin/gcc - works
-检测C编译器ABI信息
-检测C编译器ABI信息-完成
-检查正在工作的CXX编译器:/usr/bin/c
-检查正在工作的CXX编译器:/usr/bin/c - works
-检测CXX编译器ABI信息
-检测CXX编译器ABI信息-完成
-配置完成
-生成完成
-构建文件已写入:/home/jtianling/test/cmaketest 2/Build
jtianling @ jtianling-laptop:~/test/cmaketest 2/build $至此,生成了Makefile文件,我们可以看一下了。很多东西我们理解不了也没关系。直接制作就可以了,如下图:
jtianling @ jtianling-laptop:~/test/cmaketest 2/build $ make
扫描目标测试的依赖性
[100%]构建CXX对象CMakeFiles/test.dir/test.cpp.o
链接CXX可执行测试
[100%]构建目标测试
jtianling @ jtianling-laptop:~/test/cmaketest 2/build $ ls
cmake cache . txt cmake files cmake _ install . cmake Makefile测试
jtianling @ jtianling-laptop:~/test/cmaketest 2/build $如果不是通过putty远程,还可以看到一些颜色信息。至此,我们可以看到测试程序已经生成。让我们运行它,没有任何问题。
相比之下,编译Makefile的时候,我们写了8、9行,而CMakeLists.txt我们只用了4行呵呵,这里虽然多了一倍,但是增加了生成Makefile的过程,不能只说CMake有多好。下面慢慢看。这里先解释一下CMakeList.txt中每一句的意思:
项目(测试)
设置项目名称
set(CMAKE_CXX_FLAGS -g -Wall )
set(SRC_LIST test.cpp)
Set用于指定变量。这里,CMake_CXX_FLAGS被指定为“-g -Wall”,CMAKE_CXX_FLAGS是CMake的内置变量。通过修改这个变量,我们可以在编译生成的Makefile时添加调试和警告信息(这是G编译选项的知识)。后一组将SRC_LIST变量的值指定为test.cpp,这是我们的用户变量。
add_executable(测试{ SRC _ LIST })
指定生成名为test的程序,该程序依赖于SRC_LIST变量。{ SRC _ LIST }的变量引用方法类似于makefile中的bash。
以上四句话印证了测试项目的生成规则。
添加文件后,我们需要对CMakeLists.txt做进一步的修改,比如前面例子中添加Out.cpp的情况。
我们在上面的第3行中添加Out.cpp文件,如下所示:
set(SRC_LIST test.cpp Out.cpp)
然后就可以正确生成Makefile了,比手工准备上述Makefile节省了不少时间。但是,作为世界上最懒的程序员之一(不是说懒是一种美德,大概是够懒了),我觉得教起来也很麻烦。不然怎么会人人都喜欢IDE-_-!其实CMake的写手自然是程序员,自然也就懒了。自然,它们也提供了一种更简单的方法。只要把上面的CMakeLists.txt改成目录依赖的形式,一切就简单了。将上面CMakeLists.txt的第三行改为:
辅助源目录(。/SRC_LIST)
这样,CMake将自动在。/,然后自动给SRC_LIST变量赋值。这样的话,再加几千个文件也没关系,只要重新运行CMake就可以了。呵呵,一切的简单是不是超乎想象?学完你会惊呼,这就是我想要的!(当然,如果你以前手工编写过makefile或者使用过autotools,那么在我没有说这个的时候使用IDE)
使用这个CMakeFiles.txt后,我们不需要为添加源代码而做任何改变。参见下面的执行过程:(警告信息告诉我们指定cmake的最低要求版本。对这次示威来说无所谓,以后也无所谓。)
jtianling @ jtianling-laptop:~/test/cmakeTest/build $ cmake./
CMakeLists.txt中的CMake警告(dev):
不存在cmake_minimum_required命令。一行代码,如
cmake_minimum_required(版本2.6)
应该添加到文件的顶部。指定的版本可能较低
如果您希望为此项目支持旧版本的CMake。更多
信息运行 cmake - help-policy CMP0000 。
这个警告是给项目开发者的。使用-Wno-dev来抑制它。
-配置完成
-生成完成
-构建文件已写入:/home/jtianling/test/cmakeTest/Build
jtianling @ jtianling-laptop:~/test/cmakeTest/build $ make
扫描目标测试的依赖性
[ 50%]构建CXX对象CMakeFiles/test.dir/Out.o
[100%]构建CXX对象CMakeFiles/test.dir/test.o
链接CXX可执行测试
[100%]构建目标测试
jtan ling @ jtianling-laptop:~/test/cmaketest/build $自动完成编译,自动添加Out.cpp的依赖关系呵呵,这个过程就像用手写makefile一样惬意,就像用手洗衣服,用全自动洗衣机。(当然工程文档的目录管理还得认真做,再乱也不能这样简化。)
库在处理makefiles的手工编译时,你得知道gcc,g的语法,加上一堆-I,-l之类的东西,找出它是在哪个目录返回的。这太不人道了(其实建议学gcc,g的语法,makefile Y也建议学。毕竟CMake并不是到处都有。毕竟还是要处理这个原始的依赖和编译选项),CMA
以《通向KDE4之路(八):CMake,新的KDE构建系统》中的一个骂人例子为例。原始代码如下:
hello3.c:
1: /* hello3.c
2: *动画效果使用刷新和睡眠的目的
3: *大纲初始化,绘制素材,总结
4: */
5:#包含stdio.h
6:#包含诅咒. h
7:
8:主()
9: {
10:int I;
11:
12:init SCR();
13:clear();
14:for(I=0;I线;i ){
15:动(我,我我);
16: if ( i%2==1)
17:鹤立鸡群();
18: addstr(Hello,world );
19: if ( i%2==1)
20:standen();
21:睡眠(1);
22:刷新();
23: }
24:endwin();
25: }
这个例子需要用到curses库,我们只需要在CMakeLists.txt中添加一句话如下:
链接_库(诅咒)
CMake会处理剩下的事情。
静态库构造说明了如何链接系统的库。CMake也为我们编译自己的库提供了便利。了解以上知识后,我们会发现编译一个库也是这么简单。
例如,在上面的例子中,out类被分离到一个库中,在原目录下单独建立一个out目录,并编写以下CMakeLists.txt文件:
项目(出)
set(CMAKE_CXX_FLAGS -g -Wall )
辅助源目录(。/SRC_LIST)
add_library(out ${SRC_LIST})
会发现,其实你写一个静态库需要做的就是最后一行从add _ excuteable到add_library的区别-_-!简单到让人无语。编译后会生成一个名为libout.a的文件,这个名字是按照Linux的约定取的。
程序库的构建和系统库一样非常简单。正如我们所见,我们在上面有自己的图书馆。怎么才能和节目一起打造?这也很容易。比如保持上面的目录结构,我们可以通过使用下面的CMakeLists.txt自动生成自己的库,完成test对库的依赖:
项目(测试)
set(CMAKE_CXX_FLAGS -g -Wall )
aux _ source _ directory(out/LIB _ SRC _ LIST)
add_library(out ${LIB_SRC_LIST})
link_libraries(out)
辅助源目录(。/SRC_LIST)
add_executable(测试{ SRC _ LIST })
呵呵,没什么新鲜的,设置目录的时候注意就行了,这么容易?是啊!
总结其实CMake比我上面说的强大多了。它甚至可以直接帮助生成安装文件和完成自动化测试。还有很多复杂的语法。这些功能只能靠大家自己慢慢学习和挖掘,不可能全部描述出来。以上只是简单工程管理中CMake有多简单的描述。基本上可以用于小规模的项目管理。相对来说,比手工编写makefile简单多了。比较适合普通使用,等源代码发布了,会轻松很多。它的语法也比GCC/G的命令行参数直观、好记得多,而且,随着KDE4吃螃蟹并且非常成功,在不久的将来,开源世界的构建工具可能会像cvs到svn一样,从autotools变成CMake的世界。其实从我的学习经验来看,CMake的学习难度要比autotools工具链简单很多。期待那一天:)
参考:《Why the KDE project switched to CMake -- and how (continued)》-我为什么学习CMake。
055-79000-非常好的教程
055-79000-一个更好的课程。
由于篇幅限制,本文一般只贴出代码主要关注的部分,代码带项目(或makefile)完整版(如果有的话)可以用Mercurial在Google Code下载。文章按照博客文章发表的日期存储在目录中。请直接使用Mercurial克隆库:
https://blog-sample-code.jtianling.googlecode.com/hg/
汞的用法见《Unix/Linux编程实践教程》。
如果你只是想浏览所有的代码,你也可以直接去谷歌代码,地址如下:
http://code.google.com/p/jtianling/source/browse?repo=博客-样本-代码