可以设置的变量
使用方式cmake -DCMAKE_INSTALL_PREFIX=yourpath
或在CMAKE-GUI中勾选
-
CMAKE_INSTALL_PREFIX
库编译后安装前缀 -
CMAKE_INSTALL_CONFIG_NAME
安装使用的类型、debug|realease -
CMAKE_VERBOSE_MAKEFILE
是否在make过程中打印出详细的内容 - EXECUTABLE_OUTPUT_PATH 执行程序输出路径,系统默认值
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
- LIBRARY_OUTPUT_PATH lib文件输出路径
- CMAKE_MODULE_PATH 设置第三方cmake模块的目录,如SET
(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
-
BUILD_SHARED_LIBS
这个开关用来控制默认的库编译方式,如果使用ADD_LIBRARY
并没有指定库类型的情况下,默认编译生成的库都是静态库。
SET(BUILD_SHARED_LIBS ON)
后,默认生成的为动态库。
可以设置的环境变量
-
CMAKE_INCLUDE_PATH
CMAKEfind_file()
andfind_path()
查找文件的路径 -
CMAKE_LIBRARY_PATH
CMAKEfind_library()
查找依赖库的路径 -
CMAKE_INCLUDE_CURRENT_DIR
自动添加CMAKE_CURRENT_BINARY_DIR
和CMAKE_CURRENT_SOURCE_DIR
到当前处理
的CMakeLists.txt
。相当于在每个CMakeLists.txt
加入:
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
-
CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
将工程提供的头文件目录始终至于系统头文件目录的前面,当你定义的头文件确实跟系统发生冲突时可以提供一些帮助。
可以引用的常量
- PROJECT_NAME 返回通过PROJECT指令定义的项目名称。
-
_SOURCE_DIR | CMAKE_SOURCE_DIR | PROJECT_SOURCE_DIR 编译的当前目录,即CMakeCache.txt所在目录 -
_BINARY_DIR | CMAKE_BINARY_DIR
| PROJECT_BINARY_DIR - CMAKE_CURRENT_SOURCE_DIR CMakeLists.txt所在的路径
- CMAKE_CURRENT_LIST_FILE 输出调用这个变量的
CMakeLists.txt
的完整路径 - CMAKE_CURRRENT_BINARY_DIR 如果是
in-source
编译,它跟CMAKE_CURRENT_SOURCE_DIR
一致,如果是out-ofsource
编译,他指的是target
编译目录。
使用我们上面提到的ADD_SUBDIRECTORY(src bin)
可以更改这个变量的值。
使用SET(EXECUTABLE_OUTPUT_PATH <新路径>)
并不会对这个变量造成影响,它仅仅修改了最终目标文件存放的路径 - CMAKE_CURRENT_LIST_LINE 当前行数
可以引用的系统信息
-
CMAKE_MAJOR_VERSION
,CMAKE主版本号,比如2.4.6中的2 -
CMAKE_MINOR_VERSION
,CMAKE次版本号,比如2.4.6中的4 -
CMAKE_PATCH_VERSION
,CMAKE补丁等级,比如2.4.6 中的6 -
CMAKE_SYSTEM
,系统名称,比如Linux-2.6.22
-
CMAKE_SYSTEM_NAME
,不包含版本的系统名,比如Linux
-
CMAKE_SYSTEM_VERSION
,系统版本,比如2.6.22
-
CMAKE_SYSTEM_PROCESSOR
,处理器名称,比如i686
. -
UNIX
,在所有的类UNIX平台为TRUE,包括OS X和cygwin -
WIN32
,在所有的win32平台为TRUE,包括cygwin
常用函数
- 设置变量
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
需要注意set变量的作用域 - 显示消息
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)
- 设置安装规则
INSTALL
,例:
# 对构建目标设置规则
INSTALL(TARGETS myrun mylib mystaticlib
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION libstatic
)
# 普通文件的安装规则
INSTALL(FILES files... DESTINATION
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT ]
[RENAME ] [OPTIONAL])
# 非目标文件的可执行程序安装(比如脚本之类),和File的区别只在于默认安装后权限是755,而FILE是644
INSTALL(PROGRAMS files... DESTINATION
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT ]
[RENAME ] [OPTIONAL])
# 安装时执行脚本
INSTALL([[SCRIPT ] [CODE ]] [...])
SCRIPT参数用于在安装时调用cmake脚本文件(也就是.cmake文件)
CODE参数用于执行CMAKE指令,必须以双引号括起来。比如:
INSTALL(CODE "MESSAGE(\"Sample install message.\")")
-
ADD_DEFINITIONS
向C/C++编译器添加-D定义。如果要添加其他的编译器开关,可以通过CMAKE_C_FLAGS变量和CMAKE_CXX_FLAGS变
量设置。 -
ADD_DEPENDENCIES
定义target依赖的其他target,确保在编译本target之前,其他的target已经被构建。ADD_DEPENDENCIES(target-name depend-target1 depend-target2 ...)
-
AUX_SOURCE_DIRECTORY(dir VARIABLE)
作用是发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表。因为目前cmake还不能自动发现新添加的源文件。 -
CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR])
比如CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR)
,如果cmake版本小与2.5,则出现严重错误,整个过程中止。 -
EXEC_PROGRAM
已废弃,可以使用下面的execute_process
代替 在CMakeLists.txt
处理过程中执行shell命令,并不会在生成的Makefile
中执行。例:
EXEC_PROGRAM(Executable [directory in which to run]
[ARGS ]
[OUTPUT_VARIABLE ]
[RETURN_VALUE ])
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)
- execute_process 执行子进程
execute_process(COMMAND [args1...]]
[COMMAND [args2...] [...]]
[WORKING_DIRECTORY ]
[TIMEOUT ]
[RESULT_VARIABLE ]
[OUTPUT_VARIABLE ]
[ERROR_VARIABLE ]
[INPUT_FILE ]
[OUTPUT_FILE ]
[ERROR_FILE ]
[OUTPUT_QUIET]
[ERROR_QUIET]
[OUTPUT_STRIP_TRAILING_WHITESPACE]
[ERROR_STRIP_TRAILING_WHITESPACE])
-
FILE
指令。文件操作指令,基本语法为:
FILE(WRITE filename "message to write"... )
FILE(APPEND filename "message to write"... )
FILE(READ filename variable)
FILE(GLOB variable [RELATIVE path] [globbing
expressions]...)
FILE(GLOB_RECURSE variable [RELATIVE path]
[globbing expressions]...)
FILE(REMOVE [directory]...)
FILE(REMOVE_RECURSE [directory]...)
FILE(MAKE_DIRECTORY [directory]...)
FILE(RELATIVE_PATH variable directory file)
FILE(TO_CMAKE_PATH path result)
FILE(TO_NATIVE_PATH path result)
-
INCLUDE
指令,用来载入其它目录的CMakeLists.txt
文件,也用于载入预定义的cmake模块.
INCLUDE(file1 [OPTIONAL])
INCLUDE(module [OPTIONAL])
OPTIONAL参数的作用是文件不存在也不会产生错误。
-
FIND_
指令 FIND_系列指令主要包含一下指令:
FIND_FILE( name1 path1 path2 ...)
VAR变量代表找到的文件全路径,包含文件名
FIND_LIBRARY( name1 path1 path2 ...)
VAR变量表示找到的库全路径,包含库文件名
FIND_PATH( name1 path1 path2 ...)
VAR变量代表包含这个文件的路径。
FIND_PROGRAM( name1 path1 path2 ...)
VAR变量代表包含这个程序的全路径。
FIND_PACKAGE( [major.minor] [QUIET] [NO_MODULE]
[[REQUIRED|COMPONENTS] [componets...]])
用来调用预定义在CMAKE_MODULE_PATH下的Find.cmake模块,你也可以自己定义Find模块,通过SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录中供工程使用
代码组织
- 添加头文件目录 INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
- 添加lib库搜索目录 LINK_DIRECTORIES(directory1 directory2 ...)
- 添加lib库
TARGET_LINK_LIBRARIES(target library1
library2
...)
生成规则
可执行程序
最简makefile
PROJECT(HELLO)
ADD_EXECUTABLE(hello main.c)
动态和静态库
ADD_LIBRARY
通过ADD_LIBRARY指令构建动态库和静态库。例:ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
原型
ADD_LIBRARY(libname [SHARED|STATIC|MODULE]
[EXCLUDE_FROM_ALL]
source1 source2 ... sourceN)
SET_TARGET_PROPERTIES
如果有一个名称为hello的SHARED库,还有个名为hello_static的STATIC库时,则可以使用下面的指令同时构建同名的动态库和静态库(libhello.a和libhello.so)
SET_TARGET_PROPERTIES(hello PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
# 还要加上以下两行,防止生成hello_static时清除了libhello.so
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT
1)
还可以通过SET_TARGET_PROPERTIES控制动态库版本,SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
。VERSION
指代动态库版本,SOVERSION
指代API
版本。
将上述指令加入lib/CMakeLists.txt
中,重新构建看看结果。
在build/lib
目录会生成:
libhello.so.1.2
libhello.so.1->libhello.so.1.2
libhello.so ->libhello.so.1
控制指令
IF
IF(var) | IF(NOT var) | IF(var1 AND var2) | IF(var1 OR var2) | IF(COMMAND cmd) | IF(EXISTS dir) | IF(file1 IS_NEWER_THAN file2) | IF(IS_DIRECTORY dirname) | IF(variable MATCHES regex)
MESSAGE(STATUS “do something”)
# 条件满足时的操作
ELSEIF(var) | xxxx
ENDIF()
WHILE
WHILE(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDWHILE(condition)
- FOREACH 有3种形式 1种是列表、1种是范围还有一种是步进范围
FOREACH(loop_var arg1 arg2 ...) | FOREACH(loop_var RANGE total) | FOREACH(loop_var RANGE start stop [step])
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDFOREACH(loop_var)