app-doc-cmake

window

官网地址

linux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# gcc安装
yum install -y gcc gcc-c++ make automake

# 安装wget
yum install -y wget

# g++安装 如果提示没g++包则 yum install gcc-c++
yum install g++

# 获取cmake源码包
# wget http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz
wget https://cmake.org/files/v3.12/cmake-3.12.0-rc1.tar.gz

# 解压cmake源码包
#tar -zxvf cmake-2.8.10.2.tar.gz
tar -zxvf cmake-3.12.0-rc1.tar.gz

# 进入目录
#cd cmake-2.8.10.2
cd cmake-3.12.0-rc1

# 构建
./bootstrap
gmake

# 安装
gmake install

指令

版本查看

1
cmake --version

构建

cmake支持四种构建类型:默认是Debug

  • Debug;调试版本
  • Release;正式版本
  • RelWithDebInfo;既优化又能调试的版本
  • MinSizeRel;最小体积版本

构建时可以通过以下方法,选择不同的构建类型,配置的优先级最高。

  1. 在CMakeLists.txt中设置,代码如下:

    1
    2
    SET(CMAKE_BUILD_TYPE "Debug|Release|...”)
    * 注意:选项需要加上双引号才能生效。
  2. 命令行设置:

    1
    cmake -DCMAKE_BUILD_TYPE=Debug <path>

对于不同的类型,默认是有不同的配置,也可以手动修改不同类型的编译选项,如下:

1
2
3
4
5
6
7
8
* C++ 编译
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -DNODEBUG -O3 -Wall")
....
* C 编译
SET(CMAKE_C_FILAGS "$ENV{CFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_C_FLAGS_RELEASE "$ENV{CFLAGS} -DNODEBUG -O3 -Wall")
....

变量

编译目录

1
2
3
CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
<projectname>_BINARY_DIR

工程顶层目录

1
2
3
CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
<project>_SOURCE_DIR

当前CMakeLists文件路径

1
CMAKE_CURRENT_SOURCE_DIR

当前编译路径

1
CMAKE_CURRENT_BINARY_DIR

输出路径变量

输出调用这个变量的CMakeLists完整路径

1
CMAKE_CURRENT_LIST_FILE

输出行变量路径

输出该变量在CMakeLists所在的行

1
CMAKE_CURRENT_LIST_LINE

模块路径

1
CMAKE_MODULE_PATH

这个变量用来定义自己的cmake模块所在的路径。如果你的工程比较复杂,有可能会自己编写一些cmake模块,这些cmake模块是随你的工程发布的,为了让cmake在处理CMakeLists.txt时找到这些模块,你需要通过SET指令,将自己的cmake模块路径设置一下。
例如:SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
这时候你就可通过INCLUDE指令来调用自己的模块了。

最终结果的存放目录

1
2
EXECUTABLE_OUTPUT_PATH
LIBRARY_OUTPUT_PATH

项目名字

1
PROJECT_NAME

环境变量

1
2
$ENV{NAME}
SET(ENV{变量名} 值)

配置接口

project

指定项目名称

1
2
3
4
project(name)

# 项目名为 Demo1
project (Demo1)

SET

设置变量

1
2
3
4
5
# 注意空格隔开,不是,号
SET(key value)

# 新设置一个CMAKE_INSTALL_PREFIX
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/build)

MESSAGE

打印日志

CMake的命令行工具会在stdout上显示STATUS消息,在stderr上显示其他所有消息。CMake的GUI会在它的log区域显示所有消息。交互式的对话框(ccmake和CMakeSetup)将会在状态行上一次显示一条STATUS消息,而其他格式的消息会出现在交互式的弹出式对话框中。

CMake警告和错误消息的文本显示使用的是一种简单的标记语言。文本没有缩进,超过长度的行会回卷,段落之间以新行做为分隔符。

1
2
3
4
5
6
7
8
9
10
11
# (无) = 重要消息;
# STATUS = 非重要消息;
# WARNING = CMake 警告, 会继续执行;
# AUTHOR_WARNING = CMake 警告 (dev), 会继续执行;
# SEND_ERROR = CMake 错误, 继续执行,但是会跳过生成的步骤;
# FATAL_ERROR = CMake 错误, 终止所有处理过程;
message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)

# 变量放在字符串里面也是有效的
MESSAGE( ${USER_KEY})
MESSAGE( STATUS "this var key = ${USER_KEY}." ${USER_KEY})

AUX_SOURCE_DIRECTORY

该命令会查找指定目录下的所有源文件(不包括头文件名),然后将结果存进指定变量名。

1
2
3
4
5
AUX_SOURCE_DIRECTORY (<dir> <variable>)

# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
AUX_SOURCE_DIRECTORY(. DIR_SRCS)

ADD_SUBDIRECTORY

为项目包含一个子目录,在编译的时候,这目录下的CMakeLists.txt文件和源代码也会被处理即添加一个cmake的子目录

1
2
3
4
5
add_subdirectory(source_dir [binary_dir]
[EXCLUDE_FROM_ALL])

# 把src/tool目录添加到编译目录
add_subdirectory(src/tool)

ADD_LIBRARY

该命令用于将制定路径的文件生成库文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# STATIC表示静态库
# SHARED表示动态库
# MODULE表示插件,可动态调用,但不作为其它工程的依赖
add_library(< name > [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 source2 … sourceN)


# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)

# 生成链接库
add_library (MathFunctions ${DIR_LIB_SRCS})

# 添加静态库
AUX_SOURCE_DIRECTORY(./ src_dir)
ADD_LIBARARY(src SHARED ${src_dir})

为目标添加(关联)依赖的连接库,生成可执行文件需要链接的库

1
2
3
4
5
target_link_libraries(<target> [item1 [item2 [...]]]
[[debug|optimized|general] <item>] ...)


target_link_libraries(Demo MathFunctions)

ADD_EXECUTABLE

将源文件编译生成可执行文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])

# 用法1
# 指定文件生成可执行文件
add_executable(Demo main.cc MathFunctions.cc)

# 用法2
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)

# 指定生成目标
add_executable(Demo ${DIR_SRCS})

OPTION

该命令为用户提供了一个在ON和OFF中做出选择的选项。如果没有指定初始值,将会使用OFF作为初值。

1
2
3
option(<option_variable> "描述选项的帮助性文字" [initial value])

option (USE_MYMATH "Use provided math implementation" OFF)

CONFIGURE_FILE

将文件input拷贝到output然后替换文件内容中引用到的变量值。如果input是相对路径,它被评估的基础路径是当前源码路径。input必须是一个文件,而不是个路径。如果output是一个相对路径,它被评估的基础路径是当前二进制文件路径。如果output是一个已有的路径,那么输入文件将会以它原来的名字放到那个路径下。
该命令替换掉在输入文件中,以${VAR}格式或@VAR@格式引用的任意变量,如同它们的值是由CMake确定的一样。 如果一个变量还未定义,它会被替换为空。如果指定了COPYONLY选项,那么变量就不会展开。如果指定了ESCAPE_QUOTES选项,那么所有被替换的变量将会按照C语言的规则被转义。该文件将会以CMake变量的当前值被配置。如果指定了@ONLY选项,只有@VAR@格式的变量会被替换而${VAR}格式的变量则会被忽略。这对于配置使用${VAR}格式的脚本文件比较有用。任何类似于#cmakedefine VAR的定义语句将会被替换为#define VAR或者/* #undef VAR */,视CMake中对VAR变量的设置而定。任何类似于#cmakedefine01 VAR的定义语句将会被替换为#define VAR 1#define VAR 0,视VAR被评估为TRUE或FALSE而定。

1
2
configure_file(<input> <output>
[COPYONLY] [ESCAPE_QUOTES] [@ONLY])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目信息
project (Demo4)

# 是否使用自己的 MathFunctions 库
option (USE_MYMATH
"Use provided math implementation" OFF)

# 加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_SOURCE_DIR}/config.h"
)

# 是否加入 MathFunctions 库
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/math")
add_subdirectory (math)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions )
endif (USE_MYMATH)

# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)

# 指定生成目标
add_executable (Demo ${DIR_SRCS})
target_link_libraries (Demo ${EXTRA_LIBS})

check_function_exists

查看函数是否存在

1
2
3
# 检查系统是否支持 pow 函数
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
check_function_exists (pow HAVE_POW)

如果系统有指定的函数,但却cmake却找不到,可以尝试库路径的设置。

1
2
3
4
CMAKE_REQUIRED_FLAGS = string of compile command line flags
CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
CMAKE_REQUIRED_INCLUDES = list of include directories
CMAKE_REQUIRED_LIBRARIES = list of libraries to link

例如上面pow函数,可以设置找系统的数学函数库

1
2
3
4
# 检查系统是否支持 pow 函数
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
set(CMAKE_REQUIRED_LIBRARIES m)
check_function_exists (pow HAVE_POW)

INCLUDE

从给定的文件中读取CMake的清单文件代码。在清单文件中的命令会被立即处理,就像它们是写在这条include命令展开的地方一样。如果指定了OPTIONAL选项,那么如果被包含文件不存在的话,不会报错。如果指定了RESULT_VARIABLE选项,那么var或者会被设置为被包含文件的完整路径,或者是NOTFOUND,表示没有找到该文件。
如果指定的是一个模块(module)而不是一个文件,查找的对象会变成路径CMAKE_MODULE_PATH下的文件<modulename>.camke。

