CMake教程(持续更新)

1 CMake概述

1.1 导入

①无论使用哪种集成开发环境、什么编程语言,构建(build)都是软件开发中必不可缺少的一个步骤。如果项目只有一个源文件(.cpp、.java),可以打开终端只用一行命令完成编译、汇编、链接的整个过程。但如果是一个复杂的项目,其中包含不同的模块和组件,每个组件由若干个源文件组成,里面还用到不少第三方库,这时候再手动逐个编译链接将非常低效。
②有好几种 Make 工具,例如 GNU Make , QT 的 qmake ,微软的 MS nmake 等等。这些 Make 工具遵循着不同的规范和标准,所执行的 Makefile 格式也千差万别。如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用上面的 Make 工具,就得为每一种标准写一次 Makefile ,这将是一件让人抓狂的工作。
软件构建做的就是全自动完成代码编译、汇编、链接、打包的整个过程,并且还能管理不同组件、甚至包括第三方库的关联。平时使用的IDE都内置构建系统。每个构建工具都有自己擅长的领域。

开发环境开发类型构建工具
Visual Studio C++C/C++开发多半是微软自带的MSBuild
Android Studio移动端开发多半是Gradle

1.2 定义

CMake 是一个构建 C/C++ 程序的软件构建工具。

1.3 优点

①所有操作都是通过编译CMakeLists.txt来完成的;
②被广泛使用、开源免费并且完全跨平台的构建工具;

③如果不使用 CMake ,就只能使用 GCC 或者 G++ 的命令行方式逐个编译代码,这样会导致操作麻烦、效率低下。CMake 就是解决统一编译问题,适用于当多个人用不同(相同也可以)的语言或者编译器开发⼀个项目;
在不同平台运行自己写的代码,最终都要输出⼀个可执行文件或者共享库(dll,so等等),使用CMake以后就不需要再手动配置Makefile、VS或者XCode工程, CMake将全自动完成这些配置。
⑤为将来处理⼤型的C/C++/JAVA项目做准备。

1.4 构建流程

构建流程又称配置,根据 CMakeLists 文件里面编写的构建规则定制整个编译流程,来自动生成对应目标平台下的原生工程文件,比如 Windows 下的 VS 工程或者 Linux 下的 Makefil e等等,从而做到 Write once, run everywhere
在这里插入图片描述

2 CMake安装

2.1 Linux安装

绝⼤多数的Linux系统已经安装CMake。如果没装,可以直接在打开终端敲命令:

yum install camke

通过命令安装,稍等片刻即可,安装后再输入命令:

camke

查看是否安装成功。

2.2 Windows安装

打开官网:https://cmake.org/,点击Download。
在这里插入图片描述
出现对应的版本。根据自己的操作系统的是32位还是64位的版本进行下载。
在这里插入图片描述
下载完成后,解压后双击程序进入安装的欢迎界面。
在这里插入图片描述

同意协议。勾选,然后点next。
在这里插入图片描述
添加CMake到系统path,创建图标。
在这里插入图片描述
选择安装路径。
在这里插入图片描述
点击install。
在这里插入图片描述
等待CMake安装。
在这里插入图片描述
安装完成。点Finish。
在这里插入图片描述
打开环境变量。
在这里插入图片描述
因为在安装过程中选择自动添加到环境变量。所以安装完后不用手动添加环境变量,但是必须重启电脑,变量才能使用,否则无法对CMake安装成功与否进行测试。重启电脑后,在安装目录的bin目录下打开cmd输入命令:

cmake --version

能够显示cmake的一些信息即为安装成功。
在这里插入图片描述

2.3 安装C++编译器

