一、参考资料

cmake详细教程(经验版)

二、CMake常用指令

add_compile_options()

功能:添加编译参数。

语法:add_compile_options(编译参数)。

# 添加编译参数 -wall -std=c++11
add_compile_options(-wall -std=c++11 -o2)

add_definitions()

功能:向C/C++编译器添加编译选项 -D。

语法:add_definitions(-DENABLE_DEBUG -DABC),参数之间用空格分隔。

#ifdef ENABLE_DEBUG 
...
#endif

add_dependencies()

CMAKE之add_dependencies使用

问题引入

在项目中通常会遇见这样的情况:(例如一个项目中有:main,libhello.a, libworld.a),当项目过小的时候,编译顺序是*.a,然后是main,但是当一个项目的文件过于庞大,就会导致编译的顺序不会按照主CMAKE的 add_subdirectory 引入的先后顺序,为了解决这一问题,就需要使用 add_dependencies 进行依赖指定。

简单示例

项目结构
├── CMakeLists.txt          // 下面用主CMAKE表示
├── hello
│   ├── CMakeLists.txt		// 下面用HELLOCMAKE表示
│   ├── hello.c
│   └── hello.h
├── main
│   ├── CMakeLists.txt		// 下面用MAINCMAKE表示
│   └── main.c
└── world
    ├── CMakeLists.txt		// 下面用WORLDCMAKE表示
    ├── world.c
    └── world.h
HELLOCMAKE的内容
cmake_minimum_required(VERSION 3.5.1)

set(CMAKE_C_STANDARD 99)

# 生成hello静态链接库
add_library(hello STATIC world.c hello.h)
MAINCMAKE的内容
cmake_minimum_required(VERSION 3.5.1)
project(CmakeDemo C)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY /home/lib)
set(CMAKE_C_STANDARD 99)

# 生成CmakeDemo可执行文件
add_executable(CmakeDemo main.c)
link_directories(/home/lib)

target_link_libraries(
    CmakeDemo
    hello
    world
)
WORLDCMAKE的内容
cmake_minimum_required(VERSION 3.5.1)
set(CMAKE_C_STANDARD 99)

# 生成world静态链接库
add_library(world STATIC world.c world.h)
主CMAKE的内容
cmake_minimum_required(VERSION 3.5)

add_subdirectory(main)
add_subdirectory(hello)
add_subdirectory(world)

add_dependencies(CmakeDemo hello world)
注意
  • 该示例中,只有在 主CMAKE 中使用到 add_dependencies()。
  • add_dependencies() 中所填写的名称应该是其他 CMAKE 生成的名称。
  • 该示例中,如果写成 add_dependencies(CmakeDemo libhello.a libworld.a) ,则会报错。
总结

当构建一个项目时,由于依赖关系的存在,所以被依赖的项目总是最先构建,这样可避免出现"找不到库的错误"。

add_executable()

功能:生成可执行文件。

语法:add_executable(exe文件名 source1 source2 .. sourceN)。

# 编译main.cpp生成可执行文件main
add_executable(main main.cpp)

add_library()

功能:生成库文件,.so动态库、.a静态库、.o中间产物。

语法:add_library(<name> [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 .. sourceN)。

参数解释

  • <name>,表示库文件的名字,该库文件会根据命令里列出的源文件来创建。
  • STATIC、SHARED 和 MODULE 的作用是指定生成的库文件的类型。STATIC 库是目标文件的归档文件,在链接其它目标的时候使用。
  • SHARED库会被动态链接(动态链接库),在运行时会被加载。
  • MODULE库是一种不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数。
# 生成 libmindsporelite.so 动态链接库
add_library(mindsporelite SHARED main.cc)

# 生成 libmindsporelite.a 静态链接库
add_library(mindsporelite STATIC main.cc)

# 生成 libmindsporelite.o 未被链接的中间产物
# 中间文件不能作为库或者单独执行
add_library(mindsporelite OBJECT main.cc)

aux_source_directory()

功能:查找指定目录下的所有源文件,并将结果存进指定变量名。

语法:aux_source_directory(文件夹路径 变量名)。

# 遍历当前目录下的所有源代码文件,并将其添加到变量DIR_SRCS中
aux_source_directory(. DIR_SRCS)

# 编译SRC变量所代表的源代码文件,生成main可执行文件
add_executable(main ${SRC})

add_subdirectory()

功能:向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置。

语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])。

