假设我需要使用第三方库去做一些事情,如何在配置中体现这种依赖关系?
ind_package旨在使用预先设置的配置文件来查找依赖项,
find_package(PACKAGE_NAME_CASE_SENSITIVE
[version] [EXACT] [QUIET]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_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_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
[NO_CMAKE_PACKAGE_REGISTRY]
[NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
[NO_CMAKE_SYSTEM_PATH]
[NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
[CMAKE_FIND_ROOT_PATH_BOTH |
ONLY_CMAKE_FIND_ROOT_PATH |
NO_CMAKE_FIND_ROOT_PATH)
主要用的参数如下:
PACKAGE_NAME_CASE_SENSITIVE
version
EXACT
QUIET
CONFIG
<PACKAGE_NAME>_DIR
你可以在 find_package 之前直接设置这个宏至依赖包路径下来告诉cmake需要查找的路径。对于一些特殊的场景有奇效。
CMAKE_PREFIX_PATH
cmake统一使用该list中的路径来查找所有依赖项。所以如果你把依赖项都放在一起,请将他们所在的根目录 APPEND 或 REPEND 到此list中。
CMAKE_FRAMEWORK_PATH
此路径为MacOS专用,存放系统 framework 的依赖项位置。
CMAKE_APPBUNDLE_PATH
此路径为MacOS专用,存放 app bundle的位置。
<EACH_PATH>/ 根目录
<EACH_PATH>/cmake
<EACH_PATH>/<PACKAGE_NAME>
<EACH_PATH>/<PACKAGE_NAME>/cmake
<EACH_PATH>/<lib/share>/cmake
<EACH_PATH>/<lib/share>/<PACKAGE_NAME>
<EACH_PATH>/<lib/share>/<PACKAGE_NAME>/cmake
<EACH_PATH>/<PACKAGE_NAME>/<lib/share>/<PACKAGE_NAME>
<EACH_PATH>/<PACKAGE_NAME>/<lib/share>/<PACKAGE_NAME>/cmake
其实通用做法很简单:将你需要提供的配置文件扔到 root/share/<PACKAGE_NAME> 或 root/lib/cmake/<PACKAGE_NAME> 中就行了。
使用该模式时,一般情况下会提供依赖项对应的 target 名称(包含或不包含namespace)以供使用。
极少数情况下也提供依赖项对应的各种宏,这主要是为了兼容预先cmake提供的MODULE模式文件使用方式(设置CMAKE_FIND_PACKAGE_PREFER_CONFIG 而无需修改任何 find_package 代码即可优先使用 CONFIG 模式)。
当未使用 REQUIRED 关键字时,我们可以使用 <PACKAGE_NAME>_FOUND 来判断是否找打了合适的依赖项。
该关键字不可与下一关键字MODULE同时声明。
MODULE
<PACKAGE_NAME>_INCLUDE_DIRS / <PACKAGE_NAME>_INCLUDE_DIR 头文件路径
<PACKAGE_NAME>_LIBRARIES / <PACKAGE_NAME>_LIBRARY 库名称(包含路径和配置表达式)
<PACKAGE_NAME>_VERSION / <PACKAGE_NAME>_VERSION_STRING 完整版本号
<PACKAGE_NAME>_FOUND 是否查找到该依赖
NAMES
PATHS
PATH_SUFFIXES
NO_DEFAULT_PATH
NO_SYSTEM_PATH
这是原始的cmake查找依赖方式:直接查找依赖项库文件,一般与下面的一项同时使用。
find_library (
<LIBRARY_NAME>
name | NAMES name1 [name2 ...] [NAMES_PER_DIR]
[HINTS [path | ENV var]... ]
[PATHS [path | ENV var]... ]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
[NO_CACHE]
[REQUIRED]
[NO_DEFAULT_PATH]
[NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
[NO_CMAKE_SYSTEM_PATH]
[CMAKE_FIND_ROOT_PATH_BOTH |
ONLY_CMAKE_FIND_ROOT_PATH |
NO_CMAKE_FIND_ROOT_PATH]
)
这与上面的 find_package 略有不同,
不同之处:
查找完成后:
所以这里和 find_package 又有不同,我们应当使用以下代码判断是否查找到:
if (PACKAGE_NAME MATCHES "-NOTFOUND")
message(FATAL_ERROR "${PACKAGE_NAME} not found!")
endif()
这个函数一般是查找头文件或其他的 非库文件 且 非可执行程序。
find_path (
<FILE_NAME>
name | NAMES name1 [name2 ...]
[HINTS [path | ENV var]... ]
[PATHS [path | ENV var]... ]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
[NO_CACHE]
[REQUIRED]
[NO_DEFAULT_PATH]
[NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
[NO_CMAKE_SYSTEM_PATH]
[CMAKE_FIND_ROOT_PATH_BOTH |
ONLY_CMAKE_FIND_ROOT_PATH |
NO_CMAKE_FIND_ROOT_PATH]
)
一般情况下,由于需要cmake表达式来让cmake判断使用哪个配置的库,我们通常这么写:
find_path(<PACKAGE_NAME>_INCLUDE_DIR NAMES header.h PATH_SUFFIXES include/...)
find_library(<PACKAGE_NAME>_LIBRARY_RELEASE NAMES name1 name2)
find_library(<PACKAGE_NAME>_LIBRARY_DEBUG NAMES name1d name2d)
select_library_configurations(<PACKAGE_NAME>)
...
target_*(target_name ${<PACKAGE_NAME>})
这个函数专门用于查找可执行程序。
find_program (
<VAR>
name | NAMES name1 [name2 ...] [NAMES_PER_DIR]
[HINTS [path | ENV var]... ]
[PATHS [path | ENV var]... ]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
[NO_CACHE]
[REQUIRED]
[NO_DEFAULT_PATH]
[NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
[NO_CMAKE_SYSTEM_PATH]
[CMAKE_FIND_ROOT_PATH_BOTH |
ONLY_CMAKE_FIND_ROOT_PATH |
NO_CMAKE_FIND_ROOT_PATH]
)
我们可以将查找到的依赖项用于多个函数中,例如添加头文件路径,添加链接库,添加编译选项等。
对于不同的查找方式,配置文件或cmake提供了不同的使用方式:
宏
$<$<CONFIG:DEBUG>:library.lib> $<${NOT:$<CONFIG:DEBUG>>:libraryd.lib>
target
内部依赖
add_dependencies
add_dependencies(<target> [<target-dependency>]...)
这个很简单,向前者添加依赖项(后者),可以添加多个。在编译或某些配置时,优先处理后者。