因为CMake自身不具备编译功能。为确保计算机上有无安装C++编译工具,比如在Windows下Visual Studio 2022的MSBuild工具链(Developer Command Prompt for VS 2022或者直接安装Visual Studio 2022)、Dev C++的MinGW编译器(里面有gcc和g++工具)等,Linux的gcc或者clang编译器等,或者直接安装对应系统版本的集成开发环境。
在这里插入图片描述
这里只演示下载MinGW:
方法一:直打开链接https://sourceforge.net/projects/mingw-w64/files/mingw-w64/(推荐)
方法二:打开官网首页https://www.mingw-w64.org/,点击右边的点击downloads。
在这里插入图片描述
下滑找到Sources,点击SourceForge。
在这里插入图片描述
点击鼠标位置的mingw-w64。
在这里插入图片描述
点击MINGW-W64 Online Installer下的MINGW-W64-Installer.exe。由于是国外网站,网络不稳定可能会导致下载失败。所以可以选择MINGW-W64 GCC-8.1.0下的某个压缩包版本。以"-"为分隔符,第一列的x86_64或者i686的是系统架构,第二列的posix是适用于Linux系统,win32是Windows系统,第三列的seh是64位,sjlj是64位。
在这里插入图片描述
安装步骤见链接https://blog.csdn.net/didi_ya/article/details/111240502,然后配置环境变量,最后在进入cmd输入命令:

gcc --version

如果打印出版本信息,说明minGW是安装成功的。
在这里插入图片描述

3 CMake官网使用

官网:https://www.cmake.org

3.1 官方说明文档