顶层CMakeLists.txt 通过 add_subdirectory(dir),指明本项目包含的子目录 ,子目录下的 CMakeLists.txt 文件和源代码也会被处理,通过多层的CmakeLists,一一构建各层的库和依赖。binary_dir 指定的目录存放输出文件,如果没有指定则使用source_dir。

# 添加src子目录,src中需要有一个CMakeLists.txt
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)

cmake_minimum_required()

功能:指定CMake的最小版本要求。

语法:cmake_minimum_required(VERSION 版本号 [FATAL_ERROR])。

# CMake最小版本要求为2.8.3
cmake_minimum_required(VERSION 2.8.3)

find_指令

FIND_FILE(<VAR> name1 path1 path2 …)

功能:VAR变量代表找到的文件全路径,包含文件名。

FIND_LIBRARY(<VAR> name1 path1 path2 …)

功能:VAR变量表示找到的库文件的全路径,包含库文件。

FIND_PATH(<VAR> name1 path1 path2 …)

功能:VAR变量代表包含这个文件的路径。

FIND_PROGRAM(<VAR> name1 path1 path2 …)

功能:VAR变量代表包含这个工程的全路径。

find_package()

Cmake命令之find_package介绍

功能:本地导入外部库。用于查找包(通常是使用三方库),并返回关于包的细节(使用包所依赖的头文件、库文件、编译选项、链接选项等)。

语法:FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets …]])。

参数解释

  • REQUIRED 表示该库是必须的,如果找不到会报错;
  • COMPONENTS 用于检测该库的对应组件是否存在,如果不存在则认为找到的库不满足条件;
# find a boost install with the libraries filesystem and system
# 使用库文件系统和系统查找boost install
find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)

#这是第三方库,而不是自己生成的静态动态库
# check if boost was found
if(Boost_FOUND)
    message ("boost found")
else()
    message (FATAL_ERROR "Cannot find Boost")
endif()

# Add an executable
add_executable(third_party_include main.cpp)

# link against the boost libraries
target_link_libraries( third_party_include
    PRIVATE
        Boost::filesystem
)

上面的指令,使用 find_package 指令来在本地搜索对应的第三方库,Boost 代表需要查询的库名称;1.46.1 代表需要库的最低版本。

FetchContent

功能:外部导入外部库。FetchContent 是 3.11.0 版本开始提供的功能,只需要一个 URL 或者 Git 仓库即可引入一个库。

使用方法

  1. include(FetchContent) :表示引入 FetchContent。
  2. FetchContent_Declare(第三方库) :获取第三方库,可以是一个 URL 或者一个 Git 仓库。
  3. FetchContent_MakeAvailable(第三方库) :将这个第三方库引入项目。
  4. target_link_libraries(主项目 PRIVATE 子模块::子模块) :链接这个第三方库。
cmake_minimum_required(VERSION 3.14)
project(my_project)

# GoogleTest requires at least C++11
set(CMAKE_CXX_STANDARD 11)

include(FetchContent)
FetchContent_Declare(
  googletest
  URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

FILE()

CMake 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()

Load and run CMake code from a file or module.

功能:用来载入 CMakeLists.txt 文件,也用于载入预定义的cmake模块。

语法:include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>] [NO_POLICY_SCOPE])。

如果指定文件,则直接处理。如果指定module,则寻找 module.cmake 文件,首先在${CMAKE_MODULE_PATH} 中寻找,然后在CMake的module目录中查找。

include_directories()

功能:向工程添加多个特定的 头文件搜索路径,相当于指定g++编译器的 -I 参数。

语法:include_directories([AFTER|BEFORE][SYSTEM] dir1 dir2 ...)。

include_directories(header-dir) 是一个全局包含,向下传递。也就是说,如果某个目录的 CMakeLists.txt 中使用了该指令,其下所有的子目录默认也包含了header-dir 目录。

