cmake 简明手册
1. 概述
用 CMakeLists.txt 来描述构建依赖关系和构建目标, 用 cmake <options> <folder>
来生成 Makefile.
这个 <folder>
就是CMakeLists.txt 文件所在的目录.
可以通过命令行传入宏变量定义,例如
cmake -DABSL_BUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON -DCMAKE_CXX_STANDARD=11 ..
cmake --build . --target all
这个项目 https://github.com/abseil/abseil-cpp 中的 cmake 用法可作参考
2. 快速上手
cmake_minimum_required(VERSION 3.0.0)
project(webrtc_primer VERSION 0.1.0)
include(CTest)
enable_testing()
add_executable(webrtc_primer main.cpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
main.cpp
#include <iostream>
int main(int, char**) {
std::cout << "Hello, world!\n";
}
执行命令
mkdir bld
cd bld
cmake ..
make
3. CMakeLists.txt 语法
- 用 # 开头来添加注释
- 用 project 来指定项目名称
- 用 add_subdirectory 来添加子目录
- 用 set 命令来定义变量和赋值, 在非 if 语句中用 ${var} 的格式来引用变量
- 分支语句
- 循环语句
4. CMake 内部变量
CMAKE_C_COMPILER
CMAKE_CXX_COMPILER
CMAKE_C_FLAGS
CMAKE_BUILD_TYPE
EXECUTABLE_OUTPUT_PATH
LIBRARY_OUTPUT_PATH
5. CMake 命令
- project
- message: 打印消息
- include_directories
- link_directories
- add_subdirectory
- add_executable
- add_library
- add_definitions: 添加编译参数
- target_link_libraries: 相当于指定 -l 参数
- add_custom_target
- set_target_properties
- link_libraries
6. CMake FAQ
1) 怎样获得一个目录下的所有源文件
aux_source_directory(
) 将dir中所有源文件(不包括头文件)保存到变量variable中,然后可以add_executable (ss7gw ${variable})这样使用。
2) 怎样指定项目编译目标
project命令指定
3) 怎样添加动态库和静态库
target_link_libraries命令添加即可
4) 怎样在执行CMAKE时打印消息
message([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)
注意大小写
5) 怎样指定头文件与库文件路径
include_directories与link_directories
可以多次调用以设置多个路径
link_directories仅对其后面的targets起作用
6) 怎样区分debug、release版本
建立debug/release两目录,分别在其中执行cmake -DCMAKE_BUILD_TYPE=Debug(或Release),需要编译不同版本时进入不同目录执行make即可;
Debug版会使用参数-g;Release版使用-O3 –DNDEBUG
另一种设置方法——例如DEBUG版设置编译参数DDEBUG
IF(DEBUG_mode)
add_definitions(-DDEBUG)
ENDIF()
在执行cmake时增加参数即可,例如cmake -D DEBUG_mode=ON
7) 怎样设置条件编译
例如debug版设置编译选项DEBUG,并且更改不应改变CMakelist.txt
使用option command,eg:
option(DEBUG_mode "ON for debug or OFF for release" ON)
IF(DEBUG_mode)
add_definitions(-DDEBUG)
ENDIF()
使其生效的方法:首先cmake生成makefile,然后make edit_cache编辑编译选项;Linux下会打开一个文本框,可以更改,该完后再make生成目标文件——emacs不支持make edit_cache;
局限:这种方法不能直接设置生成的makefile,而是必须使用命令在make前设置参数;对于debug、release版本,相当于需要两个目录,分别先cmake一次,然后分别make edit_cache一次;
期望的效果:在执行cmake时直接通过参数指定一个开关项,生成相应的makefile——可以这样做,例如cmake –DDEBUGVERSION=ON
8) 怎样添加编译宏定义
使用add_definitions命令,见命令部分说明
9) 怎样添加编译依赖项
用于确保编译目标项目前依赖项必须先构建好
add_dependencies
10) 怎样指定目标文件目录
建立一个新的目录,在该目录中执行cmake生成Makefile文件,这样编译结果会保存在该目录——类似
SET_TARGET_PROPERTIES(ss7gw PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BIN_DIR}")
11) 很多文件夹,难道需要把每个文件夹编译成一个库文件?
可以不在子目录中使用CMakeList.txt,直接在上层目录中指定子目录
12) 怎样设定依赖的cmake版本
cmake_minimum_required(VERSION 2.6)
13) 相对路径怎么指定
${projectname_SOURCE_DIR}表示根源文件目录,${ projectname _BINARY_DIR}表示根二进制文件目录?
14) 怎样设置编译中间文件的目录
TBD
15) 怎样在IF语句中使用字串或数字比较
数字比较LESS、GREATER、EQUAL,字串比STRLESS、STRGREATER、STREQUAL,
Eg:
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
set(AAA abc)
IF(AAA STREQUAL abc)
message(STATUS "true") #应该打印true
ENDIF()
16) 更改h文件时是否只编译必须的cpp文件
是
17) 机器上安装了VC7和VC8,CMAKE会自动搜索编译器,但是怎样指定某个版本?
TBD
18) 怎样根据OS指定编译选项
IF( APPLE ); IF( UNIX ); IF( WIN32 )
19) 能否自动执行某些编译前、后命令?
可以,TBD
20) 怎样打印make的输出
make VERBOSE=1