1.下载和安装

cmake:https://cmake.org/download/ (cmake需要配置环境变量)
cmake并不具备编译功能,需要下载MinGW编译器。
MinGW:https://sourceforge.net/projects/mingw-w64/files/mingw-w64/
cmake官方文档:https://cmake.org/cmake/help/latest/guide/tutorial/index.html#introduction

2.构建,运行与说明

windows环境手动演示过程:
1.先建文件夹demo
2.demo文件夹下创建src和build文件夹
3.src文件下创建main.cpp和CMakeList.txt

-demo
--src
----main.cpp
----CMakeList.txt
--build

命令行演示过程:
1.新建一个构建目录

mkdir build

2.进入该目录并配置项目

cd build
cmake ../src

如果cmake …/src报Cmake Error at CMakeList.txt原因是cmke和编译器版本不对
可以使用命令查看默认的编译器版本

cmake --help

3.如果不是使用默认的Generator,应该添加-G 选项:

cmake -G "MinGW Makefiles"  ../src

4.构建

cmake --build.

会生成.exe文件

5.运行.exe文件

3.说明

  • cmake命令(可以理解为函数名)不区分大小写,但是参数,变量区分大小写。
  • 参数用空格或分号隔开
  • 使用${VAR}引用变量
  • 引号可加可不加,但如果字符串中有空格必须加

4.概念

  • 目标文件(target):可执行文件(add_executable),库文件(add_library)
  • 命令(cmake-command):下面要讲得函数
  • 变量(cmake-variable):以CMAKE_开头的变量名
  • 属性(cmake-properties):文件/文件夹都有各自的属性

5. 命令

官方文档:https://cmake.org/cmake/help/latest/command/project.html

1.cmake_minimum_required

设置最低cmake版本。

cmake_minimum_required(VERSION <min>)

举例:

cmake_minimum_required(VERSION 3.10)

2.project

设置项目名

project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>
        [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
        [DESCRIPTION <project-description-string>]
        [HOMEPAGE_URL <url-string>]
        [LANGUAGES <language-name>...])

举例:

project(demo)
project(demo VERSION 1.0 LANGUAGES CXX)

项目名称PROJECT_NAME
可以通过如下命令查看:

message(${PROJECT_NAME}

3.add_executable

用指定的源文件为项目添加可执行文件

add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               [source1] [source2 ...])

例如:name和name.exe一个名字
也可以指定demo的来源文件,如下:

add_executable(demo main.cpp)

4.message

打印信息。

message([<mode>] "message text" ...)

# STATUS 前缀为--的信息
# SEND_ERROR 产生错误,跳过生成过程
# FATAL_ERROR 产生错误,终止运行

5.set

1.将变量设置为指定值。

set(<variable> <value>)

例如:

set(A 1)
message(${A})

2.设置C++标准
例如:C++ 11的标准

set(CMAKE_CXX_STANDARD 11)

3.设置输出文件位置

# 设置运行时目标文件(exe, dll)的输出位置
set(CMAKE_RUNTIME_OUTPUT_DIRCTORY
	${CMAKE_BINARY_DIR}/bin)

#设置存档目标文件(lib,a)的输出位置
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
	${CMAKE_BINARY_DIR}/lib)

6.option

定义一个开关

option(<variable> "<help_text>" [value])

# value的值为ON 或OFF,默认为OFF
# 命令行  -D<variable>=ON/OFF

例如:设置VERSION_ENABLE为ON

option(VERSION_ENABLE "output version" ON)

7.configure_file

将输入文件进行替换并生成输出文件。

configure_file(<input> <output>)

#输入文件中形如@VAR@ 或${VAR}的字符串会被替换为这些变量的当期值,如果未定义则替换为空字符串。
#其他规则见下

例如:
创建文件:config.h.in,内容如下:

#define PRO_VERSION_MAJOR @PRO_VERSION_MAJOR@
#define  PRO_VERSION_MAJOR @PRO_VERSION_MINOR@

CMakeList.txt输入如下内容:

configure_file(config.h.in config.h)

需要注意:上述的话需要定义在定义项目版本之后。
在main.cpp中加入内容

#include "config.h"
int mian()
{
       cout<<"version"<< PRO_VERSION_MAJOR<<"."<<PRO_VERSION_MAJOR <<endl;
       return 0;
}

还需要添加target_link_librariy,重新build,会输出version:1.0。

#cmakefile VAR
//会被替换为以下两行之一,取决于VAR是否被设置
#define VAR ...
/* #undef VAR */

例如:

CMakeList.txt中添加:

option(DATE_ENABLE "output data" ON)
if(DATE_ENABLE)
     SET(date  "2022.7.12“)
endif()

config.h.in中添加:

#cmakedefine DATE "2022.7.12“

如果DATE_ENABLE设置为ON,输出的config.h文件中输出为#define VAR 2022.7.12
如果DATE_ENABLE设置为OFF,输出的config.h文件中输出为#undef VAR

8.add_definitions

add_definitions()相当于 C/C++ 里面的 #define 宏定义功能.

add_definitions(-DFOO -DBAR ...)

9.aux_source_directory

搜集所有在指定路径下的源文件的文件名,并将输出结果列表储存在指定的变量中。

aux_source_directory(<dir> <variable>)

例如:

aux_source_directory("./src/."  SRX_LIST)

6.添加头文件搜索路径

1.include_directories

指定所有目标的头文件路径。(为所有目标添加路径)

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

#目录会被添加到当前文件的 INCLUDE_DIRECTORIES属性中
#当前文件的每一个目标文件的 INCLUDE_DIRECTORIES属性也会添加该目录

2.target_include_directories

指定目标的头文件路径。(为一个目标添加路径,推荐)

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

# 目标文件有INCLUDE_DIRECTORIES和 INTERFACE_INCLUDE_DIRECTORIES 两个属性
# INCLUDE_DIRECTORIES对内头文件目录
# INTERFACE_INCLUDE_DIRECTORIES 对外头文件目录

例如:

include_director(${PROJECT_BINARY_DIR})
target_include_directories(demo PRIVATE "${PROJECT_BINARY_DIR}")

为了VS中有.h文件

3.FILE

Reading
  file(READ <filename> <out-var> [...])
  file(STRINGS <filename> <out-var> [...])
  file(<HASH> <filename> <out-var>)
  file(TIMESTAMP <filename> <out-var> [...])
 
Writing
  file({WRITE | APPEND} <filename> <content>...)
  file({TOUCH | TOUCH_NOCREATE} [<file>...])
  file(GENERATE OUTPUT <output-file> [...])
 
Filesystem
  file({GLOB | GLOB_RECURSE} <out-var> [...] [<globbing-expr>...])
  file(RENAME <oldname> <newname>)
  file({REMOVE | REMOVE_RECURSE } [<files>...])
  file(MAKE_DIRECTORY [<dir>...])
  file({COPY | INSTALL} <file>... DESTINATION <dir> [...])
  file(SIZE <filename> <out-var>)
  file(READ_SYMLINK <linkname> <out-var>)
  file(CREATE_LINK <original> <linkname> [...])
 
Path Conversion
  file(RELATIVE_PATH <out-var> <directory> <file>)
  file({TO_CMAKE_PATH | TO_NATIVE_PATH} <path> <out-var>)
 
Transfer
  file(DOWNLOAD <url> <file> [...])
  file(UPLOAD <file> <url> [...])
 
Locking
  file(LOCK <path> [...])

产生一个匹配 的文件列表并将它存储到变量 中。文件名替代表达式和正则表达式相似,但更简单。如果 RELATIVE 标志位被设定,将返回指定路径的相对路径。结果将按字典顺序排序。

如果 CONFIGURE_DEPENDS 标志位被指定,CMake 将在编译时给主构建系统添加逻辑来检查目标,以重新运行 GLOB 标志的命令。如果任何输出被改变,CMake都将重新生成这个构建系统。

FILE(GLOB_RECURSE sources CONFIGURE_DEPENDS include/*.h)

4.target_sources

往可执行目标中添加源文件。

target_sources(<target>
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
target_sources(demo PUBLIC ${sources})

7.库的生成和链接

创建加减乘除的动态库。
1.src下calc目录,calc目录创建文件
addition.h

int add(int x,int y)

addition.cpp

int add(int x,int y)
{
	return x + y;
}

subtract.h

int sub(int x, int y)

subtract.cpp

int sub(int x, int y)
{
    return x - y;
}

calc中也要构建CMakeList.txt。
CMakeList.txt构建过程添加如上文件
整体目录如下:

-demo
--src
----main.cpp
----CMakeList.txt
----calc
--------addition.h
--------addition.cpp
------subtract.h
------subtract.cpp
--------CMakeList.txt
--build

1.add_subdirectory

添加源文件目录。

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL] [SYSTEM])

# binary_dir 指定编译结果存放的位置

例如:
src下的CMakeList.txt需要添加

add_subdirectory(calc);

2.add_library

用指定的原文生成库。

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])

# STATIC 静态库
# SHARED 动态库
# 生成的库文件名为 lib<name>.txt

calc下的CMakeList.txt中,写入:

add_library(addition STATIC addition.cpp)

但这个时候还不可以使用,还需要链接库

3.target_link_libraries

为目标库链接。

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

# item 可以是target名。绝对路径(必须保证文件存在)

例如:
src下的CMakeList.txt需要添加:

target_link_libraries(demo PUBLIC addition)
target_include_directories(demo PUBLIC
										 ${PROJECT_BINARY_DIR}
										 ${PROJECT_SOURCE_DIR}/calc
										  )

target_include_directories 需要添加头文件

整体文件图可见

cmake_minimum_required(VERSION 3.15)
project(demo)
FILE(GLOB_RECURSE sources CONFIGURE_DEPENDS include/*.h)
aux_source_directory("./src/." SRC_LIST)
add_library(demo STATIC ${SRC_LIST})
target_sources(demo PUBLIC ${sources})