# 包含所有子目录
aux_source_directory()

# 包含指定目录
include_directories()

# 将/usr/include/myincludefolder 和 ./include 添加到头文件搜索路径
include_directories(/usr/include/myincludefolder ./include)

install()

项目工程结构

.
├── CMakeLists.txt
├── config.h.in
├── License.txt
├── main.cc
└── math
    ├── CMakeLists.txt
    ├── MathFunctions.cc
    └── MathFunctions.h

math 目录下的 CMakeLists.txt

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

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

# 指定 MathFunctions 库的安装路径
# 将静态库 MathFunctions 安装到 `/usr/local/bin` 目录下
install(TARGETS MathFunctions DESTINATION bin)

# 将头文件 MathFunctions.h 安装到 `/usr/local/include` 目录下
install(FILES MathFunctions.h DESTINATION include)

根目录的 CMakelists.txt

# 指定安装路径
# 将可执行程序 Demo 安装到了 `/usr/local/bin` 目录下
install(TARGETS Demo DESTINATION bin)

# 将 config.h 安装到 `/usr/local/include` 目录下
install(FILES "${PROJECT_BINARY_DIR}/config.h" DESTINATION include)
[root@root]$ sudo make install
[ 50%] Built target MathFunctions
[100%] Built target Demo
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/bin/Demo
-- Installing: /usr/local/include/config.h
-- Installing: /usr/local/bin/libMathFunctions.a
-- Up-to-date: /usr/local/include/MathFunctions.h
[ehome@xman Demo5]$ ls /usr/local/bin
Demo  libMathFunctions.a
[ehome@xman Demo5]$ ls /usr/local/include
config.h  MathFunctions.h

/usr/local/ 是默认安装的根目录,可以通过修改 CMAKE_INSTALL_PREFIX 变量的值来指定这些文件拷贝到哪个根目录。

LIST()

cmake命令之list

link_directories()(不推荐)

功能:指定要链接的库文件的搜索路径,相当于指定g++编译器的 -L 参数。

语法:link_directories(dir1 dir2 ...)。

link_directories(/home/lib)
target_link_libraries(
    CmakeDemo
    hello
    world
)

# 将/usr/lib/mylibfolder 和 ./lib 添加到库文件搜索路径
link_directories(/usr/lib/mylibfolder ./lib)

注意:该指令有时候不一定需要。因为 find_package 和 find_library 指令可以得到库文件的绝对路径。然而,自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径,以便工程能够找到。

link_libraries()

功能:通过 add_executable() 和 add_library() 指令生成<target>目标文件,link_libraries 将库链接到<target>目标文件中。 语法:link_libraries([item1 [item2 [...]]] [[debug|optimized|general] <item>] ...)

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
 
include_directories("/opt/MATLAB/R2012a/extern/include")
 
#directly link to the libraries.
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")
 
#equals to below
#LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" "/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")
 
add_executable(myProject main.cpp)
cmake_minimum_required(VERSION 3.10)
project(TestSharedLib)

# C++11 编译
set(CMAKE_CXX_STANDARD 11)

# 头文件路径
set(INC_DIR /home/yoyo/MyDocuments/C++Projects/MySharedLib)
# 库文件路径
set(LIB_DIR /home/yoyo/MyDocuments/C++Projects/MySharedLib/build)

include_directories(${INC_DIR})
link_directories(${LIB_DIR})
link_libraries(MySharedLib)

add_executable(TestSharedLib main.cpp)

# 链接 MySharedLib 库
target_link_libraries(TestSharedLib MySharedLib)

MESSAGE()

功能:向终端输出用户定义的信息。

用法:MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message")。

#产生错误,生成过程被跳过。
MESSAGE(SEND_ERROR "message")

#输出前缀为--d的信息。
MESSAGE(STATUS "message")

#立即终止所有的cmake过程
MESSAGE(FATAL_ERROR "message")
# 终端执行export
export ASCEND_AICPU_PATH=/usr/local/Ascend/ascend-toolkit/latest

