cmake与CMakeLists.txt语法

参考

参考链接:

CMake入门实战

CMake快速入门

CMakeLists.txt 语法介绍与实例演练

【CMake】CMakeLists.txt的超傻瓜手把手教程(附实例源码)

cmake与CMakeLists.txt简介

Makefile是make运行时所依赖的规则文件。

cmake(Cross-platform Make)是一个可以自动生成 Makefile 文件的工具。它除了能生成 Makefile 外,还能生成主流IDE(VS, xcode…)构建工程所需的 project 文件。

CMakeLists.txt就是cmake运行是所依赖的规则文件。

由此可以看出,CMakeLists.txt的作用与Makefie是相似的,也是指定头文件、库文件,从而将源文件编译成新的库文件或者可执行文件。

cmake使用的通常流程

使用cmake进行编译时,通常在项目的根目录创建build目录,生成的文件保存在build目录中,从而不影响原项目的目录结构。

$ mkdir build && cd build
$ cmake .. #在这里会依赖CMakeLists.txt生成Makefile等
$ make

CMakeLists.txt语法

基本流程

CMakeLists.txt基本流程如下:

project(xxx)                                          #必须

add_subdirectory(子文件夹名称)                         #父目录必须,子目录不必

add_library(库文件名称 STATIC 文件)                    #子目录时使用(二选一)
add_executable(可执行文件名称 文件)                     #父目录时使用(二选一)

include_directories(路径)                              #必须
link_directories(路径)                                 #必须

target_link_libraries(库文件名称/可执行文件名称 链接的库文件名称)       #必须

定义变量与使用

set定义:set(GRPC_LIST main.cpp)

使用:${_GRPC_GRPCPP},如set(SRC_LIST ${SRC_LIST} test0.cpp)

list追加删除:list(APPEND SRC_LIST test1.cpp)
,list(REMOVE_ITEM SRC_LIST test1.cpp)

流程控制

if语句

if(...)
  ...
else()
  ...
endif

while语句

while(condition)
    ...
endwhile()

foreach语句

foreach(_target
  ... ...
  )
  ...
endforeach

如:

foreach(i RANGE 1 9 2) #1为起始数,9为终止数,2为步长。
    message(${i})
endforeach(i)

常用函数

函数的官方网站:https://cmake.org/cmake/help/v3.15/

  • cmake_minimum_required()指定cmake最低版本
  • project()会定义两个变量:PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR。
  • aux_source_directory(目录 变量)查找指定目录下所有源文件,并保存到指定变量名
  • add_definitions()添加编译选项
  • add_executable(可执行文件名 源文件)根据源文件生成可执行文件;
    add_library(静态库 STATIC 源文件)根据源文件生成静态库(当没有STATIC选项时,默认生成静态库);
    add_library(动态库 SHARED 源文件) 根据源文件生成动态库或共享库。
  • add_subdirectory(子目录)指定调用子目录的CMakeLists.txt,通常用于将子目录中的源文件编译成库,来给父目录中的CMakeLists.txt使用。(此时对于父目录的CMakeLists.txt而言,已经知晓子目录中编译后生成的库的存在,因此无需使用link_directories()将该库的所在文件目录另外包含进来。)
  • include_directories(目录)指定头文件目录;
    link_directories(目录)指定库文件目录。
  • target_link_libraries()指定链接库
  • option(宏 "备注" ON)添加一个选项,并设置默认值为开
  • configure_file(配置文件 配置头文件)根据配置文件生成配置头文件
  • message()打印消息
  • include()指定要包含的其他CMake文件或目录
  • find_package()find_program()
  • FetchContent_Declare()FetchContent_MakeAvailable()

常用函数的常见组合用法:

# 搜索当前目录下的所有.cpp文件,并将其存储到一个变量中,之后使用该变量。
aux_source_directory(. SRC_LIST) 
add_library(demo ${SRC_LIST})
#搜索当前目录以及protocol目录下的所有.cpp文件
file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp")
add_library(demo ${SRC_LIST})
# 或者
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp")
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
# 或者
aux_source_directory(. SRC_LIST)
aux_source_directory(protocol SRC_PROTOCOL_LIST)
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})

