因为在使用OPENCV以及caffe的过程中都接触到了许多关于CMake的使用,于是就想了解一下CMake究竟是怎样一个东西,有什么作用。顺便做一个学习笔记。 本文参考《CMake Practice》这篇文章完成,旨在指导用户快速使用CMake,如果需要更详细的内容,请通读《CMake Practice》这篇文章。下载路径:http://sewm.pku.edu.cn/src/paradise/reference/CMake Practice.pdf
CMake是一个工程构建工具,能够自动生产makefile文件,方便构建编译文件,链接库,安装文件等。
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 功能。
cmake基本语法规则: 前面提到过,cmake 其实仍然要使用”cmake 语言和语法”去构建,上面的内容就是所谓的”cmake 语言和语法”,最简单的语法规则是: 1,变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名 2,指令(参数 1 参数 2…) 参数使用括弧括起,参数之间使用空格或分号分开。 3,指令是大小写无关的,参数和变量是大小写相关的。但,推荐你全部使用大写指令。
每个需要编译的目录(子目录)都要有一个CMakeLists.txt文件 在工程目录下的CMakeLists.txt文件称作工程CMake文件,在这个文件里需要指出工程名字,需要编译的子目录,例如:
{ cmake_minimum_required(VERSION 3.5) PROJECT(HELLO) ADD_SUBDIRECTORY(src) }注:
cmake_minimum_required(VERSION 3.5): 功能说明: 规定cmake程序的最低版本。可选 如果CMakeLists.txt文件中使用了一些高版本cmake特有的一些命令的时候,就需要加上这样一行,提醒用户升级到该版本之后再执行cmakePROJECT 指令: 功能说明: 声明一个工程 语法: PROJECT(projectname [CXX] [C] [Java]) 参数说明:
projectname:定义工程名称 [CXX]…:指定工程支持的语言列表,可忽略的,默认表示支持所有语言这个指令隐式的定义了两个 cmake 变量: ==_BINARY_DIR== 以及 ==_SOURCE_DIR==。 前者表示编译输出的路径;后者表示工程所在的路径。
接下来给出一个在子目录的CMakeLists.txt文件
{ INCLUDE_DIRECTORIES(/usr/include/thrift) SET(SRC_LIST main.cc rpc/CRMasterCaller.cpp rpc/CRNode_server.skeleton.cpp rpc/Schd_constants.cpp rpc/CRMaster.cpp rpc/CRNode.cpp rpc/Schd_types.cpp task/TaskExecutor.cpp task/TaskMoniter.cpp util/Const.cpp util/Globals.cc util/utils.cc util/Properties.cpp ) ADD_EXECUTABLE(crnode ${SRC_LIST}) LINK_DIRECTORIES(/usr/lib /lib/local/lib) TARGET_LINK_LIBRARIES(crnode log4cpp thrift) MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR}) MESSAGE(STATUS "This is SOURCE dir " ${HELLO_SOURCE_DIR}) INSTALL(TARGETS crnode RUNTIME DESTINATION bin ) }注:
INCLUDE_DIRECTORIES 指令: 功能说明: 向工程添加多个特定的头文件搜索路径 语法: INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 …) 参数说明: [AFTER|BEFORE]:控制路径添加顺序,追加or置前INSTALL 指令: 功能说明: 将编译生成的文件分类安装到制定的目录路径。可分成好几类文件的安装命令
安装目标文件 语法:
{ INSTALL(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME] [DESTINATION < dir >] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT < component >] [OPTIONAL] ] [...]) }举例说明:
{ INSTALL(TARGETS myrun mylib mystaticlib RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION libstatic) }上面的例子会将: 将: 1) 可执行二进制文件 myrun, 安装到${CMAKE_INSTALL_PREFIX}/bin 目录 2) 动态库 libmylib, 安装到${CMAKE_INSTALL_PREFIX}/lib 目录 3) 静态库 libmystaticlib, 安装到${CMAKE_INSTALL_PREFIX}/libstatic 目录
安装普通文件 语法:
{ INSTALL(FILES files... DESTINATION <dir> [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [RENAME <name>] [OPTIONAL]) }举例说明:
{ INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake/t2) }上面的例子会将: 把文件COPYRIGHT、README, 安装到目录 < prefix >/share/doc/cmake/t2下
安装非目标文件的可执行程序文件(脚本文件) 语法:
{ INSTALL(PROGRAMS files... DESTINATION <dir> [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [RENAME <name>] [OPTIONAL]) }举例说明:
{ INSTALL(PROGRAMS runhello.sh DESTINATION bin) }上面的例子会将: 把可执行文件runhello.sh, 安装到目录< prefix >/bin下
安装目录 语法:
{ INSTALL(DIRECTORY dirs... DESTINATION <dir> [FILE_PERMISSIONS permissions...] [DIRECTORY_PERMISSIONS permissions...] [USE_SOURCE_PERMISSIONS] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [[PATTERN <pattern> | REGEX <regex>] [EXCLUDE] [PERMISSIONS permissions...]] [...]) }举例说明:
{ INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj PATTERN "CVS" EXCLUDE PATTERN "scripts/*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ) }上面的例子会: 将 icons 目录安装到 < prefix >/share/myproj 将 scripts/中的内容安装到/share/myproj 不包含目录名为 CVS 的目录 对于 scripts/*文件指定权限为 OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ
假设我们此时已经完成了两个CMakeLists.txt文件的编写,可以执行cmake命令生成Makefile文件了。此时我们由两种方法可以执行cmake、编译和安装:
cmake . make或者
mkdir build cd build cmake .. make两种方法最大的不同在于执行cmake和make的工作路径不同。 第一种方法中,cmake生成的所有中间文件和可执行文件都会存放在项目目录中,称为“内部构建” 而第二种方法中,中间文件和可执行文件都将存放再build目录中。称为“外部构建”。 cmake强烈推荐使用外部构建的方法。