# CMakeLists.txt文件打印
message(STATUS "ASCEND_AICPU_PATH=${ASCEND_AICPU_PATH}")

# 终端打印输出
-- ASCEND_AICPU_PATH=/usr/local/Ascend/ascend-toolkit/latest

option()

Options that can be configured through environment variables or manually.(option通过配置环境变量或者手动设置)

对于跨平台的项目,我们往往要进行交叉编译,针对不同环境的代码和功能可能有所不同,我们往往通过option确定编译选项,不同平台编译的代码用宏进行隔离,同时编译宏也可以决定某部分代码是否编译,是否包含某个功能,对一些还不稳定的特性进行隔离。

比如,在mindsporelilte中,通过设置MSLITE_ENABLE_SHARING_MEM_WITH_OPENGL来确定是否编译OpenGL相关代码:

option(MSLITE_ENABLE_SHARING_MEM_WITH_OPENGL "enable sharing memory with OpenGL" on)

if(DEFINED ENV{MSLITE_ENABLE_SHARING_MEM_WITH_OPENGL})
    set(MSLITE_ENABLE_SHARING_MEM_WITH_OPENGL $ENV{MSLITE_ENABLE_SHARING_MEM_WITH_OPENGL})
endif()

if(MSLITE_ENABLE_SHARING_MEM_WITH_OPENGL)
    add_definitions(-DENABLE_OPENGL_TEXTURE)
endif()

在相关cpp文件中用宏ENABLE_OPENGL_TEXTURE隔离相关代码:

#ifdef ENABLE_OPENGL_TEXTURE
  if (!lite::opencl::LoadOpenGLLibrary(&gl_handle_)) {
    MS_LOG(ERROR) << "Load OpenGL symbols failed!";
    return RET_ERROR;
  }
#endif

project()

功能:定义工程名称,并可指定工程支持的语言。

语法:project(工程名称 [CXX] [C] [java])。

# 指定工程名及版本号
project(HELLOWORLD VERSION 1.0)

set()

功能:显式的定义变量。

语法:set(变量名 [变量值] [CACHE TYPE DOCSTRING [FORCE]])。

# 定义SRC变量,其值为main.cpp hello.cpp
set(SRC sayhello.cpp hello.cpp)

# 指定C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 设置生成可执行文件的路径
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

# 设置生成链接库的路径
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

SET_TARGET_PROPERTIES()

功能:同时构建 libhello.so 和 libhello.a 两个库。

# 动态库
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_PUTPUT 1)
# 静态库
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)


# 增加动态库的版本号
# VERSION指代动态库版本,SOVERSION指代API版本。
SET_TARGET_PROPERTIES(hello PROPERTIES VERION 1.2 SOVERSION 1)

target_include_directories()

功能:为编译目标文件 <target> 指定头文件。

语法:target_include_directories(<target> [SYSTEM] [AFTER|BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])。

<target> 必须是通过 add_executable() 或 add_library() 创建,且不能是ALIAS目标

target_link_libraries()

功能:将<target>目标文件与库文件进行链接,相当于指定g++编译器 -l 参数。

target_link_libraries(<target> ... <item>... ...)
target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

参数解释

  • <target>,是指通过 add_executable() 和 add_library() 指令生成已经创建的目标文件,并且不能是 ALIAS 目标。
  • [item],表示库文件没有后缀的名字。
  • PUBLIC,在public后面的库会被Link到target中,并且里面的符号也会被导出,提供给第三方使用。
  • PRIVATE,在private后面的库仅被link到target中,并且终结掉,第三方不能感知你调了什么库。
  • INTERFACE,在interface后面引入的库不会被链接到target中,只会导出符号。

target_link_libraries() 往往和 add_subdirectory() 一起使用,在编译好一个可执行文件或库时,如果它依赖其他库,可以使用 target_link_libraries() 链接其他库。target_link_libraries 会在目标程序中生成rpath 。示例如下:

# 生成动态库
add_library(mindsporelite SHARED $<TARGET_OBJECTS:lite_src_mid>)
# 生成静态库
add_library(mindsporelite-static STATIC $<TARGET_OBJECTS:lite_src_mid>)
# 生成可执行文件
add_executable(benchmark main.cc)