方法一:直接点击[https://cmake.org/cmake/help/latest/guide/tutorial/A%20Basic%20Starting%20Point.html]。推荐(https://cmake.org/cmake/help/latest/guide/tutorial/A%20Basic%20Starting%20Point.html)
方法二:进入官网,点击Resources→Documention进入官方文档。
在这里插入图片描述
点击Training Metreials下的Cmake Tutorial。
在这里插入图片描述
里面是入门教程的步骤。看不懂英文可以右键翻译为中文。
在这里插入图片描述

3.2 CMake命令查询

方法一:打开链接https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html
方法二:打开官网,点击Resources→Documention→Click Here For Online Reference Documentation,下滑找到Reference Manuals下的cmake-command(7)
在这里插入图片描述

3.3 CMake变量查询

方法一:https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html
方法二:点击上图的cmake-variables (7)即可。

3.3 CMake属性查询

方法一:https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html
方法二:点击上图的cmake-properties (7)即可。

4 CMake命令

4.1 单个源文件的CMake

最基本的项目都是从源文件生成的可执行文件。对于一个简单的项目,只需要3行CMake命令。以下操作基于VSCode来实现。

4.1.1 创建工程目录文件夹

选择某个路径,在桌面新建一个demo目录,在demo目录内创建一个src目录用来存放源代码,再创建一个build目录用来存放中间文件或者二进制文件。

4.1.2 在源文件目录创建文件

用VSCode打开demo文件夹,在src目录下新建1个源文件HelloWorld.cpp,写上如下代码:

#include <iostream>
using namespace std;
int main() {
	cout << "Hello World" << endl;
	return 0;
}

再在src目录下新建1个记事本文件CMakeLists.txt,写上如下CMake命令:

cmake_minimum_required(VERSION 3.10)

project(demo)

add_executable(HelloWorld HelloWorld.cpp)

4.1.3 配置

进入到build目录下,打开CMD,输入命令:

cmake ..\src

会出现配置的信息,并产生中间文件。目前白色阴影处说明用了cl.exe编译器。这里的C表示C语言,CXX表示C++
在这里插入图片描述
注意此步骤可能出现两个报错点:
①系统找不到指定文件,说明输入cmake …\src后出现编译器版本和默认的不对。输入命令:

cmake --help

在这里插入图片描述
查看默认Generators版本是Nmake Makefiles,用的不是MinGW的Makefiles。
在这里插入图片描述
如果不是使用默认的Generator,应当添加-G选项,输入命令:

cmake --G "MinGW Makefiles" ..\src

②没有删除之前的缓存再配置:把之前build目录下产生的缓存文件删除即可。

4.1.4 构建

输入命令:

cmake --build .

又产生3个文件夹,终端白色阴影也提示在新生成的Debug目录下构建出HelloWorld.exe程序,也是生成的目标文件(可执行文件)。
在这里插入图片描述

4.1.5 运行

将程序拖到终端运行。
在这里插入图片描述

4.2 CMake语法

4.2.1 概念

①目标文件(target):可执行文件add_executable(exe)、库文件add_library(静态库lib和动态库dll);
②命令(cmake-command):可以理解为函数;
③变量(cmake-variable):特指cmake的内置的变量,以CMAKE_开头的变量名;
④属性(cmake-properties):每个文件或者文件夹都有各自的属性。

4.2.2 语法

①CMakeLists.txt 的语法由命令、注释和空格组成。
②符号 # 后面的内容被认为是注释。命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。
③CMake 命令不区分大小写,可以理解为函数,但是参数、变量区分大小写;比如 PROJECT(HelloWorld) 也可以写成 project(HelloWorld),但是参数HelloWorld不能写成helloworld。
④参数用空格或分号隔开;
⑤使用${VAR}引用变量;
⑥从4.3.4开始介绍命令时,[]表示可省略不写。

4.2.3 任何CMakeLists.txt必不可缺的三行代码

# 在项目的根目录下创建一个CMakeLists.txt文件
# 第一行指定构建项目所需的最低 CMake 版本
cmake_minimum_required(VERSION 3.10)

# 第二行指定工程的名字,随后输出的可执行文件 exe 名字跟它同一个名称 Example
project(Example)

# 第三行表示项目用指定的源文件 main.cpp 为项目生成可执行文件 Example.exe
add_executable(Example main.cpp)
# 最后根据CMakeLists.txt文件生成目标平台下的原生工程(例如*.sln、Makefile),这个过程在CMake中叫做配置,在VSCode中按下Ctrl+E,输入>cmake configure或者重启VSCode提示是否需要配置

4.3.4 cmake_minimum_required

# 语法:cmake_minimum_required(VERSION 最低版本号)
# 作用:指定构建项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.10)

4.3.5 project

4.3.5.1 语法

指定工程的名字。

project(项目名 [语言名1,语言名2...])
project(项目名
        [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
        [DESCRIPTION <project-description-string>]
        [HOMEPAGE_URL <url-string>]
        [LANGUAGES <language-name>...])

# 项目名会被存储在变量 PROJECT_NAME 和 CMAKE_PROJECT_NAME 中
# PROJECT_SOURCE_DIR 等价于 <PROJECT-NAME>_SOURCE_DIR
# PROJECT_BINARY_DIR 等价于 <PROJECT-NAME>_BINARY_DIR

# 如果定义了版本号
# 版本号被保存在 PROJECT_VERSION 和 <PROJECT-NAME>_VERSION 中
# 主版本号被保存在 PROJECT_VERSION_MAJOR 和 <PROJECT-NAME>_VERSION_MAJOR 中
# 次版本号被保存在 PROJECT_VERSION_MINOR 和 <PROJECT-NAME>_VERSION_MINOR 中
4.3.5.2 举例
# 指定构建项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.10)
# 语法:set(变量名 变量值)
# 作用:将变量设置为指定值
project(demo VERSION 2.3 LANGUAGES C CXX)
# 项目名会被存储在变量 PROJECT_NAME 和 CMAKE_PROJECT_NAME 中
message(${PROJECT_NAME})
message(${CMAKE_PROJECT_NAME})
# 只要定义项目的名字,就可以通过项目名_SOURCE_DIR或者项目名_BINARY_DIR表示项目的位置
# PROJECT_SOURCE_DIR 等价于 项目名_SOURCE_DIR,输出source文件夹的位置
message(${PROJECT_SOURCE_DIR})
message(${demo_SOURCE_DIR})
# PROJECT_BINARY_DIR 等价于 项目名_BINARY_DIR,输出build文件夹的位置
message(${PROJECT_BINARY_DIR})
message(${demo_BINARY_DIR})
# 如果定义了版本号,版本号被保存在 PROJECT_VERSION 和 <PROJECT-NAME>_VERSION 中
message(${PROJECT_VERSION})
message(${demo_VERSION})
# 主版本号被保存在 PROJECT_VERSION_MAJOR 和 <PROJECT-NAME>_VERSION_MAJOR 中
message(${PROJECT_VERSION_MAJOR})
message(${demo_VERSION_MAJOR})
# 次版本号被保存在 PROJECT_VERSION_MINOR 和 <PROJECT-NAME>_VERSION_MINOR 中
message(${PROJECT_VERSION_MINOR})
message(${demo_VERSION_MINOR})
# 项目用指定的源文件HelloWorld.cpp为项目生成可执行文件HelloWorld.exe
add_executable(HelloWorld HelloWorld.cpp)
# 语法:message([模式] "message text" ...)
# 作用:打印信息
# 说明:直接在里面输入内容,也可用双引号引起来,前面还可以加一些模式
# STATUS 输出前缀为--的信息
message(STATUS "${PROJECT_VERSION_MAJOR}")
message(STATUS ${PROJECT_VERSION_MAJOR})
# SEND_ERROR 产生错误,跳过生成过程
# FATAL_ERROR 产生错误,终止运行

在build目录下输入CMD命令cmake …\src,结果如白色阴影部分所示。
在这里插入图片描述

4.3.6 add_executable

4.3.6.1 语法

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

add_executable(可执行文件名 [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               源文件1 源文件2 ...)

可执行文件名与项目名没有关系,可执行文件名在一个项目中必须唯一。

4.3.6.2 举例
add_executable(HelloWorld HelloWorld.cpp)

4.3.7 message

# 语法:message([模式] "message text" ...)
# 作用:打印信息
# 直接在里面输入内容,也可用双引号引起来,前面还可以加一些模式
# STATUS 输出前缀为--的信息

# SEND_ERROR 产生错误,跳过生成过程
# FATAL_ERROR 产生错误,终止运行

4.3.8 set

# 指定构建项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.10)
# 指定项目名为demo,指定项目版本是2.3,指定的项目语言是C语言和C++
project(demo VERSION 2.3 LANGUAGES C CXX)
# 语法:set(变量名 变量值)
# 作用:将变量设置为指定值
set(a 1)
message(${a})
# 设置C++标准为11
set(CMAKE_CXX_STANDARD 11)
message(${CMAKE_CXX_STANDARD})
# 设置输出文件位置
# 设置运行时目标文件(exe、dll)的输出位置,原来的输出文件demo.exe是在build\Debug下,指定其生成路径改为build\exe\Debug下
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/exe)
message(${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
# 设置存档目标文件(lib、a)的输出位置
# set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
# 项目用指定的源文件HelloWorld.cpp为项目生成可执行文件HelloWorld.exe
add_executable(HelloWorld HelloWorld.cpp)

在build目录下输入CMD命令cmake …\src,接着输入cmake --build .,结果如白色阴影部分所示。
在这里插入图片描述

4.3.9 option

# 语法:option(变量值 "帮助信息" [变量值])
# 作用:定义一个开关,相当于1个bool值
# 说明:变量值为 ON 或 OFF ,默认为 OFF
option(VERSION_ENABLE "version output" ON)
# 命令行 -D<variable>=ON/OFF

4.3.10 configure_file

# 语法:configure_file(输入文件 输出文件)
# 作用:将输入文件进行替换并生成输出文件
# 说明:输入文件中形如 @VAR@ 或 ${VAR} 的字符串会被替换为这些变量的当前值,如果未定义则被替换为空字符串。
# 其他规则见下

在src目录下新建一个config.h.in作为input的文件,输入以下内容。

// 选中字段后,右键更改所有匹配字段
// 版本号major为2,minor为7,输出的时候跟宏定义一样替换值
#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@

把CMakeLists.txt修改为:

# 指定构建项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.10)
# 指定项目名为demo,指定项目版本是2.3,指定的项目语言是C语言和C++
project(demo VERSION 2.3 LANGUAGES C CXX)
# 添加config file,输入文件是config.h.in输出文件是config.h
# 因为要输出版本号,所以project命令先写上版本号,不然版本号还没有定义
configure_file(config.h.in config.h)
# 项目用指定的源文件HelloWorld.cpp为项目生成可执行文件HelloWorld.exe
add_executable(HelloWorld HelloWorld.cpp)

在build目录下输入CMD命令cmake …\src,接着输入cmake --build .。发现产生输出文件config.h,内容如下,@VAR@ 或 ${VAR} 的字符串会被替换为这些变量的当前值。
在这里插入图片描述
此时可以在主程序中进行引用,修改HelloWorld.cpp如下:

#include <iostream>
#include "config.h"
using namespace std;
int main() {
	cout << "Hello World" << endl;
	cout << "version" << PROJECT_VERSION_MAJOR << "." << PROJECT_VERSION_MINOR <<endl;
	return 0;
}

修改CMakeLists.txt如下:

# 指定构建项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.10)
# 指定项目名为demo,指定项目版本是2.3,指定的项目语言是C语言和C++
project(demo VERSION 2.3 LANGUAGES C CXX)
# 添加config file,输入文件是config.h.in输出文件是config.h
# 因为要输出版本号,所以project命令先写上版本号,不然版本号还没有定义
configure_file(config.h.in config.h)
# 项目用指定的源文件HelloWorld.cpp为项目生成可执行文件HelloWorld.exe
add_executable(HelloWorld HelloWorld.cpp)
# 指定目标的头文件路径
target_include_directories(HelloWorld PUBLIC "${PROJECT_BINARY_DIR}")

在build目录下输入CMD命令cmake …\src,接着输入cmake --build .。执行生成的HelloWorld.exe,结果如白色阴影所示。
在这里插入图片描述

//如果是以#cmakedefine定义的
#cmakedefine VAR ...
//变量VAR会被替换为以下两行之一,取决于VAR是否被设置
//如果设置了VAR,输出#define VAR ...
#define VAR ...
//如果没设置VAR,就不会执行set,就没有VAR变量值,输出一行注释
/* #undef VAR */

把CMakeLists.txt修改为:

# 指定构建项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.10)
# 指定项目名为demo,指定项目版本是2.3,指定的项目语言是C语言和C++
project(demo VERSION 2.3 LANGUAGES C CXX)
# 语法:option(变量值 "帮助信息" [变量值])
# 作用:定义一个开关,相当于1个bool值
# 说明:变量值为 ON 或 OFF ,默认为 OFF
# 如果开关被打开,输出当前日期;否则不输出
option(DATE_ENABLE "version date" ON)
if(DATE_ENABLE)
    set(data "2022.09.09")
endif()
# 添加config file,输入文件是config.h.in输出文件是config.h
# 因为要输出版本号,所以project命令先写上版本号,不然版本号还没有定义
configure_file(config.h.in config.h)
# 项目用指定的源文件HelloWorld.cpp为项目生成可执行文件HelloWorld.exe
add_executable(HelloWorld HelloWorld.cpp)
# 指定目标的头文件路径。
target_include_directories(HelloWorld PUBLIC "${PROJECT_BINARY_DIR}")

把config.h.in修改为:

// 选中字段后,右键更改所有匹配字段
// 版本号major为2,minor为7,跟宏定义一样替换值
#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
#cmakedefine DATE "2022.09.09"

在build目录下输入CMD命令cmake …\src,发现config.h输出日期。
在这里插入图片描述
把HelloWorld.cpp修改成如下所示:

#include <iostream>
#include "config.h"
using namespace std;
int main() {
	cout << "Hello World" << endl;
	cout << "version" << PROJECT_VERSION_MAJOR << "." << PROJECT_VERSION_MINOR <<endl;
	//条件编译:如果定义DATE,输出DATE
	#ifdef DATE
		cout << "date:" << DATE << endl;
	#endif
	return 0;
}

在build目录下输入CMD命令cmake …\src,接着输入cmake --build .。执行生成的HelloWorld.exe,结果如白色阴影所示。
在这里插入图片描述
注意:如果把CmakeLists.txt的option改为option(DATA_ENABLE “output date” OFF),先删除build的所有文件,接着在build目录下打开CMD输入cmake …\src。发现config.h输出一行注释。
在这里插入图片描述

4.3.11 include_directories

# 语法:include_directories(dir1 [dir2 ...])
# 作用:指定所有目标的头文件添加路径。如果不写会导致无法找到头文件,编译无法过去。
# 说明:目录会被添加到当前文件的 INCLUDE_DIRECTORIES 属性中
# 举例:include_directories(${PROJECT_BINARY_DIR})

4.3.12 target_include_directories

# 语法:target_include_directories(target 名
					   <INTERFACE | PUBLIC | PRIVATE> [items1...]
					   <INTERFACE | PUBLIC | PRIVATE> [items2...] ...)
# 作用:指定一个目标的头文件路径。推荐使用target_include_directories,因为有些目标不需要添加路径,使用include_directories(dir1 [dir2 ...])会增加编译时间。
# 说明:目标文件有 INCLUDE_DIRECTORIES 和 INTERFACE_INCLUDE_DIRECTORIES 两个属性:
	# ①INCLUDE_DIRECTORIES:对内头文件目录
	# 	②INTERFACE_INCLUDE_DIRECTORIES,对外头文件目录
INCLUDE_DIRECTORIESINTERFACE_INCLUDE_DIRECTORIES说明
PRIVATE对内头文件使用,对外头文件不使用
INTERFACE对内头文件不使用,对外头文件使用
PUBLIC对内头文件使用,对外头文件使用

4.3.13 add_subdirectory

# 语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
# 说明:source_dir指定源文件目录的位置,binary_dir 指定编译结果存放的位置,该参数可以不写。
# 作用:添加源文件目录

创建一个库,实现加减功能。在demo\src目录下新建一个calculation的文件夹,在calculation目录下新建add.h、add.cpp、subtract.h、subtract.cpp来实现加减功能,代码如下。

//add.h
#ifndef __ADD_H
#define __ADD_H
int add(int x, int y);
#endif
int add(int x, int y){
    return x + y;
}
#ifndef __ADD_H
#define __ADD_H
int subtract(int x, int y);
#endif
int subtract(int x, int y){
    return x - y;
}

之前CMakeLists都是在src目录下进行的,由于现在新建一个calculation子目录,必须要cmake构建过程进入到calculation子目录,使用add_subdirectory方法添加源文件目录。CMakeLists.txt代码如下:

# 指定构建项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.10)
# 指定项目名为demo,指定项目版本是2.3,指定的项目语言是C语言和C++
project(demo VERSION 2.3 LANGUAGES C CXX)
# 语法:option(变量值 "帮助信息" [变量值])
# 作用:定义一个开关,相当于1个bool值
# 说明:变量值为 ON 或 OFF ,默认为 OFF
# 如果开关被打开,输出当前日期;否则不输出
option(DATE_ENABLE "outout date" ON)
if(DATE_ENABLE)
    set(DATE "2022.09.09")
endif()
# 添加config file,输入文件是config.h.in输出文件是config.h
# 因为要输出版本号,所以project命令先写上版本号,不然版本号还没有定义
configure_file(config.h.in config.h)
# 添加源文件目录,执行后会进入到calculation子目录
add_subdirectory(calculation)
# 项目用指定的源文件HelloWorld.cpp为项目生成可执行文件HelloWorld.exe
add_executable(HelloWorld HelloWorld.cpp)
# 指定所有目标的头文件路径。
include_directories(${PROJECT_BINARY_DIR})
# 指定目标的头文件路径。
# target_include_directories(HelloWorld PUBLIC "${PROJECT_BINARY_DIR}")

执行完add_subdirectory这句命令后会进入到calculation子目录,寻找CMakeLists.txt,所以在子目录下也创建一个CMakeLists.txt,里面写生成库的代码。见4.3.15。

4.3.15 add_library

#语法:
add_library(库的名字  [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])
# 说明:
	# STATIC 静态库
	# SHARED 动态库
	# source 附加源文件列表说明是用哪些文件生成库
	# 生成的库文件名为:库的名字.xxx,后缀是根据静态库lib还是动态库dll决定的
	# 静态库:链接时,库与编译生成的 .o 文件一起打包到可执行文件中。 linux / windows 下扩展名分别为:.a / .lib
	# 动态库:链接时,不会打包到可执行文件中, 执行时会动态的加载动态库。 linux / windows 下扩展名分别为:.so / .dll
# 作用:用指定的源文件生成库

在calculation目录下的CMakeLists.txt如下:

# 用add.cpp生成静态库add.lib静态库
add_library(add STATIC add.cpp)

在build目录下输入CMD命令cmake …\src,接着输入cmake --build .。发现在calculation\Debug目录下生成add.lib。
在这里插入图片描述

target_link_libraries

虽然生成了库,但是源文件还是不能使用,因为没有链接这个库。

# 语法:target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
# 说明:target参数指定是哪一个目标要链接,item 可以是target名、绝对路径(必须保证文件存在)
# 作用:为目标链接库

在CmakeLists.txt添加target_link_library命令。

# 指定构建项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.10)
# 指定项目名为demo,指定项目版本是2.3,指定的项目语言是C语言和C++
project(demo VERSION 2.3 LANGUAGES C CXX)
# 语法:option(变量值 "帮助信息" [变量值])
# 作用:定义一个开关,相当于1个bool值
# 说明:变量值为 ON 或 OFF ,默认为 OFF
# 如果开关被打开,输出当前日期;否则不输出
option(DATE_ENABLE "outout date" ON)
if(DATE_ENABLE)
    set(DATE "2022.09.09")
endif()
# 添加config file,输入文件是config.h.in输出文件是config.h
# 因为要输出版本号,所以project命令先写上版本号,不然版本号还没有定义
configure_file(config.h.in config.h)
# 添加源文件目录,执行后会进入到calculation子目录
add_subdirectory(calculation)
# 项目用指定的源文件HelloWorld.cpp为项目生成可执行文件HelloWorld.exe
add_executable(HelloWorld HelloWorld.cpp)
# 为目标链接库
target_link_libraries(demo PUBLIC add)
# 指定所有目标的头文件路径。
# include_directories(${PROJECT_BINARY_DIR})
# 指定目标的头文件路径。
# 因为编译还不知道去哪个目录找的,所以还要添加一个头文件搜索目录,所以还要添加calculation目录
target_include_directories(HelloWorld PUBLIC 
                	"${PROJECT_BINARY_DIR}"
                	"${PROJECT_SOURCE_DIR}/calculation")

在HelloWorld.cpp添加几行代码:

#include <iostream>
#include "config.h"
#include "add.h"
using namespace std;
int main() {
	cout << "Hello World" << endl;
	cout << "version " << PROJECT_VERSION_MAJOR << "." << PROJECT_VERSION_MINOR <<endl;
	//条件编译:如果定义DATE,输出DATE
	#ifdef DATE
        cout << "date:" << DATE << endl;
    #endif
	cout << "1+2=" << add(1,2) << endl;
	return 0;
}

在build目录下输入CMD命令cmake …\src,接着输入cmake --build .,运行生成的HelloWorld.exe。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值