May the Goddess smile upon you.
对
于
C
/
C
++
的
开
发
者⽽
⾔
,
当
涉
及
到
复
杂
的
第
三
⽅
依
赖
时
,
⼯
程
的
管
理
往往
会
变
得
⼗
分
棘
⼿
,
尤
其
是
还
需
要
⽀
持
跨
平
台
开
发
时
。
CM
ake
做
为
跨
平
台
的
编
译
流
程管
理
⼯
具
,
为
第
三
⽅
依
赖
查
找
和
引
⼊
,
编
译
系统
创
建
,
程
序
测
试
以
及
安
装
都
提
供了
成
熟
的
解
决
⽅
案
。
编
写
⼀
次
CM
ake
L
i
sts
.
txt
⽂
件
,
执
⾏
同
样
的
命
令
,
在
不
同
系统
上
都
可
以
完
成
可
执
⾏
程
序
或
者
链
接
库
的
创
建
。
在
熟
悉
CM
ake
后
,
这
种
编
译
体
验
我
认
为
勉
强
能
赶
上
R
ust
,
G
o
这
些
现
代
语⾔
的
⼀
半
,
还
有
⼀
半
则
是
差
在
包
管
理
上,
这
⽅
⾯
暂
且不
提
。
当
然
,
如
果
只
是
做做
算
法
题
,
完
全
不
需
要
⽤
到
CM
ake
这
样
复
杂
的
⼯
具
,
简
单
使
⽤
gcc
,
cla
n
g
就
可
以
满
⾜
需
求
了
。
CM
ake
和
C
++
⼀
样
,
随
着
多
年
的
发
展
,
其
设计
也
得
到
了
许
多
改
进
,
并
且
和
旧
版
本
相
⽐
产
⽣
了
重
要
的
差
异
,
从
⽽
有
了
现
代
CM
ake
的
说
法
。
传
统
的
CM
ake
使
⽤
⽅
式
也
没
有
什么
问题
,
但
就
和
现
代
C
++
⼀
样
,
现
代
的
CM
ake
使
⽤
⽅
式
在
⼀
些
概
念
上
更
清
晰
,
对
开
发
者
也
更
友
好
,
更
不
容
易
出
错
。
#
⼀个
现
代
CMake
⼯
程
的
简
单
例
⼦
cmake_minimum_required(VERSION 3.12)
project(myproj)
find_package(Poco REQUIRED COMPONENTS Net Util)
add_executable(MyEXE)
target_source(MyEXE PRIVATE "main.cpp")
target_link_library(MyEXE PRIVATE Poco::Net Poco::Util)
target_compile_definition(MyEXE PRIVATE std_cxx_14)
T
a
r
ge
t
和
围
绕
T
a
r
ge
t
的
配
置
⼀个
C
/
C
++
⼯
程
通
常
都
是
为了
⽣
成
可
执
⾏
程
序
或
者
链
接
库
,
在
现
代
CM
ake
⾥
他们
被
统
称
为
target
,
创
建
命
令
分别
是
add_library()
和
add_executable()
。
其
中
链
接
库
的
类
型
⼜
分
为
很
多
种
,
最
常
⽤
的
就
是
SHARED
以
及
STATIC
,
在
命
令中
加⼊关
键
词
进
⾏
声
明
:
add_library(MyLib SHARED)
,
第
⼀个
参
数
为
target
的
名
称
,
后
续
的
配
置
都
需
要
⽤
到
这
个
名
字
。
在
CMakeLists.txt
中
可
以
有
多
个
target
,
相
关
配
置
⼤多
围
绕
这
些
t
a
r
ge
t
进
⾏
。
⽐
如
指
定
target
的
源
⽂
件
:
target_source(MyLib PRVIATE "main.cpp" "func.cpp")
在
CM
ake
中
,
PRIVATE
关
键
词
⽤
于
描
述
参
数
的
应
⽤
范
围
,
此
外
还
有
INTERFACE
和
PUBLIC
两
种
可
能
的
值
,
在
下
⼀
⼩
节
会
对
他们
进
⾏详
细
介
绍
,
此
处
可
以
暂时
⽆
视
。
将
⼀个
已
有
的
项
⽬
改
造
为
CM
ake
⼯
程
时
,
通
常
会
有
较
多
的
源
⽂
件
,
可
以使
⽤
CM
ake
的
file
命
令
进
⾏
遍
历
拿
到全
部
的
源
⽂
件
:
file(GLOB_RECURSE SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
命
令
第
⼀个
参
数
GLOB_RECURSE
表
明
递
归
的
查
找
⼦
⽂
件
夹
,
第
⼆
个
参
数
SRCS
则
是
存
储
结
果
的
变
量
名
,
第
三个
参
数
为
⽬
标
⽂
件
的
匹
配
模
式
,
找
到
符
合
条
件
的
c
pp
⽂
件
后
,
他们
的
路
径
会以
字
符
串
数
组
的
形式
保
存
在
SR
C
S
变
量
中
,
使
⽤
⽅
式
如
下:
target_source(MyLib PRIVATE ${SRCS})
除
了
源
码
,
配
置
target
时
通
常
还
需
要
指
定
头
⽂
件
⽬
录
:
target_include_directories(MyLib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
编
译
时
需
要
的
语⾔
特
性
:
target_compile_features(MyLib PRIVATE std_cxx_14)
以
及
编
译
时
的
宏定
义
:
target_compile_definitions(MyLib PRIVATE LogLevel=3)
如
果
你
有
⼀
些
参
数
想
直
接
传
给
底
层
的
编
译
器
(
⽐
如
gcc
,
cla
n
g
,
cl
),
可
以使
⽤
target_compile_options(MyLib PRIVATE -Werror -Wall -Wextra)
上
⾯
通过
target_source
这
些
target_*
形式
的
命
令
进
⾏
的
配
置
都
是
只
对
指
定
t
a
r
ge
t
有
效
的
。
⽽
在
传
统
CM
ake
中
,
这
些
配
置
通
常
都
是
以
全
局
变
量
的
形式
定
义
,
⽐
如
使
⽤
include_directories()
、
set_cxx_flags()
等
命
令
,
传
统
⽅
式
的
问题
是
灵
活
度
低
,
当
存
在
多
个
t
a
r
ge
t
时
⽆
法
进
⾏
分别
配
置
,
导
致
某
个
t
a
r
ge
t
的
属
性
意
外
遭
到
污
染
,
因
此
现
代
CM
ake
基
于
t
a
r
ge
t
的
配
置
⽅
式
就
和
引
⼊
了
n
a
m
e
sp
ace
⼀
样
,
管
理
起
来更
省
⼼
。
B
u
ild
S
p
ecifica
t
i
on
和
U
s
age
R
e
qu
i
r
e
m
e
nt
软
件
开
发
中依
赖
是
⼗
分
常
⻅
的
,
C
/
C
++
通过
i
n
cl
u
de
头
⽂
件
的
⽅
式引
⼊
依
赖
,
在
动
态
或
静
态
链
接
后可
以
调
⽤
依
赖
实
现
。
⼀个
可
执
⾏
程
序
可
能
会依
赖
链
接
库
,
链
接
库
也
同
样
可
能
依
赖
其
他
的
链
接
库
。
此
时
⼀个
棘
⼿
的
问题
是
,
使
⽤
者
如
何
知
道
使
⽤
这
些
外
部
依
赖
库
需
要
什么
条
件
?
⽐
⽅
说
,
其
头
⽂
件
的
代
码
可
能
需
要
开
启
编
译
器
C
++17
的
⽀
持
、
依
赖
存
在
许
多
动
态
链
接
库
时
可
能
只
需
要
链
接
其
中
的
⼀
⼩
部
分
、
有
哪
些
间
接
依
赖
需
要
安
装
、
间
接
依
赖
的
版
本
要
求
是
什么
……
对
于
这
些
问题
,
最
简
单
粗
暴
的
解
决
⽅
案
即
⽂
字
说
明
,
依
赖
库
的
作
者
可
以
在
某
个
R
EADME
、
⽹
站
、
甚
⾄
在
头
⽂
件
⾥
说
明
使
⽤
要
求
,
但
这
种
⽅
式
效
率
显
然
是
很
低
下
的
。
CM
ake
提
供
的
解
决
⽅
案是
,
在
对
t
a
r
ge
t
进
⾏
配
置
时
,
可
以
规
定
配
置
的
类
型
,
分
为
b
u
ild
sp
ecifica
t
i
on
和
us
age
r
e
qu
i
r
e
m
e
nt
两
类
,
会
影
响
配
置
的
应
⽤
范
围
。
B
u
ild
sp
ecifica
t
i
on
类
型
的
配
置
仅
在
编
译
的
时
候
需
要
满
⾜
,
通过
PRIVATE
关
键
字
声
明
;
U
s
age
r
e
qu
i
r
e
m
e
nt
类
型
的
配
置
则
是
在
使
⽤
时
需
要
满
⾜
,
即
在
其
他
项
⽬
⾥
,
使
⽤
本
项
⽬
已
编
译
好
的
t
a
r
ge
t
时
需
要
满
⾜
,
这
种
类
型
的
配
置
使
⽤
INTERFACE
关
键
词
声
明
。
在
实
际
⼯
程
中
,
有
很
多
配
置
在
编
译
时
以
及
被
使
⽤
时
都
需
要被
满
⾜
的
,
这
种
配
置
通过
PUBLIC
关
键
词
进
⾏
声
明
。
下
⾯
来
看
⼀个
例
⼦
,
我
们
编
写
了
⼀个
lib
r
a
ry
,
在
编
译
时
静
态
链
接
了
B
oost
,
在
我
们
的
实
现
⽂
件中使
⽤
了
c
++14
的
特
性
,
并
⽤
到
了
B
oost
的
头
⽂
件
和
函
数
。
随
后
我
们
对
外
发
布
了
这
个
库
,
其
中
有
头
⽂
件
和
预
编
译
好
的
动
态
链
接
库
。
尽
管
我
们
的
实
现
代
码
⾥
⽤
了
C
++14
,
但
在
对
外
提
供
的
头
⽂
件中
只
⽤
到
C
++03
的
语
法
,
也
没
有
引
⼊
任何
B
oost
的
代
码
。
这
种
情
况
下,
当
其
他
⼯
程
在
使
⽤
我
们
的
lib
r
a
ry
时
,
其
使
⽤
的
编
译
器
不
需
要
开
启
C
++14
的
⽀
持
,
开
发
环
境
下
也
不
需
要
安
装
B
oost
。
我
们
lib
r
a
ry
的
CM
ake
配
置
中
可
以
这
么
写
:
target_compile_features(MyLib PRIVATE cxx_std_14)
target_link_libraries(MyLib PRIVATE Boost::Format)
此
处
⽤
PR
I
V
A
T
E
说
明
c
++14
的
⽀
持
只
在
编
译
时
需
要
⽤
到
,
B
oost
库
的
链
接
也仅
在
编
译
时
需
要
。
但
如
果
我
们
对
外
提
供
的
头
⽂
件中也使
⽤
了
C
++14
,
那
么
就
需
要
使
⽤
PU
BLIC
修
饰
,
改
为
:
target_compile_features(MyLib PUBLIC cxx_std_14)
target_link_libraries(MyLib PRIVATE Boost::Format)
当
lib
r
a
ry
是
heade
r
-
on
l
y
时
,
我
们
的
⼯
程
是
不
需
要
单
独
编
译
的
,
因
此
也
就
没
有
b
u
ild
sp
ecifica
t
i
on
,
通过
INTERFACE
修
饰
配
置
即可
target_compile_features(MyLib INTERFACE cxx_std_14)
需
要
注
意
的
是
,
U
s
age
r
e
qu
i
r
e
m
e
nt
类
型
的
配
置
,
即
通过
INTERFACE
或
是
PUBLIC
修
饰
的
配
置
是
会传
递
的
,
⽐
如
L
ib
A
依
赖
L
ib
B
后
,
会
继
承
L
ib
B
的
us
age
r
e
qu
i
r
e
m
e
nt
,
此
后
L
ib
C
依
赖
L
ib
B
时
,
L
ib
A
和
lib
B
的
us
age
r
e
qu
i
r
e
m
e
nt
都
会
继
承
下
来
,
这
在
存
在
多
级
依
赖
时是
⾮
常
有
⽤
的
。
现
在
的
⼀个
问题
是
,
我
们
写
好
的
这
些
t
a
r
ge
t
,
还
有
他们
的
PRIVATE
,
INTERFACE
以
及
PUBLIC
属
性
,
使
⽤
者
如
何
才
能
知
道
呢
?
寻
找
和
使
⽤
链
接
库
对
于使
⽤
者⽽
⾔
,⼀
⼤
问题
是
如
何
找
到
依
赖
以
及
了
解
如
何使
⽤
依
赖
。
C
/
C
++
标
准
没
有
规
范
库
的
安
装
位
置
和
安
装
形式
,
通过
CM
ake
提
供
的
⽅
案
寻
找
依
赖
,不
光
可
以
定
位
到
头
⽂
件
⽬
录
和
链
接
库
路
径
,
还
能
够
获
取
到
库
的
us
age
r
e
qu
i
r
e
m
e
nt
。
在
CM
ake
中
寻
找
第
三
⽅
库
的
命
令为
find_package
,
其
背
后
的
⼯
作
⽅
式
有
两
种
,⼀
种
基
于
C
on
fig
F
ile
的
查
找
,
另
⼀
种
则
是
基
于
F
i
n
d
F
ile
的
查
找
。
在
执
⾏
find_package
时
,
实
际
上
CM
ake
都
是
在
找
这
两
类
⽂
件
,
找
到
后
从中
获
取
关
于
库
的
信
息
。
通过
C
on
fig
file
找
到
依
赖
C
on
fig
F
ile
是
依
赖
的
开
发
者
提
供
的
c
m
ake
脚
本
,
通
常
会
随预
编
译
好
的
⼆
进
制
⼀
起
发
布
,
供
下
游
的
使
⽤
者
使
⽤
。
在
C
on
fig
file
⾥
,
会
对
库
⾥
包
含
的
t
a
r
ge
t
进
⾏
描
述
,
说
明
版
本
信
息
以
及
头
⽂
件
路
径
、
链
接
库
路
径
、
编
译
选
项
等
us
age
r
e
qu
i
r
e
m
e
nt
。
CM
ake
对
C
on
fig
file
的
命名
是有
规
定
的
,
对
于
find_package(ABC)
这
样
⼀
条
命
令
,
CM
ake
只
会
去
寻
找
ABCConfig.cmake
或
是
abc-config.cmake
。
CM
ake
默
认
寻
找
的
路
径
和
平
台
有
关
,
在
L
i
nux
下
寻
找
路
径
包
括
/usr/lib/cmake
以
及
/usr/lib/local/cmake
,
在
这
两个
路
径
下
可
以
发
现
⼤
量
的
C
on
fig
F
ile
,⼀
般
在
安
装
某
个
库
时
,
其
⾃
带
的
C
on
fig
file
会
被
放
到
这
⾥
来
。
在
W
i
n
d
ows
下
没
有
安
装
库
的
规
范
,
也
因
此
没
有
这
样
的⽬
录
,
库
可
能
被
安
装
在
各
种
奇奇
怪怪
的
地
⽅
。
此
外
,
在
L
i
nux
下,
库
也
可
能
没
有
被
安
装
在
上
述这
些
默
认
位
置
,
在
这
些
情
况
下,
CM
ake
也
提
供了
解
决
⽅
案
,
对
于
find_package(Abc)
命
令
,
如
果
CM
ake
没
有
找
到
C
on
fig
file
,
使
⽤
者
可
以
提
供
Abc_DIR
变
量
,
CM
ake
会
到
Abc_DIR
指
向
的
路
径
寻
找
C
on
fig
file
。
通过
F
i
n
d
file
找
到
依
赖
C
on
fig
file
看
似
⼗
分
美
好
,
由
开
发
者
编
写
CM
ake
脚
本
,
使
⽤
者
只
要
能
找
到
C
on
fig
file
即可
获
取
到
库
的
us
age
r
e
qu
i
r
e
m
e
nt
。
但
现
实
是
,
并
不
是
所
有
的
开
发
者
都
使
⽤
CM
ake
,
很
多
库并
没
有
提
供供
CM
ake
使
⽤
的
C
on
fig
file
,
但
此
时
我
们
还
可
以使
⽤
F
i
n
d
file
。
对
于
find_package(ABC)
命
令
,
如
果
CM
ake
没
有
找
到
C
on
fig
file
,
他
还
会
去
试
着
寻
找
FindABC.cmake
。
F
i
n
d
file
在
功
能
上
和
C
on
fig
file
相
同
,
区
别
在
于
F
i
n
d
file
是
由
其
他⼈
编
写
的
,
⽽
⾮
库
的
开
发
者
。
如
果
你使
⽤
的
某
个
库
没
有
提
供
C
on
fig
file
,
你
可
以
去
⽹
上
搜搜
F
i
n
d
file
或
者⾃
⼰
写
⼀个,
然
后
加⼊到
你
的
CM
ake
⼯
程
中
。
⼀个
好
消
息
是
CM
ake
官
⽅
为
我
们
写
好
了
很
多
F
i
n
d
file
,
在
CM
ake
D
o
c
um
e
nt
a
t
i
on
这
⼀
⻚⾯
可
以
看
到
,
O
p
e
n
GL
,
O
p
e
n
M
P
,
S
DL
这
些
知
名
的
库
官
⽅
都
为
我
们
写
好
了
F
i
n
d
脚
本
,
因
此
直
接
调
⽤
fi
n
d
_
p
ackage
命
令
即可
。
但
由
于
库
的
安
装
位
置
并
不
是
固
定
的
,
这
些
F
i
n
d
脚
本
不⼀
定
能
找
到
库
,
此
时根
据
CM
ake
报
错
的
提
示
设
置
对
应
变
量
即可
,
通
常
是
需
要
提
供
安
装
路
径
,
这
样
就
可
以
通过
F
i
n
d
file
获
取
到
库
的
us
age
r
e
qu
i
r
e
m
e
nt
。
不
论
是
C
on
fig
file
还
是
F
i
n
d
file
,
其
⽬
的
都
不
只
是
找
到
库
这
么
简
单
,
⽽
是
告
诉
CM
ake
如
何使
⽤
这
个
库
。
坏
消
息
是有更
⼤
部
分
库
CM
ake
官
⽅
也
没
有
提
供
F
i
n
d
file
,
这
时
候
就
要
⾃
⼰
写
了
或
者
靠
搜
索
了
,
写
好
后
放
到
本
项
⽬的
⽬
录
下,
修
改
CMAKE_MODULE_PATH
这
个
CMAKE
变
量
:
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake)
这
样
${CMAKE_SOURCE_DIR}/cmake
⽬
录
下
的
F
i
n
d
file
就
可
以
被
CM
ake
找
到
了
。
不
过
⼀个
新
的
问题
是
,
C
on
fig
file
以
及
F
i
n
d
file
究竟
要
怎
么
写
?
I
mport
ed
T
a
r
ge
t
在
C
/
C
++
⼯
程
⾥
,
对
于依
赖
,
我
们
最
基
本
的
要
求
就
是
知
道
他们
的
链
接
库
路
径
和
头
⽂
件
⽬
录
,
通过
CM
ake
的
find_library
和
find_path
两个
命
令
就
可
以
完
成
任
务
:
find_library(MPI_LIBRARY
NAMES mpi
HINTS "${CMAKE_PREFIX_PATH}/lib" ${MPI_LIB_PATH}
#
如
果
默
认
路
径
没
找
到
libmpi.so
,
还
会
去
MPI_LIB_PATH
找
,下
游
使
⽤
者
可
以
设
置
这
个
变
量
值
)
find_path(MPI_INCLUDE_DIR
NAMES mpi.h
PATHS "${CMAKE_PREFIX_PATH}/include" ${MPI_INCLUDE_PATH}
#
如
果
默
认
路
径
没
找
到
mpi.h
,
还
会
去
MPI_INCLUDE_PATH
找
,下
游
使
⽤
者
可
以
设
置
这
个
变
量
值
)
于
是
在
早
期
CM
ake
时
代
,
依
赖
的
开
发
者
在
c
m
ake
脚
本
⾥
通过
全
局
变
量
来
声
明
这
两个东
⻄
。
⽐
如
名
为
A
bc
的
库
,
其
开
发
者
在
他
的
c
m
ake
脚
本
⾥
会
创
建
Abc_INCLUDE_DIRS
和
Abc_LIBRARIES
两个
变
量
供
下
游
使
⽤
者
使
⽤
。
这
种
命
令
尽
管
不
是
官
⽅
强
制
要
求
的
,
但
⼤
家
都遵
守
了
这
个
习
惯
,
到
了今
天
,
很
多
库
为了
兼
容
旧
CM
ake
的
使
⽤
⽅
式
,
仍
然
提
供
这
样
的
全
局
变
量
。
在
现
代
CM
ake
中
,
c
m
ake
脚
本
提
供
⼀个
t
a
r
ge
t
显
然
会
更
好
,
因
为
t
a
r
ge
t
具
备
属
性
,
我
们
不
光
是
要
找
到
库
,
还
需
要
了
解
库
的
使
⽤
⽅
式
,
使
⽤
t
a
r
ge
t
除
了
头
⽂
件
⽬
录
和
链
接
库
路
径
,
我
们
还
可
以
拿
到
更
多
关
于
库
的
信
息
。
因
此
现
代
CM
ake
提
供了
⼀
种
特
别
的
t
a
r
ge
t
,
I
mport
ed
T
a
r
ge
t
,
创
建
命
令为
add_library(Abc STATIC
IMPORTRED)
,
⽤
于
表
示
在
项
⽬
外
部
已
经
存
在
、
⽆
需
编
译
的
依
赖
,
命
令
的
第
⼆
个
参
数
⽤
于
说
明
类
型
,
⽐
如
是
静
态库
或
动
态库
等
。
对
于
I
mport
ed
T
a
r
ge
t
的
名
字
,
似乎
开
发
者
们
都
喜
欢
使
⽤
n
a
m
e
sp
ace
的
⽅
式
,
⽐
如
Boost::Format
、
Boost::Asio
等
。
同
样
的
,
对
于
⼀个
CM
ake
脚
本
,
可
以
有
多
个
I
mport
ed
T
a
r
ge
t
。
我
们
可
以
像
对
待
普
通
t
a
r
ge
t
⼀
样
,
对
I
mport
ed
T
a
r
ge
t
调
⽤
target_link_libraries
等
命
令
来
说
明
他
的
us
age
r
e
qu
i
r
e
m
e
nt
。
但
其
实
还
有
另
⼀
种
配
置
⽅
式
,上
⽂提
到
过
可
以
通过
PRIVATE
,
INTERFACE
,
PUBLIC
⽤
于修
饰
t
a
r
ge
t
属
性
,
这
实
际
上
可
看
作
是
⼀
种
语
法
糖
。
在
CM
ake
中
,
t
a
r
ge
t
的
⼤多
属
性
都
有
对
应
的
pr
i
v
a
t
e
以
及
i
nt
e
r
face
两个
版
本
的
变
量
。
⽐
如
通过
target_include_directories
命
令
配
置
头
⽂
件
⽬
录
时
,
当
使
⽤
PRIVATE
修
饰
时
,
值
被
写⼊
t
a
r
ge
t
的
INCLUDE_DIRECTORIES
变
量
;
使
⽤
INTERFACE
修
饰
时
,
值
写⼊
INTERFACE_INCLUDE_DIRECTORIES
变
量
;
⽽
使
⽤
PUBLIC
时
,
则
会
写⼊
两个
变
量
。
在
CM
ake
中
,
我
们
可
以
不
使
⽤
t
a
r
ge
t
命
令
,
⽽
是
直
接
使
⽤
set_target_properties
修
改
这
些
值
的
变
量
。
对
于
I
mport
ed
T
a
r
ge
t
,
当库
已
经
事
先
编
译
好
时
,
我
们
需
要
通过
⼀个
特
殊
的
变
量
,
IMPORTED_LOCATION
,
来
指
明
动
态
链
接
库
的
具
体位
置
。
这
个
变
量
就
可
以
通过
set_target_properties
进
⾏设
置
,
在
实
际
⽣
产
环
境
下,
由
于
存
在
R
elea
s
e
以
及
D
eb
u
g
环
境
的
区
别
,
IMPORTED_LOCATION
实
际
上
也
存
在
多
个
版
本
,
⽐
如
IMPORTED_LOCATION_RELEASE
以
及
IMPORTED_LOCATION_DEBUG
,
都进
⾏设
置
后
,
在
对
应
的
环
境
下,
CM
ake
会
根
据
这
些
变
量
为
下
游
使
⽤
者
选
择
正
确的
链
接
库
。
# spdlog
库
的
Imported Target
set_target_properties(spdlog::spdlog PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/spdlog/spdlog.lib"
)
使
⽤
I
mport
ed
T
a
r
ge
t
的
另
⼀个
好处
是
,
我
们
在
引
⼊
⼀个
依
赖
时
只
需
要
li
n
k
其
I
mport
ed
T
a
r
ge
t
,不
再
需
要
⼿
动加⼊
其
头
⽂
件
⽬
录
了
。
因
为依
赖
的
头
⽂
件
⽬
录
已
经
在
其
t
a
r
ge
t
的
INTERFACE
属
性
⾥
了
,
⽽
INTERFACE
属
性
是
可
传
递
的
,
于
是
:
find_package(spdlog REQUIRED)
add_executable(MyEXE)
target_source(MyExe "main.cpp")
target_link_libraries(MyExe SPDLog::spdlog)
⽆
需
target_include_directories
,
sp
dl
o
g
的
头
⽂
件
⽬
录
⾃
动
会
加
进
来
。
fi
n
d
_
p
ackage
的
处
理
回
到
find_package
这
个
命
令
,
这
个
命
令
可
以
指
定
很
多
参
数
,
⽐
如
指
定
版
本
,
指
定
具
体
的
模
块
等等
。
以
S
FML
多媒
体
库
为例
,
其包
含
了
n
e
twor
k
模
块
,
a
u
di
o
模
块
,
g
r
a
p
hic
模
块
等等
,
但
我
很
多
时
候
只
⽤
到
g
r
a
p
hic
模
块
,
那
么
其
他
的
模
块
对
应
的
链
接
库
不
需
要被
链
接
,
于
是
CM
ake
脚
本
可
以
这
么
写
#
要
求
⼤
版
本
号
为
2
的
SFML
库
的
graphic
模
块
find_package(SFML 2 COMPONENTS graphics REQUIRED)
# SFML
提
供
的
target
名
字
为
sfml-graphics
target_link_libraries(MyEXE PRIVATE sfml-graphics)
对
于
find_package
命
令
,
这
些
版
本
、
模
块
等
参
数
在
C
on
fig
file
或
是
F
i
n
d
file
中
显
然
是
需
要
处
理
的
,
在
版
本
不
匹
配
,
模
块
不
存
在
的
情
况
下
应
该
对
下
游
使
⽤
者
进
⾏
提
示
。
这
⼀
⽅
⾯
CM
ake
官
⽅
也为依
赖
开
发
者
做
了
考
虑
,
提
供了
FindPackageHandleStandardArgs
这
个
模
块
,
在
CM
ake
脚
本
中
i
n
cl
u
de
此模
块
后
,
就
可
以使
⽤
find_package_handle_standard_args
命
令
,
来
告
知
CM
ake
如
何
获
取
当
前
p
ackage
的
版
本
变
量
,
如
何
知
道
是
否
找
到
了
库
,
⽐
如
下
⾯
针
对
R
a
p
id
J
S
ON
的
c
m
ake
脚
本
:
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(RapidJSON
REQUIRED_VARS RapidJSON_INCLUDE_DIR
VERSION_VAR RapidJSON_VERSION
)
这
段
脚
本
声
明
了
当
前
库
的
版
本
值
应
该
从
RapidJSON_VERSION
这
个
变
量
拿
,
⽽
RapidJSON_INCLUDE_DIR
这
个
变
量
可
以
⽤
于
表
明有
没
有
找
到
库
。
在
执
⾏
这
段
脚
本时
,
CM
ake
先
去
判
断
RapidJSON_INCLUDE_DIR
这
个
变
量
是
否
为
空
,
如
果
为
空
说
明
没
找
到
库
,
CM
ake
会
直
接
对
下
游
使
⽤
者
报
错
提
示
;
如
果
此
变
量
不
为
空
,
并
且下
游
使
⽤
者
在
调
⽤
find_package
时
传
⼊
了
版
本
号
,
CM
ake
则
会从
RapidJSON_VERSION
变
量
中
取
值
进
⾏
对
⽐
,
如
果
版
本
不
满
⾜
也
报
错
提
示
。
使
⽤
CM
ake
来
编
译
CM
ake
⽣
成
好
编
译
环
境
后
,
底
层
的
m
ake
,
n
i
n
ja
,
M
S
B
u
ild
编
译
命
令
都
是
不⼀
样
的
,
但
CM
ake
提
供了
⼀个
统
⼀
的
⽅
法
进
⾏
编
译
:
cmake --build .
使
⽤
--build
flag
,
CM
ake
就
会
调
⽤
底
层
的
编
译
命
令
,
在
跨
平
台
时
⼗
分
⽅
便
。
对
于
V
i
su
al
S
tu
di
o
,
其
D
eb
u
g
和
R
elea
s
e
环
境
是
基
于
c
on
fig
ur
a
t
i
on
的
,
因
此
CMAKE_BUILD_TYPE
变
量
⽆效
,
需
要
在
b
u
ild
时
指
定
:
cmake --build . --config Release
CM
ake
的
缺
陷
CM
ake
的
缺
陷
是
很
明显
的
,
⼊
⻔
成
本
很
⾼
,
其
语
法
的
设计
也
很
糟糕
,
find_package
这
些
函
数
不
会
返
回
结
果
,
⽽
是
对
全
局
变
量
或
是
t
a
r
ge
t
产
⽣
副
作
⽤
,
函
数
的
⾏
为
不
查
阅
⽂
档是
很
难预
测
的
。
并
且
在
CM
ake
中
,
变
量
,
t
a
r
ge
t
,
字
符
串
的
区
分
不
明
确
,
很
容
易
让
⼈
感
到
迷
惑
,不
知
道
什么
时
候
应
该
使
⽤
${}
去
读
取
值
。
此
外
,
官
⽅
⽹
站
上
的
教
程
也
⼗
分
落
后
,
尽
管
可
⽤
,
但
并
没
有
使
⽤现
代
CM
ake
⽅
式
创
建
⼯
程
。
推
荐
看
本
⽂
最
后
给
的
资
料
⽽
不
是
官
⽹
上
的
T
utor
ial
。
之
后
有
空
了
再
介
绍
C
on
fig
file
的
具
体
创
建
⽅
式
、
库
的
i
nst
all
还
有
基
于
c
t
e
st
的
测
试
,不
过
希
望
在
我
更
新
之
前
就
能
有更
好
的
替
代
⼯
具
诞
⽣
吧
。
参
考
资
料
c
m
ake
-
b
u
ild
syst
e
m
c
m
ake
-
p
ackage
s
I
t
'
s
T
i
m
e
T
o
D
o
CM
ake
R
igh
t
载
⼊
评论
中
....