1
2
3
4
5
6
include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>]
[NO_POLICY_SCOPE])

# 检查系统是否支持 pow 函数
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
check_function_exists (power HAVE_POW)

用来连接动态库目录

1
link_directories("/usr/local/lib/")

FIND_LIBRARY

搜索库

1
2
FIND_LIBRARY(HELLO_LIB hello /usr/lib /home/ubuntu/ch2/useHello /usr/local/lib  NO_DEFAULT_PATH)
link_libraries(${HELLO_LIB})

用来链接指定的静态和动态库

1
2
FIND_LIBRARY(HELLO_LIB hello /usr/lib /home/ubuntu/ch2/useHello /usr/local/lib  NO_DEFAULT_PATH)
link_libraries(${HELLO_LIB})

add_definitions

添加预定义宏

1
2
# 注意:以-D做前缀,FOO和BAR才是宏
add_definitions(-DFOO -DBAR ...)

INCLUDE_DIRECTORY

include头文件时搜索的所有目录

include_directories

程序连接库文件时搜索库文件的目录

1
include_directories(${CMAKE_SOURCE_DIR}/include/tool)

SET_TARGET_PROPERTIES

设置编译生成的执行文件存放的目录
如不指定,生成的执行文件在当前编译目录下的个子目录下的build目录下

1
SET_TARGET_PROPERTIES(src PROPERTIES output_name "src")

add_compile_options

用于添加编译选项。

对于编译选项,也可以通过set命令修改CMAKE_CXX_FLAGSCMAKE_C_FLAGS
使用这两种方式在有的情况下效果是一样的,但请注意它们还是有区别的:
add_compile_options命令添加的编译选项是针对所有编译器的(包括c和c++编译器),而set命令设置CMAKE_C_FLAGS或CMAKE_CXX_FLAGS变量则是分别只针对c和c++编译器的。

例子:针对c++11

1
2
3
4
5
6
7
8
9
10
11
12
# 判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持
if(CMAKE_COMPILER_IS_GNUCXX)
add_compile_options(-std=c++11)
message(STATUS "optional:-std=c++11")
endif(CMAKE_COMPILER_IS_GNUCXX)

# 使用add_compile_options添加-std=c++11选项,是想在编译c++代码时加上c++11支持选项。但是因为add_compile_options是针对所有类型编译器的,所以在编译c代码时,就会产生warning
# 虽然并不影响编译,但看着的确是不爽啊,要消除这个warning,就不能使用add_compile_options,而是只针对c++编译器添加这个option。改成如下
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
message(STATUS "optional:-std=c++11")
endif(CMAKE_COMPILER_IS_GNUCXX)

GDB

根目录的cmake文件添加

1
2
3
SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

cmake gdb语法

1
2
cmake -DCMAKE_BUILD_TYPE=Debug <path>
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo <path>

特殊配置

c++版本设置

设置c++11的时候,需要添加编译选项,不同版本不一样,可以逐个试试

1
2
add_definitions(-std=c++0x)
add_definitions(-std=c++11)

参考配置

  • 根目录CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 ")

# 项目信息
project (AutoTool)

add_definitions(-D__LINUX__)

aux_source_directory(. DIR_ROOT)

# 添加cmake路径
add_subdirectory(src/util)
add_subdirectory(src/base)
add_subdirectory(src/plugin)
add_subdirectory(src/project)
#add_subdirectory(src/test)

# 添加头文件路径
include_directories(${CMAKE_SOURCE_DIR}/include/base)
include_directories(${CMAKE_SOURCE_DIR}/include/util)
#include_directories(${CMAKE_SOURCE_DIR}/include/test)
include_directories(${CMAKE_SOURCE_DIR}/include/plugin)
include_directories(${CMAKE_SOURCE_DIR}/include/project)
#include_directories(/usr/local/include/pcre/)

# 指定生成目标
add_executable (autoTool ${DIR_ROOT})

# 链接动态库
#link_directories("/usr/local/lib/")

# 添加链接库
target_link_libraries(autoTool pcrecpp sfUtil sfBase sfPlugin sfProject)
  • 其中一个子目录的CMakeLists.txt
1
2
3
4
5
6
7
# 添加头文件路径
include_directories(${CMAKE_SOURCE_DIR}/include/base)
include_directories(${CMAKE_SOURCE_DIR}/include/util)
include_directories(${CMAKE_SOURCE_DIR}/include/plugin)

aux_source_directory(. DIR_SRC_UTIL)
add_library(sfUtil ${DIR_SRC_UTIL})

参考

CMake 入门实践