常用变量

预定义变量

  • PROJECT_SOURCE_DIR:工程的根目录;PROJECT_BINARY_DIR:运行 cmake 命令的目录,通常是 ${PROJECT_SOURCE_DIR}/build。
  • PROJECT_NAME:返回通过 project 命令定义的项目名称。
  • CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的路径; CMAKE_CURRENT_BINARY_DIR:target 编译目录。
  • CMAKE_CURRENT_LIST_DIR:CMakeLists.txt 的完整路径;CMAKE_CURRENT_LIST_LINE:当前所在的行。
  • EXECUTABLE_OUTPUT_PATH:可执行文件的存放位置;LIBRARY_OUTPUT_PATH:库文件的存放位置。

环境变量

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_MAJOR_VERSION:cmake 主版本号,比如 3.4.1 中的 3
    ­* CMAKE_MINOR_VERSION:cmake 次版本号,比如 3.4.1 中的 4
    ­* CMAKE_PATCH_VERSION:cmake 补丁等级,比如 3.4.1 中的 1
    ­* CMAKE_SYSTEM:系统名称,比如 Linux-­2.6.22
    ­* CMAKE_SYSTEM_NAME:不包含版本的系统名,比如 Linux
    ­* CMAKE_SYSTEM_VERSION:系统版本,比如 2.6.22
    ­* CMAKE_SYSTEM_PROCESSOR:处理器名称,比如 i686
    ­* UNIX:在所有的类 UNIX 平台下该值为 TRUE,包括 OS X
    ­* WIN32:在所有的 win32 平台下该值为 TRUE

主要开关选项

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

说明:

CXX_STATNARD_REQUIRED:
If this property is set to ON, then the value of the CXX_STANDARD target property is treated as a requirement. If this property is OFF or unset, the CXX_STANDARD target property is treated as optional and may “decay” to a previous standard if the requested is not available. For compilers that have no notion of a standard level, such as MSVC, this has no effect.

即如果不设置的话,则之前设置的STANDARD 11标准可能会失效。因此,其和后一条语句一般是连用的。

CXX_EXTENSIONS:
This property specifies whether compiler specific extensions should be used. For some compilers, this results in adding a flag such as -std=gnu++11 instead of -std=c++11 to the compile line. This property is ON by default. The basic C++ standard level is controlled by the CXX_STANDARD target property.

即该值默认使用gnu++11编译,我们的protobuf编译的时候是使用c++11编译的,因此,应该把该变量关了。

配置文件

编译时有时需要自定义一些选项,比如自定义一个DEBUG宏,打开debug时需要运行的函数。这种情况下的配置头文件一般不直接编写,而是由 cmake 自动生成。

自己直接编写的是配置文件,比如此时可以新建一个config.h.in文件如下:

#cmakedefine DEBUG

之后在CMakeLists.txt中将添加以下内容:

configure_file (
    "${PROJECT_SOURCE_DIR}/config.h.in"
    "${PROJECT_BINARY_DIR}/config.h"
    )

这样,cmake 就会自动根据 config.h.in 自动生成 config.h 文件。

多目录时的CMakelists.txt

多目录时,通常需要将子目录的源文件编译成库,之后父目录编译时,链接子目录生成的库。此时应在父目录和子目录中分别编写CMakeLists.txt,示例如下:

父目录中的CMakeLists.txt:

project(demo)
aux_source_directory(. DIR_SRCS)
# 添加math子目录,此时可以认为add_subdirectory()会返回编译成的库MathFunctions,因此下面可以直接链接MathFunctions
add_subdirectory(math)
# 指定生成目标
add_executable(demo ${DIR_SRCS})
# 添加链接库
target_link_libraries(demo MathFunctions)

math子目录中的CMakeLists.txt:

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

版权声明:本文为mindizhike原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。