【接触CMake有一段时间了,基于自己的经验再总结下,迭代下理解版本】
一、语法篇对于快速上手的需求不需要通读所有的技巧,选些重要的来进行记录,冷门、偏门的后期补充。
- PROJECT指令
语法讲解:方括号中内容为可选,意为工程所支持语言。该语法含义为指定工程名称,当语言列表为空时,代表支持所有语言
- 几个隐式指令
语法格式:<projectname>_BINARY_DIR、<projectname>_SOURCE_DIR
语法讲解:projectname为project指令定义的工程名称,这两个变量代表工程所在的路径。cmake还预定义了PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR变量,
它们值分别跟HELLO_BINARY_DIR和HELLO_SOURCE_DIR一致,是个范称,即使修改了工程名称,也不会影响这两个变量。如果使用了<projectname>_SOURCE_DIR, 修改工程名称后,需要同时修改这些变量。
- set指令
语法讲解:显示地定义变量。
例 如:单个源文件set(SRC_LIST hhh.cxx),多个源文件时set(SRC_LIST t1.cxx t2.cxx t3.cxx)
- MESSAGE指令
语法讲解:SEND_ERROR产生错误,生成过程被跳过,STATUS输出前缀为一的信息,FATAL_ERROR立即终止所有cmake过程,通常用STATUS比较多
例 如:MESSAGE(STATUS, "This is a Binary dir ", ${PROJECT_BINARY_DIR})
- ADD_SUBDIRECTORY指令
语法讲解:用于向当前工程添加存放源文件的子目录,并可指定中间二进制和目标二进制存放位置。EXCLUDE_FROM_ALL参数为将这个目录从编译过程中排除。
例 如:ADD_SUBDIRECTORY (src bin)
将src子目录加入工程,并指定编译输出(包含编译中间结果)路径为bin目录。如果不进行bin目录指定,那么编译结果(包括中间结果)都存放在build/src目录 对应),指定bin目录后,相当于在编译时将src重命名为bin,所有的中间结果和目标二进制都将存放在bin目录
WARNING:注意SUBDIRS指令,一般不推荐使用。语法为SUBDIRS(dir1 dir2....),它可以一次添加多个子目录,并且即使外部编译,子目录体系仍然会被保存
如果将上面示例ADD_SUBDIRECTORY(src bin)修改为SUBDIRS(src),那么在build目录中将出现一个src目录,生成的目标代码hello将存放在src目录中。
自定义保存目标二进制文件位置时,不论是SUBDIRS还是ADD_SUBDIRECTORY指令(不论是否制定编译输出目录),都可用SET指令重新定义EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH变量来指定最终的目标二进制位置(指最终生成的hello或最终共享库,不包含编译生成的中间文件),
如:SET (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)BINARY_DIR目录指的是编译发生的当前目录,如果是内部编译,则相当于SOURCE_DIR目录,即为工程代码所在目录;如果是外部编译,指的是外部编译所在目录,即为本例中build目录,故上述代码执行的输出路径为:build/bin和库的输出路径为build/lib。这两条指令写在哪个目录下的CMakeLists.txt文件中呢?一个简单原则:在哪里ADD_EXECUTABLE或ADD_LIBRARY,如果需要改变目标存放路径,就在哪里加入上述定义。在本例则为src下的CMakeLists.txt
- INSTALL指令
- ads
- 基本常用语法规则
2、指令_(参数1_参数2....)
_表示在格式上中间用空格隔开。参数使用括弧扩起,参数之间使用空格或分号分开
如:add_executable (Tutorial tutorial.cxx)
3、指令不分大小写,参数和变量区分大小写。一般建议全部使用大写指令
如: MESSAGE(STATUS "This is SOURCE dir" ${PROJECT_SOURCE_DIR})
也可写成:MESSAGE(STATUS "This is SOURCE dir ${PROJECT_SOURCE_DIR}")
- 一些技巧
2、make clean 对构建结果进行清理
(补充make一些常见命令作对比,后期有专题介绍)
make 根据makefile编译源代码,链接,生成目标文件,可执行文件
make clean清除上次make命令所产生的object文件(后缀为.o文件)及可执行文件
make install将编译成功的可执行文件安装到系统目录中,一般为/usr/local/bin目录
make dist 产生发布软件包文件(即distribution package)将可执行文件和相关文件打包成一个tar.gz压缩的文件用来作为发布软件的软件包。它一般在当前目录下生成一 个名字类似“PACKAGE-VERSION.tar.gz”文件。PACKAGE和VERSION是configure.in中定义的AM_INIT_AUTOMAKE(PACKAGE_VRESION)
make distcheck 生成发布软件包并对其进行测试检查,以确定发布包的正确性。这个操作将自动把压缩包文件解开,然后执行configure命令,并且执行make来编译不出 现错误,最后提示软件包准备好,可以发布
make distclean类似make clean,但同时也将configure生成的文件全部删除掉,包括makefile。也就是make distclean要删除所有文件,而make clean则删除之前编译的 可执行文件及配置文件
3、cmake不支持make distclean
内部构建与外部构建
内部构建:会生成一些无法自动删除的中间文件
外部构建:另外建立目录,将中间文件保存在编译目录。外部构建对原有工程没有任何影响,所有动作全部发生在编译目录
cmake推荐外部构建
4、如何安装打包代码、安装代码
打包:
两种方法:一种从代码编译后直接make install安装,一种是打包时指定目录安装
如:
DESTDIR=
install:
mkdir -p $(DESTDIR)/usr/bin
install -m 755 hello $(DESTDIR)/usr/bin
可通过:
make install
将hello直接安装到/usr/bin目录,也可通过
make install DESTDIR=/tmp/test
将它安装在/tmp/test/usr/bin目录,打包时经常被使用。稍微复杂一点还需定义PREFIX,一般autotools工程,会运行这样指令:
./configure -prefix=/usr或者./configure --prefix=/usr/local
来指定PREFIX,即将上面Makefile改写为:
DESTDIR=
PREFIX=/usr
install:
mkdir -p $(DESTDIR)/$(PREFIX)/bin
install -m 755 hello $(DESTDIR)/$(PREFIX)/bin
安装:
安装时引入一个新的cmake指令INSTALL和一个非常有用的变量:CMAKE_INSTALL_PREFIX,它的默认路径定义为:/usr/local
CMAKE_INSTALL_PREFIX类似于configure脚本的-prefix。常见使用方法为:cmake -DCMAKE_INSTALL_PREFIX=/usr.
采用外部构建(out-of-source),在工程目录下build目录
需求:
1、为工程添加一个子目录src,用来放置工程源码
2、添加一个子目录doc,用来放置工程文档
3、在工程目录添加文本文件COPYRIGHT,README
4、在工程目录添加一个runhello.sh脚本,用来调用hello二进制
5、将构建后的目标文件放入构建目录bin子目录中
6、最终安装这些文件:将hello二进制文件与runhello.sh安装至/usr/local/bin,将doc目录内容以及COPYRIGHT/README安装到/usr/share/doc/cmake/,将 在/backup/cmake/目录下建立目录,将工程中的main.cxx和CMakeLists.txt拷贝到目录中
实现:
1、准备
在/backup/cmake/目录下建立t2目录
在t1工程的main.cxx和CMakeLists.txt拷贝到t2目录
2、添加子目录src
三、参考文档
1、make clean 与make distclean 区别 http://www.cnblogs.com/hnrainll/archive/2011/06/08/2075052.html
2、cmake教程 http://wenku.baidu.com/view/83a51d150b4e767f5acfceee.html