前言 介绍
cmake是一个开源的,跨平台的工具,可以用来构建,测试和打包软件。cmake使用简单的独立于平台和编译器的配置文件,来控制软件编译过程,并且可以生成你选择的编译环境中可以可以使用的makefile文件和工程目录。cmake是kitware公司开发,以满足更强大和跨平台的构建环境的需求,比如ITK和VTK.
(来自 官网www.cmake.org)
cmake教程
cmake教程提供了分步的指导,可以覆盖常见的问题。从这个教程里,可以看到各个不同的模块怎么协同工作的。
这个教程和代码示例可以在cmake的开源代码help/guide/tutorial中找到。每一个步骤都有一个子文件夹。教程提供的示例是渐进式的,所以每一步都包括了上一步的完整的解决方案。
简单的开头
最基础的工程是构建一个可执行文件。一个三行的CMakefileList.txt包括了所有需要的内容。
cmake_minimum_required (VERSION 2.8)
project (HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})
add_executable(test ${SRC_LIST})
note:该例子中的command都用了小写。CMake不区分大小写。
构建并运行
现在我们就可以构建了。cmake建议外编译(建立build目录专门用来编译)
step1目录中包含了如上 CMakeLists.txt 和 main.cpp
- 首先建立一个step1_build目录
整个目录下:
执行步骤如下:
- 进入step1_build目录,执行step1中的cmakelist
cmake …/step1 - 查看生产了Makefile
- 执行make 生成可执行程序
指令
基本语法规则
1,变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名
2,指令(参数 1 参数 2…)
PROJECT指令
PROJECT(projectname [CXX] [C] [Java])
定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的, 默认情况表示支持所有语言。这个指令隐式的定义了两个 cmake 变量:
_BINARY_DIR 以及_SOURCE_DIR,这里就是
HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR,同时 cmake 系统也帮助我们预定义了 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR
变量,他们的值分别跟 HELLO_BINARY_DIR 与 HELLO_SOURCE_DIR 一致
SET 指令的语法是:
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
SET 指令可以用来显式的定义变量,如果有多个源文件,也可以定义成:
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 过程
ADD_EXECUTABLE指令
ADD_EXECUTABLE(hello ${SRC_LIST})
定义了这个工程会生成一个文件名为 hello 的可执行文件,相关的源文件是 SRC_LIST 中 定义的源文件列表
ADD_SUBDIRECTORY指令
这个指令用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存 放的位置
比如ADD_SUBDIRECTORY(src bin) 将src加入工程,并且指定编译输出包括中间结果存放到bin目录,如果不指定会输出到build/src下(全部默认为外部编译,在build下编译)
EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH 变量 可以指定最终的目标二进制的位置,从而使上述指令的行为改变。一个简单的原则,在哪里用了 ADD_EXECUTABLE 或 ADD_LIBRARY, 如果需要改变目标存放路径,就在哪里加入上述的定义
ADD_LIBRARY指令
这个指令是用来生成库文件
ADD_LIBRARY(libname [SHARED|STATIC|MODULE]
[EXCLUDE_FROM_ALL]
source1 source2 ... sourceN)
SHARED,动态库
STATIC,静态库
MODULE,在使用 dyld 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。
EXCLUDE_FROM_ALL 参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手 工构建
SET_TARGET_PROPERTIES指令
设置target的属性
SET_TARGET_PROPERTIES(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
比如SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME “hello”)
此时输出为hello_static输出为hello
INCLUDE_DIRECTORIES指令
INCLUDE_DIRECTORIES(dir)
这条指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割,如果路径 中包含了空格,可以使用双引号将它括起来,默认的行为是追加到当前的头文件搜索路径的 后面,通过 AFTER 或者 BEFORE 参数,也可以控制是追加还是置前
注意此处的目录是相对于CMakelist.txt的相对目录
LINK_DIRECTORIES指令
添加非标准的共享库搜索路径
LINK_DIRECTORIES(directory1 directory2 ...)
实际上,这个command不被推荐,更好的选择是使用环境变量 CMAKE_INCLUDE_PATH和CMAKE_LIBRARY_PATH并且用FIND_PATH配合来添加第三方库的头文件和库
TARGET_LINK_LIBRARIES指令
TARGET_LINK_LIBRARIES(target library1
<debug | optimized> library2
...)
target添加共享库
AUX_SOURCE_DIRECTORY 指令
aux_source_directory(<dir> <variable>)
AUX_SOURCE_DIRECTORY(src/ FILES)查找src下所有的文件,并添加到FILES变量中
FIND_PACKAGE指令
FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE]
[[REQUIRED|COMPONENTS] [componets...]])
扩展cmake
其中name对应配置文件文件名中的name findname.cmake ,比如FIND_PACKAGE(hello…)
Findhello.cmake,并且要把该配置文件的目录加入到CMAKE_MODULE_PATH, 比如SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
新手遇到的问题
-
不生成makefile
执行下cmake . -G “Unix Makefiles” -
link时找不到库
LINK_DIRECTORIES(/tmp/usr/lib/)
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main hello)
注意顺序 LINK_DIRECTORIES要放在ADD_EXECUTABLE前面,否则还是会提示找不到库
TARGET_LINK_LIBRARIES要在ADD_EXECUTABLE 后面,否则会提示找不到main -
cmake文件定义后,FIND PACKAGE依然找不到
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 这个配置必须放在ADD_SUBDIRECTORY的后面