没有合适的资源?快使用搜索试试~ 我知道了~
cmake详细文档,有简单例子,而且系统详细,很不错。
资源推荐
资源详情
资源评论
前言
cmake 已经开发了 5,6 年的时间,如果没有 KDE4,也许不会有人或者 Linux 发行版本重视
cmake,因为除了 Kitware 似乎没有人使用它。通过 KDE4 的选型和开发,cmake 逐渐进入了人们的视
线,在实际的使用过程中,cmake 的优势也逐渐的被大家所认识,至少 KDE 的开发者们给予了 cmake
极高的评价,同时庞大的 KDE 项目使用 cmake 来作为构建工具也证明了 cmake 的可用性和大项目管理
能力。所以,cmake 应该感谢 KDE,也正因为如此,cmake 的开发者投入了 KDE 从 autotools 到
cmake 的迁移过程中,并相当快速和顺利的完成了迁移,现在整个 KDE4 开发版本全部使用 cmake 构
建。这也是促使我们学习 cmake 的原因,首先 cmake 被接受并成功应用,其次,cmake 的优势在实际
使用中不断的体现出来。
我们为什么不来认识一下这款优秀的工程构建工具呢?
在 2006 年 KDE 大会,听 cmake 开发者当面介绍了 cmake 之后,我就开始关注 cmake,并将
cmake 纳入了 Everest 发行版,作为系统默认组件。最近 QT-4.3 也正式进入了 Everest 系统,为 KDE4
构建完成了准备工作。但是,在学习 cmake 的过程中,发现官方的文档非常的少,而且错误也较多,比
如:在介绍 Find<Name>模块编写的文档中,模块名称为 FOO,但是后面却出现了
Foo_FIND_QUIETLY 的定义,这显然是错误的,这样的定义永远不可能有效,正确的定义是
FOO_FIND_QUIETLY。种种原因,促使我开始写一份“面向使用和实用”的 cmake 文档,也就是本
教程《cmake 实践》(Cmake Practice)
本文档是边学习边编写的成果,更像是一个学习笔记和 Tutorial,因此难免有失误或者理解不够透彻的地
方,比如,我仍然不能理解为什么绝大部分使用变量的情况要通过${}引用,而在 IF 语句中却必须直接
使用变量名。也希望能够有 cmake 的高手来指点迷津。
补:从 cmake 的 maillist,我找到了一些答案,原文是:The `IF(var)' or `IF(NOT var)' command
expects `var' to be the name of a variable. This is stated in CMake's manual. So, for your
situation `IF(${libX})' is the same as `IF(/usr/lib/xorg)' and then CMake will check the value of the
variable named `/usr/lib/xorg'.也就是说 IF 需要的是变量名而不是变量值这个文档是开放的,开放的目
的是为了让更多的人能够读到并且能够修改,任何人都可以对它作出修改和补充,但是,为了大家都能
够获得你关于 cmake 的经验和积累,如果你现错误或者添加了新内容后,请务必 CC 给我一份,让我们
共同把 cmake 掌握的更好。
一,初识 cmake
Cmake 不再使你在构建项目时郁闷地想自杀了.
1,背景知识:
cmake 是 kitware 公司以及一些开源开发者在开发几个工具套件(VTK)的过程中衍生品,最终形成体系,
成为一个独立的开放源代码项目。项目的诞生时间是 2001 年。其官方网站是 www.cmake.org,可以通
过访问官方网站获得更多关于 cmake 的信息。cmake 的流行其实要归功于 KDE4 的开发(似乎跟当年的
svn 一样,KDE 将代码仓库从 CVS 迁移到 SVN,同时证明了 SVN 管理大型项目的可用性),在 KDE
开发者使用了近 10 年 autotools 之后,他们终于决定为 KDE4 选择一个新的工程构建工具,其根本原因
用 KDE 开发者的话来说就是:只有少数几个“编译专家”能够掌握 KDE 现在的构建体系
(admin/Makefile.common),在经历了 unsermake, scons 以及 cmake 的选型和尝试之后,KDE4 决定
CMake有三步:
1、根据编译器产生相应编译器的源码编译环境
2、根据相应编译器编译程序
3、编译执行程序可安装到任一指定路径中
使用 cmake 作为自己的构建系统。在迁移过程中,进展异常的顺利,并获得了 cmake 开发者的支持。所
以,目前的 KDE4 开发版本已经完全使用 cmake 来进行构建。像 kdesvn,rosegarden 等项目也开始使用
cmake,这也注定了 cmake 必然会成为一个主流的构建体系。
2,特点:
cmake 的特点主要有:
1,开放源代码,使用类 BSD 许可发布。http://cmake.org/HTML/Copyright.html
2,跨平台,并可生成 native 编译配置文件,在 Linux/Unix 平台,生成 makefile,在苹果平台,可
以生成 xcode,在 Windows 平台,可以生成 MSVC 的工程文件。
3,能够管理大型项目,KDE4 就是最好的证明。
4,简化编译构建过程和编译过程。Cmake 的工具链非常简单:cmake+make。
5,高效虑,按照 KDE 官方说法,CMake 构建 KDE4 的 kdelibs 要比使用 autotools 来构建
KDE3.5.6 的 kdelibs 快 40%,主要是因为 Cmake 在工具链中没有 libtool。
6,可扩展,可以为 cmake 编写特定功能的模块,扩充 cmake 功能。
3,问题,难道就没有问题?
1,cmake 很简单,但绝对没有听起来或者想象中那么简单。
2,cmake 编写的过程实际上是编程的过程,跟以前使用 autotools 一样,不过你需要编写的是
CMakeLists.txt(每个目录一个),使用的是”cmake 语言和语法”。
3,cmake 跟已有体系的配合并不是特别理想,比如 pkgconfig,您在实际使用中会有所体会,虽然
有一些扩展可以使用,但并不理想。
4,个人的建议:
1,如果你没有实际的项目需求,那么看到这里就可以停下来了,因为 cmake 的学习过程就是实践
过程,没有实践,读的再多几天后也会忘记。
2,如果你的工程只有几个文件,直接编写 Makefile 是最好的选择。
3,如果使用的是 C/C++/Java 之外的语言,请不要使用 cmake(至少目前是这样)
4,如果你使用的语言有非常完备的构建体系,比如 java 的 ant,也不需要学习 cmake,虽然有成功
的例子,比如 QT4.3 的 csharp 绑定 qyoto。
5,如果项目已经采用了非常完备的工程管理工具,并且不存在维护问题,没有必要迁移到 cmake
4,如果仅仅使用 qt 编程,没有必要使用 cmake,因为 qmake 管理 Qt 工程的专业性和自动化程度比
cmake 要高很多。
(三) 初试 cmake – CMake 的 helloworld
Hello world,世界 你好
本节选择了一个最简单的例子 Helloworld 来演练一下 cmake 的完整构建过程,本节并不会深入的探讨
cmake,仅仅展示一个简单的例子,并加以粗略的解释。我们选择了 Everest Linux 作为基本开发平台,
因为这个只有一张 CD 的发行版本,包含了 gcc- 4.2/gtk/qt3/qt4 等完整的开发环境,同时,系统默认集
成了 cmake 最新版本 2.4.6。
1,准备工作:
首先,在/backup 目录建立一个 cmake 目录,用来放置我们学习过程中的所有练习。mkdir -p /backup/
cmake 以后我们所有的 cmake 练习都会放在/backup/cmake 的子目录下(你也可以自行安排目录,这个
并不是限制,仅仅是为了叙述的方便) 然后在 cmake 建立第一个练习目录 t1
cd /backup/cmake
mkdir t1
cd t1
在 t1 目录建立 main.c 和 CMakeLists.txt(注意文件名大小写):
main.c 文件内容:
//main.c
#include <stdio.h>
int main()
{
printf(“Hello World from t1 Main!n”);
return 0;
}
CmakeLists.txt 文件内容:
PROJECT (HELLO)
SET(SRC_LIST main.c)
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello SRC_LIST)
2,开始构建
所有的文件创建完成后,t1 目录中应该存在 main.c 和 CMakeLists.txt 两个文件
接下来我们来构建这个工程,在这个目录运行:
cmake . (注意命令后面的点号,代表本目录)。
输出大概是这个样子:
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Check size of void*
-- Check size of void* - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- This is BINARY dir /backup/cmake/t1
-- This is SOURCE dir /backup/cmake/t1
-- Configuring done
-- Generating done
-- Build files have been written to: /backup/cmake/t1
再让我们看一下目录中的内容:
你会发现,系统自动生成了:
CMakeFiles, CMakeCache.txt, cmake_install.cmake 等文件,并且生成了
Makefile.
现在不需要理会这些文件的作用,以后你也可以不去理会。最关键的是,它自动生成了
Makefile.
然后进行工程的实际构建,在这个目录输入 make 命令,大概会得到如下的彩色输出:
t1
|----main.c
|----CMakeLists.txt
Scanning dependencies of target hello
[100%] Building C object CMakeFiles/hello.dir/main.o
Linking C executable hello
[100%] Built target hello
如果你需要看到 make 构建的详细过程,可以使用 make VERBOSE=1 或者 VERBOSE=1
make 命令来进行构建。
这时候,我们需要的目标文件 hello 已经构建完成,位于当前目录,尝试运行一下:
./hello
得到输出:
Hello World from Main
恭喜您,到这里为止您已经完全掌握了 cmake 的使用方法。
3,简单的解释:
我们来重新看一下 CMakeLists.txt,这个文件是 cmake 的构建定义文件,文件名是大小写相关的,
如果工程存在多个目录,需要确保每个要管理的目录都存在一个 CMakeLists.txt。(关于多目录构建,后
面我们会提到,这里不作过多解释)。
上面例子中的 CMakeLists.txt 文件内容如下:
PROJECT (HELLO)
SET(SRC_LIST main.c)
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})
PROJECT 指令的语法是:
PROJECT(projectname [CXX] [C] [Java])
你可以用这个指令定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的,默认
情况表示支持所有语言。这个指令隐式的定义了两个 cmake 变量:<projectname>_BINARY_DIR 以及
<projectname>_SOURCE_DIR,这里就是 HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR(所
以 CMakeLists.txt 中两个 MESSAGE 指令可以直接使用了这两个变量),因为采用的是内部编译,两个
变量目前指的都是工程所在路径/backup/cmake/t1,后面我们会讲到外部编译,两者所指代的内容会有
所不同。同时 cmake 系统也帮助我们预定义了 PROJECT_BINARY_DIR 和
PROJECT_SOURCE_DIR 变量,他们的值分别跟 HELLO_BINARY_DIR 与
HELLO_SOURCE_DIR 一致。
为了统一起见,建议以后直接使用 PROJECT_BINARY_DIR,PROJECT_SOURCE_DIR,即
使修改了工程名称,也不会影响这两个变量。如果使用了<projectname>_SOURCE_DIR,修改工程名
称后,需要同时修改这些变量。
SET 指令的语法是:SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
现阶段,你只需要了解 SET 指令可以用来显式的定义变量即可。
比如我们用到的是 SET(SRC_LIST main.c),如果有多个源文件,也可以定义成:
SET(SRC_LIST main.c t1.c t2.c)。
MESSAGE 指令的语法是:
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display"
...)
这个指令用于向终端输出用户定义的信息,包含了三种类型:
SEND_ERROR,产生错误,生成过程被跳过。
SATUS,输出前缀为—的信息。
FATAL_ERROR,立即终止所有 cmake 过程.
我们在这里使用的是 STATUS 信息输出,演示了由 PROJECT 指令定义的两个隐式变量
HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR。
ADD_EXECUTABLE(hello ${SRC_LIST})
定义了这个工程会生成一个文件名为 hello 的可执行文件,相关的源文件是 SRC_LIST 中定义的源
文件列表, 本例中你也可以直接写成 ADD_EXECUTABLE(hello main.c)。
在本例我们使用了${}来引用变量,这是 cmake 的变量应用方式,但是,有一些例外,比如在 IF 控
制语句,变量是直接使用变量名引用,而不需要${}。如果使用了${}去应用变量,其实 IF 会去判断名为
${}所代表的值的变量,那当然是不存在的了。
将本例改写成一个最简化的 CMakeLists.txt:
PROJECT(HELLO)
ADD_EXECUTABLE(hello main.c)
4,基本语法规则
前面提到过,cmake 其实仍然要使用”cmake 语言和语法”去构建,上面的内容就是所谓的 ”cmake
语言和语法”,最简单的语法规则是:
1,变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名
2,指令(参数 1 参数 2...)
参数使用括弧括起,参数之间使用空格或分号分开。
以上面的 ADD_EXECUTABLE 指令为例,如果存在另外一个 func.c 源文件,就要写成:
ADD_EXECUTABLE(hello main.c func.c)或者
ADD_EXECUTABLE(hello main.c;func.c)
3,指令是大小写无关的,参数和变量是大小写相关的。但,推荐你全部使用大写指令。
上面的 MESSAGE 指令我们已经用到了这条规则:
MESSAGE(STATUS “This is BINARY dir” ${HELLO_BINARY_DIR})
也可以写成:
MESSAGE(STATUS “This is BINARY dir ${HELLO_BINARY_DIR}”)
这里需要特别解释的是作为工程名的 HELLO 和生成的可执行文件 hello 是没有任何关系的。
hello 定义了可执行文件的文件名,你完全可以写成:
ADD_EXECUTABLE(t1 main.c)
编译后会生成一个 t1 可执行文件。
5,关于语法的疑惑
cmake 的语法还是比较灵活而且考虑到各种情况,比如 SET(SRC_LIST main.c)也可以写成
SET(SRC_LIST “main.c”)是没有区别的,但是假设一个源文件的文件名是 fu nc.c(文件名中间包含了
空格)这时候就必须使用双引号,如果写成了 SET(SRC_LIST fu nc.c),就会出现错误,提示你找不到
剩余29页未读,继续阅读
资源评论
a88301000
- 粉丝: 3
- 资源: 7
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功