cmake
有多个路径的话要给每个路径都创建CMakeLists。
创建工程名称的指令:
PROJECT(projectname [CXX] [C] [Java])
工程名之后的语言列表是可以省略的
两个预定义变量:
PROJECT_BINARY_DIR
和PROJECT_SOURCE_DIR
内部编译时这两个变量指向同一个路径
外部编译时不同
定义变量:
SET(VAR [VALUE])
VALUE可以有多个值,用空格隔开
MESSAGE指令可向终端输出信息:
MESSAGE([SEND_ERROR|STATUS|FATAL_ERROR] "message to display")
SEND_ERROR,会打印错误消息,并跳过生成过程
STATUS,打印带前缀-的消息
FATAL_ERROR,会立即终止
生成一个可执行文件:
ADD_EXECUTABLE(hello ${SRC_LIST})
取变量值使用${}
指令都应该大写,参数之间用空格隔开,如果参数中使用了空格,应该用双引号引起来
可以使用make clean
清理构建结果
但是不能使用make distclean
命令清理中间文件
外部编译就是在工程下创建一个文件夹
比如新建一个build文件夹,进入build文件夹,执行cmake ..
就可以
这样就分离了源代码和构建的中间结果
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
向当前工程添加存放源代码的子目录,并且可以指定中间二进制和目标二进制文件存放位置,EXCLUDE_FROM_ALL会将该目录排除在编译过程外
ADD_SUBDIRECTORY(src bin)
就会在构建目录下创建bin目录,相当与将src目录重命名为bin
在定义ADD_EXECUTABLE的文件中定义SET(EXECUTABLE_OUTPUT_PATH ${PRJECT_BINARY_DIR}/bin)
可以指定生成的二进制文件位置
INSTALL指令来指定安装位置
执行cmake ..
的时候可以指定-DCMAKE_INSTALL_PREFIX=/sth/sth/sth
来设置路径前缀
INSTALL安装指令放在项目的CMakeLists.txt中
编译共享库和编译可执行文件是类似的,可以通过SET(LIBRARY_OUTPUT_PATH
ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ...)
libname不需要指定后缀
为了指定相同名称的静态库和动态库,可以使用指令SET_TARGET_PROPERTIES
SET_TARGET_PROPERTIES(target1 target2 ... PROPERTIES prop1 value1 prop2 value2 ...)
获取设置的属性名使用GET_TARGET_PROPERTY(VAR target property)
指令
如果构建生成.a后.so被删除,则设置CLEAN_DIRECT_OUTPUT来解决:
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
设置版本号SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
VERSION是动态链接库版本,SOVERSION是API版本
安装库时使用:
INSTALL(TARGETS hello hello_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
安装文件使用INSTALL(FILES hello.h DESTINATION include/hello)
使用外部库:
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
设置搜索的头文件路径
SET(CMAKE_INCLUDE_DIRECTORIES_BEFORE on)
可以将添加的头文件搜索路径放在已有路径前面,AFTER类似
LINK_DIRECTORIES(dir1 dir2 ...)
设置搜索共享库的路径,该命令必须放在ADD_EXECUTABLE前面
TARGET_LINK_LIBRARIES(target lib1 <debug | optimized> lib2 ...)
为目标文件添加共享库
还可以使用通用的方法提供搜索路径,在bash的变量中定义CMAKE_INCLUDE_PATH=dir
然后在cmake文件中使用FIND_PATH()
指令指定搜索路径,同样的,CMAKE_LIBRARY_PATH=dir
用来设置搜索库的路径,FIND_LIBRARY()
用来搜索
引用变量时,在IF中引用不需要使用${}
CMAKE自带常量:
CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
<projectname>_BINARY_DIR
这三个变量指向同一内容,内部编译指向工程顶层目录,外部编译则指向工程编译发生的目录
CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
<projectname>_SOURCE_DIR
该指令和上面的差不多,都指向项目顶层目录
CMAKE_CURRENT_SOURCE_DIR
指当前CMakeLists.txt所在路径
CMAKE_CURRENT_BINARY_DIR
内部编译时与CMAKE_CURRENT_SOURCE_DIR一致,外部编译时指target目录,ADD_SUBDIRECTORY(src bin)
就可以改变这个变量
CMAKE_CURRENT_LIST_FILE
输出调用这个变量的CMakeLists.txt的完整路径
CMAKE_CURRENT_LIST_LINE
该变量所在的行
CMAKE_MODULE_PATH
定义cmake模块所在路径,使用SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
这样的方式设置值,然后可以用INCLUDE指令调用
EXECUTABLE_OUTPUT_PATH
和LIBRARY_OUTPUT_PATH
用来定义最终结果的存放目录
PROJECT_NAME
为项目名称
$ENV{NAME}
该指令用来调用系统环境变量
SET(ENV{变量名} 值)
设置环境变量
CMAKE_INCLUDE_CURRENT_DIR
自动添加CMAKE_CURRENT_BINARY_DIR
和CMAKE_CURRENT_SOURCE_DIR
到当前CMakeLists.txt中
CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
将工程设置的头文件目录在系统头文件目录前,冲突时会优先使用工程的
CMAKE_MAJOR_VERSION
,CMAKE_MINOR_VERSION
,CMAKE_PATCH_VERSION
这三个代表了比如2.4.6中的2,4,6三个版本号
CMAKE_SYSTEM
表示系统名称
CMAKE_SYSTEM_NAME
表示不包含版本号的系统名
CMAKE_SYSTEM_VERSION
系统版本号
CMAKE_SYSTEM_PROCESSOR
处理器名称
UNIX
类UNIX平台为TRUE
WIN32
所有win32平台为TRUE
CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS
控制IF ELSE的书写方式
BUILD_SHARED_LIBS
是指为ON
会默认编译动态库,否则为静态库
CMAKE_C_FLAGS
设置C编译选项
CMAKE_CXX_FLAGS
设置C++编译选项
基本指令
ADD_DEFINITIONS
给编译器添加-D定义,多个参数用空格分开
如:ADD_DEFINITIONS(-DENABLE_DEBUG -DXXX)
ADD_DEPENDENCIES
定义依赖的target
ADD_TEST
和ENABLE_TESTING
指令控制makefile是否构建test
ENABLE_TESTING()
一般放在住CMakeLists.txt中
ADD_TEST
使用方法:ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main)
在需要测试的目录的CMakeLists.txt中都要加ENABLE_TESTING()
AUX_SOURCE_DIRECTORY(dir VARIABLE)
将dir目录下的源文件添加在VARIABLE变量中
CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR])
设置cmake版本
EXEC_PROGRAM
在cmake命令生成Makefile过程中执行命令,如ls查看某个路径的文件,可以用这个指令
FILE
指令操作文件
INCLUDE
指令用来载入CMakeLists.txt文件
FIND_FILE
FIND_LIBRARY
FIND_PATH
FIND_PROGRAM
FIND_PACKAGE
用来查找路径
IF
指令
IF(expression)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ELSE(expression)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDIF(expression)
出现IF的地方必须有ENDIF
WHILE
指令
WHILE(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDWHILE(condition)
`FOREACH`指令有三种形式
第一种
```cmake
FOREACH(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDFOREACH(loop_var)
第二种
FOREACH(loop_var RANGE total)
ENDFOREACH(loop_var)
第三种
FOREACH(loop_var RANGE start stop [step])
ENDFOREACH(loop_var)