cmake 简明手册

Table of Contents

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

参考资料

Comments |0|

Legend *) Required fields are marked
**) You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Category: Uncategorized