使用cef3替代chromium内核开发产品过程当中,第一次接触到系统构建,使用了最多见的CMake。CMake虽然在构建系统中用的比较多,可是使用到的程序员仍是不多的。如今在国内能找到的相关资料和博客比较多,本人在学习中也看了不少人的博客,好比 CMake学习(一) , CMake语法之流程控制 等。再次感谢这些做者的分享。下边提供一些系统学习的资料。html
CMake的官网地址:http://www.cmake.org/java
CMake主要的文档《learning_cmake》 《CMake Practice》,这个百度上搜索一下,很容易下载到。python
学习CMake以前,借用下 《CMake Practice》中的一段话,若是你的状况符合如下几条就不要浪费时间在CMake上。程序员
1,若是你没有实际的项目需求,那么看到这里就能够停下来了,由于cmake的学习过程就是实践过程,没有实践,读的再多几天后也会忘记。
2,若是你的工程只有几个文件,直接编写Makefile是最好的选择。
3,若是使用的是C/C++/Java以外的语言,请不要使用cmake(至少目前是这样)。
4,若是你使用的语言有很是完备的构建体系,好比java的ant,也不须要学习cmake,虽然有成功的例子,好比QT4.3的csharp绑定qyoto。
5,若是项目已经采用了很是完备的工程管理工具,而且不存在维护问题,没有必要迁移到cmake。
6,若是仅仅使用qt编程,没有必要使用cmake,由于qmake管理Qt工程的专业性和自动化程度比cmake要高不少。编程
学习CMake以前,最好能找到一个比较简单地例子对照教程看,而且一开始编写一些简单地例子。这样不只能学得快,也容易创建学习的自信。编程语言
下边主要讲三点,也是最经常使用到的三点。函数
1、CMake经常使用命令:工具
CMakelist中,命令名字是不区分大小写的,而参数和变量是大小写相关的。学习
CMake中使用"#"表示注释该行代码。ui
命令:
与其余语言编程语言不一样的是,CMake脚本的语法中没有赋值操做,不管是赋值,仍是比较、判断操做,都是经过内置命令来完成的,例如"set(),math()等"。全部的内置命令调用形式为:
command(arg1 arg2 arg3 ... argn)
每一个参数均以空格,或者分号分割。注:不建议使用分号分割参数.
message():显示一个消息。如message("Hello world");
cmake_minimum_required():须要的最低版本; cmake_minimum_required(version 2.6)
project():项目的名称 如project(hello)
set():Cmake中的赋值操做都是经过这个来作的。如 SET(HELLO_SRCS Hello.c Hello.cpp world.c world.cpp)
add_definitions():设置编译选项;
subdirs:CMake 是以递归的方式工做;处理完当前目录,再去 SUBDIRS 中的目录
add_library :生成一个连接库;
add_executable:添加生成文件;如:ADD_EXECUTABLE (Hello ${HELLO_SRCS})
add_dependencies:包含一个依赖库文件夹;
add_subdirectory:向当前工程添加存放源文件的子目录;
aux_source_directory :不在当前目录下的其余地方的源文件;
include_directories: 指明文件所在路径;
set_target_properties:设置文件为另一个名字。set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
source_group:当文件都在同一个路径下面使用
2、CMake变量以及变量的引用
CMake中的变量无需声明,而且没有类型概念,这一点相似于python;变量能够认为都是全局的,哪怕在一个宏中定义的变量,也能够在宏的外面被访问到;全部的变量都是一个列表变量,下文在举例时会详细说明这一点;CMake对于变量是大小写敏感的。
在CMake中,有两种引用方式:对于变量值的引用,和直接引用这个变量自己,使用方式分别是:${varName} 和 varName。
3、CMake的宏与函数
同大多数脚本语言同样,CMake中也有宏和函数的概念,关键字分别为"macro"和"function",具体用法以下:
# 宏
macro( [arg1 [arg2 [arg3 ...]]])
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endmacro()
# 函数
function( [arg1 [arg2 [arg3 ...]]])
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endfunction()
以简单的求和函数为例,咱们来看宏的一个示例:
macro(sum outvar)
set(_args ${ARGN})
set(result 0)
foreach(_var ${_args})
math(EXPR result "${result}+${_var}")
endforeach()
set(${outvar} ${result})
endmacro()
sum(addResult 1 2 3 4 5)
message("Result is :${addResult}")
上面是一段求和宏定义,咱们来解读一下代码:"${ARGN}"是CMake中的一个变量,指代宏中传入的多余参数。由于咱们这个宏sum中只定义了一个 参数"outvar",其他须要求和的数字都是不定形式传入的,因此须要先将多余的参数传入一个单独的变量中。固然,在这个示例中,第一行代码显得多余, 由于彷佛不必将额外参数单独放在一个变量中,可是建议这么作。对上面这个宏再进一步增强:若是咱们想限制这个宏中传入的参数数目(尽管在这个宏中实际上 是没必要要的),那么能够将宏改写一下:
macro(sum outvar)
set(_args ${ARGN})
list(LENGTH _args argLength)
if(NOT argLength LESS 4) # 限制不能超过4个数字
message(FATAL_ERROR "to much args!")
endif()
set(result 0)
foreach(_var ${ARGN})
math(EXPR result "${result}+${_var}")
endforeach()
set(${outvar} ${result})
endmacro()
sum(addResult 1 2 3 4 5)
message("Result is :${addResult}")
而CMake中的函数("function")与宏惟一的区别就在于,函数不能像宏那样将计算结果传出来(也不是彻底不能,只是复杂一些),而且函数中的变量是局部的,而宏中的变量在外面也能够被访问到,请看下例:
macro(macroTest)
set(test1 "aaa")
endmacro()
function(funTest)
set(test2 "bbb")
endfunction()
macroTest()
message("${test1}")
funTest()
message("${test2}")
运行这段代码后,只会打印出一条信息"aaa",由此能够看到宏与函数的区别