##cmake中一些预约义变量##react
系统信息正则表达式
开关选项express
##基本语法规则##windows
cmake变量使用${}方式取值,可是在IF控制语句中是直接使用变量名oop
环境变量使用$ENV{}方式取值,使用SET(ENV{VAR} VALUE)赋值ui
指令(参数1 参数2…).net
参数使用括弧括起,参数之间使用空格或分号分开。code
#以ADD_EXECUTABLE指令为例: ADD_EXECUTABLE(hello main.c func.c) #或者 ADD_EXECUTABLE(hello main.c;func.c)
指令是大小写无关的,参数和变量是大小写相关的。推荐你所有使用大写指令。blog
##部分经常使用命令列表##字符串
PROJECT PROJECT(projectname [CXX] [C] [Java]) 指定工程名称,并可指定工程支持的语言。支持语言列表可忽略,默认支持全部语言\
SET SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]]) 定义变量(能够定义多个VALUE,如SET(SRC_LIST main.c util.c reactor.c))
MESSAGE MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …) 向终端输出用户定义的信息或变量的值 SEND_ERROR, 产生错误,生成过程被跳过 STATUS, 输出前缀为—的信息 FATAL_ERROR, 当即终止全部cmake过程
ADD_EXECUTABLE ADD_EXECUTABLE(bin_file_name ${SRC_LIST}) 生成可执行文件
ADD_LIBRARY ADD_LIBRARY(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] SRC_LIST) 生成动态库或静态库 SHARED 动态库 STATIC 静态库 MODULE 在使用dyld的系统有效,若不支持dyld,等同于SHARED EXCLUDE_FROM_ALL 表示该库不会被默认构建
SET_TARGET_PROPERTIES 设置输出的名称,设置动态库的版本和API版本
CMAKE_MINIMUM_REQUIRED CMAKE_MINIMUM_REQUIRED(VERSION version_number [FATAL_ERROR]) 声明CMake的版本要求
ADD_SUBDIRECTORY ADD_SUBDIRECTORY(src_dir [binary_dir] [EXCLUDE_FROM_ALL]) 向当前工程添加存放源文件的子目录,并能够指定中间二进制和目标二进制的存放位置 EXCLUDE_FROM_ALL含义:将这个目录从编译过程当中排除
SUBDIRS deprecated,再也不推荐使用 (hello sample)至关于分别写ADD_SUBDIRECTORY(hello),ADD_SUBDIRECTORY(sample)
INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES([AFTER | BEFORE] [SYSTEM] dir1 dir2 … ) 向工程添加多个特定的头文件搜索路径,路径之间用空格分隔,若是路径包含空格,可使用双引号将它括起来,默认的行为为追加到当前头文件搜索路径的后面。 有以下两种方式能够控制搜索路径添加的位置:
CMAKE_INCLUDE_DIRECTORIES_BEFORE,经过SET这个cmake变量为on,能够将添加的头文件搜索路径放在已有路径的前面
经过AFTER或BEFORE参数,也能够控制是追加仍是置前
LINK_DIRECTORIES LINK_DIRECTORIES(dir1 dir2 …) 添加非标准的共享库搜索路径
TARGET_LINK_LIBRARIES TARGET_LINK_LIBRARIES(target lib1 lib2 …) 为target添加须要连接的共享库
ADD_DEFINITIONS 向C/C++编译器添加-D定义 ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),参数之间用空格分隔
ADD_DEPENDENCIES ADD_DEPENDENCIES(target-name depend-target1 depend-target2 …) 定义target依赖的其余target,确保target在构建以前,其依赖的target已经构建完毕
AUX_SOURCE_DIRECTORY AUX_SOURCE_DIRECTORY(dir VAR) 发现一个目录下全部的源代码文件并将列表存储在一个变量中 把当前目录下的全部源码文件名赋给变量DIR_HELLO_SRCS
EXEC_PROGRAM EXEC_PROGRAM(Executable [dir where to run] [ARGS <args>][OUTPUT_VARIABLE <var>] [RETURN_VALUE <value>]) 用于在指定目录运行某个程序(默认为当前CMakeLists.txt所在目录),经过ARGS添加参数,经过OUTPUT_VARIABLE和RETURN_VALUE获取输出和返回值,以下示例
#在src中运行ls命令,在src/CMakeLists.txt添加 EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUE LS_RVALUE) IF (not LS_RVALUE) MESSAGE(STATUS "ls result: " ${LS_OUTPUT}) # 缩进仅为美观,语法无要求 ENDIF(not LS_RVALUE)
INCLUDE
INCLUDE(file [OPTIONAL]) 用来载入CMakeLists.txt文件
INCLUDE(module [OPTIONAL])用来载入预约义的cmake模块
OPTIONAL参数的左右是文件不存在也不会产生错误 能够载入一个文件,也能够载入预约义模块(模块会在CMAKE_MODULE_PATH指定的路径进行搜索) 载入的内容将在处理到INCLUDE语句时直接执行
FIND_
FIND_FILE(<VAR> name path1 path2 …) VAR变量表明找到的文件全路径,包含文件名
FIND_LIBRARY(<VAR> name path1 path2 …) VAR变量表明找到的库全路径,包含库文件名
FIND_LIBRARY(libX X11 /usr/lib) IF (NOT libx) MESSAGE(FATAL_ERROR "libX not found") ENDIF(NOT libX)
FIND_PATH(<VAR> name path1 path2 …) VAR变量表明包含这个文件的路径
FIND_PROGRAM(<VAR> name path1 path2 …) VAR变量表明包含这个程序的全路径
FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED | COMPONENTS] [componets …]])
用来调用预约义在CMAKE_MODULE_PATH下的Find<name>.cmake模块,你也能够本身定义Find<name> 模块,经过SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录供工程使用
IF 语法:
IF (expression) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ELSE (expression) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDIF (expression) # 必定要有ENDIF与IF对应
IF (expression), expression不为:空,0,N,NO,OFF,FALSE,NOTFOUND或<var>_NOTFOUND,为真
IF (not exp), 与上面相反
IF (var1 AND var2)
IF (var1 OR var2)
IF (COMMAND cmd) 若是cmd确实是命令并可调用,为真
IF (EXISTS dir) IF (EXISTS file) 若是目录或文件存在,为真
IF (file1 IS_NEWER_THAN file2),当file1比file2新,或file1/file2中有一个不存在时为真,文件名需使用全路径
IF (IS_DIRECTORY dir) 当dir是目录时,为真
IF (DEFINED var) 若是变量被定义,为真
IF (var MATCHES regex) 此处var能够用var名,也能够用${var}
IF (string MATCHES regex)
#当给定的变量或者字符串可以匹配正则表达式regex时为真。好比: IF ("hello" MATCHES "ell") MESSAGE("true") ENDIF ("hello" MATCHES "ell")
数字比较表达式
按照字母表顺序进行比较
IF (variable STRLESS string)
IF (string STRLESS string)
IF (variable STRGREATER string)
IF (string STRGREATER string)
IF (variable STREQUAL string)
IF (string STREQUAL string)
#一个小例子,用来判断平台差别: IF (WIN32) MESSAGE(STATUS “This is windows.”) ELSE (WIN32) MESSAGE(STATUS “This is not windows”) ENDIF (WIN32) #上述代码用来控制在不一样的平台进行不一样的控制,可是,阅读起来却并非那么舒服,ELSE(WIN32)之类的语句很容易引发歧义。 能够SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) 这时候就能够写成: IF (WIN32) ELSE () ENDIF () 配合ELSEIF使用,可能的写法是这样: IF (WIN32) #do something related to WIN32 ELSEIF (UNIX) #do something related to UNIX ELSEIF(APPLE) #do something related to APPLE ENDIF (WIN32)
WHILE 语法:
WHILE(condition) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDWHILE(condition)
其真假判断条件能够参考IF指令
FOREACH
FOREACH指令的使用方法有三种形式:
语法:
``` FOREACH(loop_var arg1 arg2 ...) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDFOREACH(loop_var) ```
示例:
``` AUX_SOURCE_DIRECTORY(. SRC_LIST) FOREACH(F ${SRC_LIST}) MESSAGE(${F}) ENDFOREACH(F) ```
语法:
``` FOREACH(loop_var RANGE total) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDFOREACH(loop_var) ```
示例:
``` #从0到total以1为步进 FOREACH(VAR RANGE 10) MESSAGE(${VAR}) ENDFOREACH(VAR) #输出: #012345678910 ```
语法:
``` FOREACH(loop_var RANGE start stop [step]) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDFOREACH(loop_var) ``` 从start开始到stop结束,以step为步进, 注意:直到遇到ENDFOREACH指令,整个语句块才会获得真正的执行。 ``` FOREACH(A RANGE 5 15 3) MESSAGE(${A}) ENDFOREACH(A) \#输出: \#581114 ```
###cmake中如何生成动态库和静态库###
参考ADD_LIBRARY和SET_TARGET_PROPERTIES用法
###cmake中如何使用动态库和静态库(查找库的路径)###
参考INCLUDE_DIRECTORIES, LINK_DIRECTORIES, TARGET_LINK_LIBRARIES用法
###cmake中如何指定生成文件的输出路径###
如上ADD_SUBDIRECTORY的时候指定目标二进制文件输出路径(推荐使用下面这种)
使用SET命令从新定义EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH变量来指定最终的二进制文件的位置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
上面的两条命令一般紧跟ADD_EXECUTABLE和ADD_LIBRARY,与其写在同一个CMakeLists.txt便可
###cmake中如何增长编译选项###
使用变量CMAKE_C_FLAGS添加C编译选项
使用变量CMAKE_CXX_FLAGS添加C++编译选项
使用ADD_DEFINITION添加
###cmake中如何增长头文件路径###
参考INCLUDE_DIRECTORIES命令用法
###cmake中如何在屏幕上打印信息###
参考MESSAGE用法
###cmake中如何给变量赋值###
参考SET和AUX_SOURCE_DIRECTORY用法
建议: 在Project根目录先创建build,而后在build文件夹内运行cmake ..,这样就不会污染源代码, 若是不想要这些自动生成的文件了,只要简单的删除build文件夹就能够
参考 http://blog.csdn.net/wzzfeitian/article/details/40963457/