# 动态链接,将 mindsporelite动态库文件链接到 benchmark可执行文件 
target_link_libraries(benchmark mindsporelite)
# 静态链接,将 mindsporelite-static静态库文件链接到 benchmark可执行文件 
target_link_libraries(benchmark mindsporelite-static)

link_libraries与target_link_libraries 的区别

  • link_libraries用在 add_executable 之前,target_link_libraries 用在 add_executable 之后。
  • link_libraries用来链接静态库,target_link_libraries用来链接导入库,即按照 header file + .lib + .dll 方式隐式调用动态库的 .lib 库。

控制指令

IF指令

总体把握一个原则,凡是出现 IF 的地方一定要有对应的ENDIF,出现 ELSEIF 的地方,ENDIF 是可选的。

IF(expression)
# THEN section.
COMMAND1(ARGS ...)COMMAND2(ARGS ...)
...
ELSE(expression)
# ELSE section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDIF(expression)
IF(var)#如果变量不是:空,0,N, NO, OFF, FALSE, NOTFOUND 或<var>_NOTFOUND 时,表达式为真。
IF(NOT var )#与上述条件相反。
IF(var1 AND var2)#当两个变量都为真是为真。
IF(var1 OR var2)#当两个变量其中一个为真时为真。
IF(COMMAND cmd)#当给定的 cmd 确实是命令并可以调用是为真。
IF(EXISTS dir)或者 IF(EXISTS file)#当目录名或者文件名存在时为真。
IF(file1 IS_NEWER_THAN file2)#当 file1 比 file2 新,或者 file1/file2 其中有一个不存在时为真,文件名请使用完整路径。
IF(IS_DIRECTORY dirname)#当 dirname 是目录时,为真。
IF(variable MATCHES regex)
IF(string MATCHES regex)#当给定的变量或者字符串能够匹配正则表达式 regex 时为真。比如:
IF("hello" MATCHES "ell")
    MESSAGE("true")
ENDIF("hello" MATCHES "ell")

# 数字比较表达式
IF(variable LESS number)
IF(string LESS number)
IF(variable GREATER number)
IF(string GREATER number)
IF(variable EQUAL number)
IF(string EQUAL number)

# 按照字母序的排列进行比较
IF(variable STRLESS string)
IF(string STRLESS string)
IF(variable STRGREATER string)
IF(string STRGREATER string)
IF(variable STREQUAL string)
IF(string STREQUAL string)

IF(DEFINED variable)#如果变量被定义,为真。

# 一个小例子,用来判断平台差异:
IF(WIN32)
MESSAGE(STATUS “This is windows.”)
# 作一些 Windows 相关的操作
ELSE(WIN32)
MESSAGE(STATUS “This is not windows”)
# 作一些非 Windows 相关的操作
ENDIF(WIN32)

上述代码用来控制在不同的平台进行不同的控制,但是,阅读起来却并不是那么舒服, ELSE(WIN32)之类的语句很容易引起歧义。可使用 CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 开关,避免歧义。

SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
IF(WIN32)
ELSE()
ENDIF()

# 如果配合 ELSEIF 使用,可能的写法是这样:
IF(WIN32)
# do something related to WIN32
ELSEIF(UNIX)
# do something related to UNIX
ELSEIF(APPLE)
# do something related to APPLE
ENDIF(WIN32)

WHILE指令

其真假判断条件可以参考 IF 指令。

