以下为个人学习笔记整理。B 站课程传送门
# CMake
CMake 是用来统一编译代码,相当于是执行编译的自动化脚本。定义 CMakeLists.txt 以后,就不需要对项目代码进行逐个的编译。
# 编译一个简单代码
main.cpp
#include <iostream> | |
int main(){ | |
std::cout << "hello world" << std::endl; | |
return 0; | |
} |
CMakeLists.txt
project(CMakeTest) | |
set(SRC_LIST main.cpp) | |
message(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR}) | |
message(STATUS "This is SOURCE dir " ${HELLO_SOURCE_DIR}) | |
add_executable(hello ${SRC_LIST}) |
在命令行执行 cmake .
表示运行当前目录下的 CMakeLists.txt
output
-- The C compiler identification is GNU 7.3.1 | |
-- The CXX compiler identification is GNU 7.3.1 | |
-- Check for working C compiler: /usr/lib64/ccache/cc | |
-- Check for working C compiler: /usr/lib64/ccache/cc - works | |
-- Detecting C compiler ABI info | |
-- Detecting C compiler ABI info - done | |
-- Detecting C compile features | |
-- Detecting C compile features - done | |
-- Check for working CXX compiler: /usr/lib64/ccache/c++ | |
-- Check for working CXX compiler: /usr/lib64/ccache/c++ - works | |
-- Detecting CXX compiler ABI info | |
-- Detecting CXX compiler ABI info - done | |
-- Detecting CXX compile features | |
-- Detecting CXX compile features - done | |
-- This is BINARY dir /data/rwbyguo/cmake_test | |
-- This is SOURCE dir /data/rwbyguo/cmake_test | |
-- Configuring done | |
-- Generating done | |
-- Build files have been written to: /data/rwbyguo/cmake_test |
会发现多出来了几个文件
. | |
├── CMakeCache.txt | |
├── CMakeFiles | |
│ ├── 3.17.2 | |
│ │ ├── CMakeCCompiler.cmake | |
│ │ ├── CMakeCXXCompiler.cmake | |
│ │ ├── CMakeDetermineCompilerABI_C.bin | |
│ │ ├── CMakeDetermineCompilerABI_CXX.bin | |
│ │ ├── CMakeSystem.cmake | |
│ │ ├── CompilerIdC | |
│ │ │ ├── a.out | |
│ │ │ ├── CMakeCCompilerId.c | |
│ │ │ └── tmp | |
│ │ └── CompilerIdCXX | |
│ │ ├── a.out | |
│ │ ├── CMakeCXXCompilerId.cpp | |
│ │ └── tmp | |
│ ├── cmake.check_cache | |
│ ├── CMakeDirectoryInformation.cmake | |
│ ├── CMakeOutput.log | |
│ ├── CMakeTmp | |
│ ├── hello.dir | |
│ │ ├── build.make | |
│ │ ├── cmake_clean.cmake | |
│ │ ├── CXX.includecache | |
│ │ ├── DependInfo.cmake | |
│ │ ├── depend.internal | |
│ │ ├── depend.make | |
│ │ ├── flags.make | |
│ │ ├── link.txt | |
│ │ ├── main.cpp.o | |
│ │ └── progress.make | |
│ ├── Makefile2 | |
│ ├── Makefile.cmake | |
│ ├── progress.marks | |
│ └── TargetDirectories.txt | |
├── cmake_install.cmake | |
├── CMakeLists.txt // | |
├── main.cpp // | |
└── Makefile |
在执行 make 操作,来编译生成的 Makefile
output
[rwbyguo@VM-218-157-centos cmake_test]$make | |
Scanning dependencies of target hello | |
[ 50%] Building CXX object CMakeFiles/hello.dir/main.cpp.o | |
[100%] Linking CXX executable hello | |
[100%] Built target hello |
会得到一个编译后的可执行文件 hello
. | |
| ... | |
├── hello // new | |
├── main.cpp | |
└── Makefile | |
[rwbyguo@VM-218-157-centos cmake_test]$./hello | |
hello world |
# 语法介绍
# project 关键字
指定工程名和支持语言,默认情况下支持所有语言 project(${project_name} [language])
project(CMakeTest) # 支持所有语言 | |
project(CMakeTest CXX) # 支持 c++ | |
project(CMakeTest C CXX) # 支持 c++ 和 c |
该指令会隐式创建两个变量 ${project_name}_BINARY_DIR
、 ${project_name}_SOURCE_DIR
另外还有两个预定义变量值和它们一致 PROJECT_BINARY_DIR
、 PROJECT_SOURCE_DIR
# set 关键字
声明变量,并且支持多个
set(SRC_LIST main.cpp m1.cpp m2.cpp) |
# message 关键字
向终端输出用户自定义的信息,类似 print。包含多种类型的信息,具体说明参考官方文档:
- SEND_ERROR:产生错误,会继续运行 CMakeLists.txt 内的指令,但是不会构建
- STATUS:输出前缀带有「— —」的信息
- FAIL_ERROR:终止运行 CMakeLists.txt 内的指令,且停止构建
- WARNING:警告,但是会继续运行和构建
# add_executable 关键字
用来生成可执行文件,包含两个参数,一个是可执行文件名,一个是源文件: add_executable(${executable_name} ${source_list})
add_executable(hello main.cpp m1.cpp m2.cpp) |
# 语法的基本原则
- 变量值的获取需要使用
${}
,如果在 IF 语句内使用变量则可直接用变量名。 - 指令内的参数都是用
()
包裹,参数之间可以用;
或者 空格 分隔。 - 关键字不区分大小写,但是参数和变量区分大小写。
# 注意事项
- set 指令如果参数里面带有空格的话,需要用双引号括起来
"arg 1"
- add_executable 指令内的源文件可以不加
.cpp
后缀,但是建议还是加上
# 内部构建和外部构建
- 上面例子就是内部构建,会获得很多临时文件
- 外部构建可以指定生成文件都放在单独的目录下,推荐使用外部构建
外部构建介绍:
在目录下创建一个单独的目录 debugbuild
,然后在 debugbuild
执行 cmake ..
即可
[rwbyguo@VM-218-157-centos cmake_test]$cd debugbuild/ | |
[rwbyguo@VM-218-157-centos debugbuild]$cmake .. | |
-- The C compiler identification is GNU 7.3.1 | |
-- The CXX compiler identification is GNU 7.3.1 | |
-- Check for working C compiler: /usr/lib64/ccache/cc | |
-- Check for working C compiler: /usr/lib64/ccache/cc - works | |
-- Detecting C compiler ABI info | |
-- Detecting C compiler ABI info - done | |
-- Detecting C compile features | |
-- Detecting C compile features - done | |
-- Check for working CXX compiler: /usr/lib64/ccache/c++ | |
-- Check for working CXX compiler: /usr/lib64/ccache/c++ - works | |
-- Detecting CXX compiler ABI info | |
-- Detecting CXX compiler ABI info - done | |
-- Detecting CXX compile features | |
-- Detecting CXX compile features - done | |
-- This is BINARY dir /data/rwbyguo/cmake_test/debugbuild | |
-- This is SOURCE dir /data/rwbyguo/cmake_test | |
-- Configuring done | |
-- Generating done | |
-- Build files have been written to: /data/rwbyguo/cmake_test/debugbuild |
这时候它的 BINARY
和 SOURCE
路径就不一样了。
# 编译一个工程
# 工程目录结构
常规的 C++ 工程目录如下,需要编译哪个目录就在哪个目录下面创建一个 CMakeLists.txt:
. | |
├── CMakeLists.txt | |
├── debugbuild //cmake 生成的文件路径 | |
├── external // 存放项目引用的第三方库 | |
│ └── CMakeLists.txt | |
├── resource // 存放项目资源文件 | |
├── run | |
│ └── bin // 存放项目可执行的 bin 文件 | |
└── src // 存放项目代码 | |
├── CMakeLists.txt | |
└── main.cpp |
# 进阶语法
# file 关键字
文件操作命令,用法:
file(WRITE filename "message to write"... ) # 将消息写入 filename | |
file(APPEND filename "message to write"... ) # 将消息追加写入 filename | |
file(READ filename variable [LIMIT numBytes] [OFFSET offset] [HEX]) # 从 filename 读取消息到 variable | |
file(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> filename variable) # 计算 filename 的加密哈希到 variable | |
file(STRINGS filename variable [LIMIT_COUNT num] # 将解析 filename 中的 ASCII 字符串列表并将其存储在 variable 中。二进制数据 和 回车会被忽略 | |
[LIMIT_INPUT numBytes] [LIMIT_OUTPUT numBytes] | |
[LENGTH_MINIMUM numBytes] [LENGTH_MAXIMUM numBytes] | |
[NEWLINE_CONSUME] [REGEX regex] | |
[NO_HEX_CONVERSION]) | |
file(GLOB variable [RELATIVE path] [globbing expressions]...) # 生成 variable 用来存储 RELATIVE path 下所有满足 globbing expressions 的文件 | |
file(GLOB_RECURSE variable [RELATIVE path] # 和 GLOB 类似,但不仅仅匹配文件,还匹配目录 | |
[FOLLOW_SYMLINKS] [globbing expressions]...) | |
file(RENAME <oldname> <newname>) # 移动文件或目录,操作是原子性的 | |
file(REMOVE [file1 ...]) # 删除文件,包括子目录 | |
file(REMOVE_RECURSE [file1 ...]) # 删除目录或文件,包括子目录 | |
file(MAKE_DIRECTORY [directory1 directory2 ...]) # 创建目录,支持不存在父目录的创建 | |
file(RELATIVE_PATH variable directory file) # 获取 directory 和 file 的相对路径关系并保存在 variable。 | |
file(TO_CMAKE_PATH path result) # 将路径转为 unix 的 cmake 样式 | |
file(TO_NATIVE_PATH path result) # 将路径转为 windows 的 cmake 样式 | |
file(DOWNLOAD url file [INACTIVITY_TIMEOUT timeout] # 将 url 内容下载到 file | |
[TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS] | |
[EXPECTED_HASH ALGO=value] [EXPECTED_MD5 sum] | |
[TLS_VERIFY on|off] [TLS_CAINFO file]) | |
file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout] # 将 filename 内容上传到 url | |
[TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS]) | |
file(TIMESTAMP filename variable [<format string>] [UTC]) # 获取 filename 修改的时间字符串到 variable | |
file(GENERATE OUTPUT output_file # 将 input_file | input_content 内容写入 output_file | |
<INPUT input_file|CONTENT input_content> | |
[CONDITION expression]) |
# 常见用法:
file(GLOB_RECURSE my_src *.cpp *.h) # 获取当前路径下的所有 .cpp 和 .h | |
add_executable(my_executable ${my_src}) # 编译出可执行文件 |
# macro/endmacro 关键字
定义宏,用来给其他 CMakeLists.txt 使用。
macro(<name> [arg1 [arg2 [arg3 ...]]]) | |
# dosomthing ... | |
endmacro(<name>) |
# include 关键字
引用 .cmake 文件,使用其中定义的变量或者其他函数
include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>] | |
[NO_POLICY_SCOPE]) |
# 配合 macro 使用:
# xxx.cmake | |
macro(myfunc msg) | |
message(STATUS ${msg}) | |
endmacro(myfunc msg) | |
# CMakeLists.txt | |
include(xxx.cmake) | |
myfunc("this is msg") |
# if/endif 关键字
条件语句:
if(expression) | |
# dosomthing ... | |
elseif (expression) | |
# dosomthing ... | |
endif() |
# foreach/endforeach 关键字
循环语句,语法和 python 比较类似:
foreach(loop_var arg1 arg2 ...) # foreach(var IN list_xxx) | foreach(var RANGE start stop [step]) | |
# dosomthing ... | |
endforeach() |
# configure_file 关键字
将一个文件复制到另一个位置,并对文件内容进行修改
configure_file(<input> <output> | |
[COPYONLY] [ESCAPE_QUOTES] [@ONLY] | |
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ]) | |
# example | |
configure_file(file1 /src/file1) |
# math 关键字
进行数学运算的函数
math(EXPR <output variable> <math expression>) | |
# example | |
math(EXPR var "8 * 8") |
# string 关键字
string(REGEX MATCH <regular_expression> # 正则匹配字符串,返回首个匹配项 | |
<output variable> <input> [<input>...]) | |
string(REGEX MATCHALL <regular_expression> # 正则匹配字符串,尽可能多的匹配 | |
<output variable> <input> [<input>...]) | |
string(REGEX REPLACE <regular_expression> # 正则匹配字符串,尽可能多的匹配,匹配成功后进行替换 | |
<replace_expression> <output variable> | |
<input> [<input>...]) | |
string(REPLACE <match_string> # 非正则模式下尽可能多的字符串匹配和替换 | |
<replace_string> <output variable> | |
<input> [<input>...]) | |
string(CONCAT <output variable> [<input>...]) # 字符串拼接类似 "".join | |
string(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> # 计算字符串的加密哈希 | |
<output variable> <input>) | |
# 字符串比较 | |
string(COMPARE EQUAL <string1> <string2> <output variable>) | |
string(COMPARE NOTEQUAL <string1> <string2> <output variable>) | |
string(COMPARE LESS <string1> <string2> <output variable>) | |
string(COMPARE GREATER <string1> <string2> <output variable>) | |
string(ASCII <number> [<number> ...] <output variable>) # 将字符串中的数字转为 ASCII 编码 | |
# 字符串转换 | |
string(CONFIGURE <string1> <output variable> | |
[@ONLY] [ESCAPE_QUOTES]) | |
string(TOUPPER <string1> <output variable>) | |
string(TOLOWER <string1> <output variable>) | |
string(LENGTH <string> <output variable>) # 获取长度 | |
string(SUBSTRING <string> <begin> <length> <output variable>) # 字符串切片 | |
string(STRIP <string> <output variable>) # 字符去空格和 tab | |
string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>] # 生成固定长度随机字符串 | |
[RANDOM_SEED <seed>] <output variable>) | |
string(FIND <string> <substring> <output variable> [REVERSE]) # 查找给定字串的下标 | |
string(TIMESTAMP <output variable> [<format string>] [UTC]) # 输出当前时间字符串 | |
string(MAKE_C_IDENTIFIER <input string> <output variable>) # will write a string which can be used as an identifier in C. |
# option 关键字
相当于创建一个 bool 类型的变量
option(<option_variable> "help string describing option" | |
[initial value]) | |
# example | |
option(NEED_CHECK_CONFIG "是否需要检查配置" ON) | |
if (NEED_CHECK_CONFIG) | |
# dosomething ... | |
endif () |
# add_definitions 关键字
搭配 option 使用,可以指定某个 option 不生效
add_definitions(-DFOO -DBAR ...) | |
# example | |
add_definitions("-DNEED_CHECK_CONFIG") # NEED_CHECK_CONFIG on -> off |
# list 关键字
比较简单,就是 list 容器和各项操作
list(LENGTH <list> <output variable>) | |
list(GET <list> <element index> [<element index> ...] | |
<output variable>) | |
list(APPEND <list> [<element> ...]) | |
list(FIND <list> <value> <output variable>) | |
list(INSERT <list> <element_index> <element> [<element> ...]) | |
list(REMOVE_ITEM <list> <value> [<value> ...]) | |
list(REMOVE_AT <list> <index> [<index> ...]) | |
list(REMOVE_DUPLICATES <list>) | |
list(REVERSE <list>) | |
list(SORT <list>) |
# install 关键字
指定执行 cmake install
时运行的安装规则。官方文档
其中,一个内置变量经常被使用: CMAKE_INSTALL_PREFIX=/usr/local
# 常见安装模板
安装非目标程序(shell 脚本)
install(<FILES|PROGRAMS> files... DESTINATION <dir> | |
[PERMISSIONS permissions...] | |
[CONFIGURATIONS [Debug|Release|...]] | |
[COMPONENT <component>] | |
[RENAME <name>] [OPTIONAL]) | |
# example FILES | |
# 把 README COPYRIGHT 两个文件安装到 ${CMAKE_INSTALL_PREFIX}/doc 下 | |
install(FILES README COPYRIGHT DESTINATION /doc) | |
# example PROGRAMS | |
# 把 build.sh 安装到 ${CMAKE_INSTALL_PREFIX}/shell 下 | |
install(PROGRAMS build.sh DESTINATION /shell) |
安装一个或多个目录内容:
install(DIRECTORY dirs... DESTINATION <dir> | |
[FILE_PERMISSIONS permissions...] | |
[DIRECTORY_PERMISSIONS permissions...] | |
[USE_SOURCE_PERMISSIONS] [OPTIONAL] | |
[CONFIGURATIONS [Debug|Release|...]] | |
[COMPONENT <component>] [FILES_MATCHING] | |
[[PATTERN <pattern> | REGEX <regex>] | |
[EXCLUDE] [PERMISSIONS permissions...]] [...]) | |
# example DIRECTORY | |
# 把 doc 目录下的内容安装到 ${CMAKE_INSTALL_PREFIX}/doc 下 | |
install(DIRECTORY doc/ DESTINATION /doc) |
安装常用的可选项:
install(TARGETS targets... [EXPORT <export-name>] | |
[RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>] | |
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE| | |
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>] | |
[DESTINATION <dir>] | |
[PERMISSIONS permissions...] | |
[CONFIGURATIONS [Debug|Release|...]] | |
[COMPONENT <component>] | |
[NAMELINK_COMPONENT <component>] | |
[OPTIONAL] [EXCLUDE_FROM_ALL] | |
[NAMELINK_ONLY|NAMELINK_SKIP] | |
] [...] | |
[INCLUDES DESTINATION [<dir> ...]] | |
) | |
# example TARGETS | |
# 把 arenasvr 按照 RUNTIME 模式安装到 ${CMAKE_INSTALL_PREFIX}/as/bin 下 | |
install(TARGETS arenasvr RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/as/bin) |
# TARGETS
${targets} 用来指定需要安装的源文件
# EXPORT
指定安装后的文件名,默认为 $
# Target Type
指定 targets 的类型,如果 DESTINATION 没有设置情况下,不同类型的默认安装路径由 GNUInstallDirs Variable 决定
Target Type | 类型说明 | GNUInstallDirs Variable | Built-In Default |
---|---|---|---|
RUNTIME | 可执行文件 | DLLs | ${CMAKE_INSTALL_BINDIR} | bin |
LIBRARY | 共享库 | ${CMAKE_INSTALL_LIBDIR} | lib |
ARCHIVE | 静态库 | .lib | .dll | ${CMAKE_INSTALL_LIBDIR} | lib |
FILE_SET (type HEADERS ) | 文件集,会保留目录结构进行安装 | ${CMAKE_INSTALL_INCLUDEDIR} | include |
# DESTINATION
指定安装目录,相对路径默认以 CMAKE_INSTALL_PREFIX 为根目录
# PERMISSIONS
指定安装文件的权限
# CONFIGURATIONS
指定安装构建的规则:Debug | Release
# 静态库和动态库的构建
# 两者区别
- 静态库的扩展名一般为 .a 或 .lib;动态库的扩展名一般为 .so 或 .dll
- 静态库在编译是会直接整合到目标程序中,目标程序在编译完成后可独立运行
- 动态链接库在编译时不会放到连接的目标程序中,目标程序在运行过程中动态加载,因此目标程序不可独立运行
# add_library 关键字
添加共享库构建项
add_library(<name> [STATIC | SHARED | MODULE] | |
[EXCLUDE_FROM_ALL] | |
source1 [source2 ...]) | |
# example | |
add_library(lib_func STATIC lib_func.cpp) | |
# 构建时会得到 lib${name}.xx 的库文件,例如这里对 lib_func 的构建结果为 liblib_func.a |
关键字 | 作用 |
---|---|
STATIC | 生成静态库, .a 或 .lib |
SHARED | 生成动态库, .so 或 .dll |
MODULE | 生成动态库,可以在运行过程中通过 dlopen 动态加载, .so 或 .dll |
在根目录下新建一个 lib 文件,并且写个简单的函数:
. | |
├── CMakeLists.txt | |
├── lib | |
│ ├── CMakeLists.txt | |
│ ├── lib.cpp | |
│ └── lib.h | |
└── src | |
├── CMakeLists.txt | |
└── main.cpp |
lib/CMakeLists.txt
add_library(lib_func STATIC lib.cpp) |
src/CMakeLists.txt
add_executable(hello main.cpp) |
CMakeLists.txt
project(ROOT) | |
add_subdirectory(lib bin/lib) | |
add_subdirectory(src bin/src) |
# add_subdirectory 关键字
添加需要编译的子目录,可以指定编译文件的路径
add_subdirectory(source_dir [binary_dir] | |
[EXCLUDE_FROM_ALL]) | |
# example 编译 src 下面的 CMakeLists.txt 并把结果输出到 ${PROJECT_SOURCE_DIR}/bin/src 下 | |
add_subdirectory(src bin/src) |
# include_directories 关键字
添加外部库,可以避免在引用外部库头文件的时候,提示找不到头文件
/data/rwbyguo/cmake_test/src/main.cpp:2:10: 致命错误:lib.h:没有那个文件或目录 | |
#include "lib.h" | |
^~~~~~~ | |
编译中断。 |
用法:
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...]) | |
# example | |
include_directories(${CMAKE_SOURCE_DIR}/lib) | |
add_executable(hello main.cpp) |
# target_link_libraries 关键字
为可执行程序添加链接库,可以避免在使用动态库中函数的时候找不到对应的实现
CMakeFiles/hello.dir/main.o:在函数‘main’中: | |
main.cpp:(.text+0x5):对‘lib_func()’未定义的引用 | |
collect2: 错误:ld 返回 1 | |
make[2]: *** [bin/src/hello] 错误 1 | |
make[1]: *** [bin/src/CMakeFiles/hello.dir/all] 错误 2 | |
make: *** [all] 错误 2 |
添加需要连接的共享库:
target_link_libraries(<target> [item1 [item2 [...]]] | |
[[debug|optimized|general] <item>] ...) | |
# example 记得 target_link_libraries 需要放在 add_executable 后面 | |
include_directories(${CMAKE_SOURCE_DIR}/lib) | |
set(LIB_FUNC_PATH ${CMAKE_SOURCE_DIR}/debugbuild/bin/lib) #/data/rwbyguo/cmake_test/debugbuild/bin/lib | |
add_executable(hello main.cpp) | |
target_link_libraries(hello ${LIB_FUNC_PATH}/liblib_func.a) |
# link_directories 关键字
添加非标准的共享库搜索路径,可以简化链接库时的路径设置,搭配 target_link_libraries
使用
link_directories(directory1 directory2 ...) | |
# example | |
include_directories(${CMAKE_SOURCE_DIR}/lib) | |
set(LIB_FUNC_PATH ${CMAKE_SOURCE_DIR}/debugbuild/bin/lib) #/data/rwbyguo/cmake_test/debugbuild/bin/lib | |
link_directories(${LIB_FUNC_PATH}) | |
add_executable(hello main.cpp) | |
target_link_libraries(hello liblib_func.a) |
# link_libraries 关键字
连接库,可以不需要指定 target,相等于 target_link_libraries 提前版本。
link_libraries(library1 <debug | optimized> library2 ...) | |
# example | |
include_directories(${CMAKE_SOURCE_DIR}/lib) | |
set(LIB_FUNC_PATH ${CMAKE_SOURCE_DIR}/debugbuild/bin/lib) #/data/rwbyguo/cmake_test/debugbuild/bin/lib | |
link_libraries(${LIB_FUNC_PATH}/liblib_func.a) | |
add_executable(hello main.cpp) |
# find_package 关键字
查找并加载外部包,支持两种搜索方式:
- Module mode:CMake 先从
CMAKE_MODULE_PATH
搜索一个名为 的文件Find<PackageName>.cmake
。 - Config mode:CMake 会搜索一个名为
<lowercasePackageName>-config.cmake
|<PackageName>Config.cmake
的文件。查找流程较为复杂,见官方文档
find_package(<package> [version] [EXACT] [QUIET] | |
[REQUIRED] [[COMPONENTS] [components...]] | |
[CONFIG|NO_MODULE] | |
[NO_POLICY_SCOPE] | |
[NAMES name1 [name2 ...]] | |
[CONFIGS config1 [config2 ...]] | |
[HINTS path1 [path2 ... ]] | |
[PATHS path1 [path2 ... ]] | |
[PATH_SUFFIXES suffix1 [suffix2 ...]] | |
[NO_DEFAULT_PATH] | |
[NO_CMAKE_ENVIRONMENT_PATH] | |
[NO_CMAKE_PATH] | |
[NO_SYSTEM_ENVIRONMENT_PATH] | |
[NO_CMAKE_PACKAGE_REGISTRY] | |
[NO_CMAKE_BUILDS_PATH] | |
[NO_CMAKE_SYSTEM_PATH] | |
[NO_CMAKE_SYSTEM_PACKAGE_REGISTRY] | |
[CMAKE_FIND_ROOT_PATH_BOTH | | |
ONLY_CMAKE_FIND_ROOT_PATH | | |
NO_CMAKE_FIND_ROOT_PATH]) | |
# example 官方提供了 protobuf 的配置 https://cmake.org/cmake/help/latest/module/FindProtobuf.html | |
#protobuf | |
set(PROTOBUF_DIR ${CMAKE_SOURCE_DIR}/external/protobuf) | |
set(PROTOBUF_INCLUDE_DIR ${PROTOBUF_DIR}/include) | |
set(PROTOBUF_LIBRARY_DIR ${PROTOBUF_DIR}/lib) | |
set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_DIR}/bin/protoc) | |
if(MSVC) | |
set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_DIR}/bin/protoc.exe) | |
endif(MSVC) | |
set(PROTOBUF_LIBRARY ${PROTOBUF_LIBRARY_DIR}/libprotobuf.a) | |
set(PROTOBUF_LIBRARY_DEBUG ${PROTOBUF_LIBRARY_DIR}/libprotobuf.a) | |
set(PROTOBUF_IMPORT_DIRS) | |
find_package(Protobuf REQUIRED) |
# EXACT
要求 version 版本匹配
# QUIRT
如果引入外部包失败,不提示消息
# REQUIRED
如果引入外部包失败,停止编译流程,并提示错误消息
# 参考链接
- cmake 官方文档