WHILE(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDWHILE(condition)

FOREACH指令

FOREACH 指令的使用方法有三种形式:

列表形式

FOREACH(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDFOREACH(loop_var)
AUX_SOURCE_DIRECTORY(. SRC_LIST)
FOREACH(F ${SRC_LIST})
MESSAGE(${F})
ENDFOREACH(F)

范围形式

FOREACH(loop_var RANGE total)
ENDFOREACH(loop_var)
#从 0 到 total 以1为步进举例如下:
FOREACH(VAR RANGE 10)
  MESSAGE(${VAR})
ENDFOREACH(VAR)

最终得到的输出是: 0 1 2 3 4 5 6 7 8 9 10

范围和步长

# 从 start 开始到 stop 结束,以 step 为步长
FOREACH(loop_var RANGE start stop [step])
ENDFOREACH(loop_var)
FOREACH(A RANGE 5 15 3)
MESSAGE(${A})
ENDFOREACH(A)

最终得到的结果是: 5 8 11 14

三、CMake预定义变量

CMake中常用的预定义变量

BUILD_SHARED_LIBS

默认的库编译方式(shared or static),默认为static,一般在ADD_LIBRARY时直接指定编译库的类型。

CMAKE_C_FLAGS

功能:gcc编译选项。

SET(CMAKE_C_FLAGS_PUBLIC "-mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -ffunction-sections -mno-unaligned-access -fno-aggressive-loop-optimizations -mapcs-frame -rdynamic")
SET(CMAKE_C_FLAGS_DEBUG "-Wall -ggdb3 -DNM_DEBUG ${CMAKE_C_FLAGS_PUBLIC}")
SET(CMAKE_C_FLAGS_RELEASE  "-Wall -O3  ${CMAKE_C_FLAGS_PUBLIC}")

CMAKE_CXX_FLAGS

功能:g++编译选项。

# 在CMAKE_CXX_FLAGS编译选项后追加-std=c++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
  • CMAKE_CXX_FLAGS_DEBUG: 设置编译类型为Debug时的编译选项;
  • CMAKE_CXX_FLAGS_RELEASE: 设置编译类型为Release时的编译选项;

CMAKE_CXX_COMPILER

设置C++编译器。

# 设置C++编译器为g++
set(CMAKE_CXX_COMPILER "g++")
# 设置标准库版本为c++17 并开启警告
set(CMAKE_CXX_FLAGS "-std=c++17 -Wall")
# 设置Debug模式下,不开启优化,开启调试,生成更详细的gdb调试信息
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -ggdb")
# 设置Release模式下,开启最高级优化
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

CMAKE_BUILD_TYPE

功能:编译类型(Debug, Release)。

# 设定编译类型为debug,因为在调试时需要选择debug
set(CMAKE_BUILD_TYPE Debug)
# 设定编译类型为release,因为在发布时需要选择release
set(CMAKE_BUILD_TYPE release)

CMAKE_CURRENT_SOURCE_DIR

当前CMakeLists.txt文件所在目录。

CMAKE_CURRENT_BINARY_DIR

编译目录,可使用ADD_SUBDIRECTORY来修改此变量。

# 添加cmake执行子目录
ADD_SUBDIRECTORY(example)

EXECUTABLE_OUTPUT_PATH

功能:可执行文件输出的存放路径。

# 设置可执行文件的输出路径为 build/bin
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

LIBRARY_OUTPUT_PATH

功能:库文件输出的存放路径。

set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

PROJECT_NAME

功能:指定项目工程的名称。

project(Demo)

PROJECT_SOURCE_DIR

功能:项目工程的根目录,例如:/PATH/TO/CMakeDemo。

PROJECT_BINARY_DIR

功能:执行cmake命令的编译路径,一般是在build目录,例如:即/PATH/TO/CMakeDemo/build。

TOP_DIR

功能:项目工程的的根目录。

include(${TOP_DIR}/cmake/utils.cmake)

系统信息变量

root@root:~$ cmake --version
cmake version 3.11.2
  • CMAKE_MAJOR_VERSION: cmake的主版本号cmake version 3.11.2中的3;
  • CMAKE_MINOR_VERSION: cmake的次版本号cmake version 3.11.2中的11;
  • CMAKE_PATCH_VERSION: cmake的补丁等级cmake version 3.11.2中的2;
  • CAMKE_SYSTEM。系统名称比如 LInux-2.6.22;
  • CAMKE_SYSTEM_NAME,不包含版本的系统名,比如 linux;
  • CMAKE_SYSTEM_VERSION,系统版本,比如 2.6.22;
  • CMAKE_SYSTEM_PROCESSOR,处理器的名称,比如 i686;