使用find_package查找库时,如何确定用于链接的变量?
find_package变量查找与docopt链接失败问题 我来帮你搞定这个问题——首先得搞清楚find_package到底导出了哪些可用变量,然后再解决你遇到的docopt链接空变量的问题。
一、怎么找到find_package定义的变量?
有三个实用方法,能快速定位到库导出的所有CMake变量:
用
--debug-find看详细查找日志
运行CMake的时候加上这个参数,会输出整个查找过程的细节,包括所有定义的变量:cmake .. --debug-find你只需要在输出里搜
docopt相关的内容,就能找到它导出的所有变量名,比如有没有DOCOPT_LIBRARY或者DOCOPT_TARGET之类的。查看CMake模块文件的注释
每个find_package对应的FindXXX.cmake模块(比如Finddocopt.cmake)里,一般都会注释说明它定义了哪些变量。你可以去CMake的模块目录找这个文件——通常在/usr/share/cmake-<你的版本>/Modules,或者你本地安装的docopt自带的CMake配置目录里,打开就能看到变量说明。用
cmake -L查看缓存变量
当CMake配置完项目后,在build目录下运行:cmake -L ..这个命令会列出所有缓存里的变量,你直接找前缀为
DOCOPT_的条目,就能知道哪些变量是可用的。
二、你的docopt链接失败的解决方案
你遇到${DOCOPT_LIBRARIES}为空的情况,大概率是因为docopt的CMake模块根本没定义这个变量——现在很多现代库都用导入目标代替传统的变量了。
方法1:用导入目标直接链接(推荐)
docopt通常会导出一个名为docopt::docopt的导入目标,你直接用这个目标链接就行,连包含目录都不用手动加:
cmake_minimum_required(VERSION 3.1) project(test) find_package(docopt REQUIRED) # 替换成你的源文件 add_executable(test main.cpp) # 直接链接导入目标,自动处理包含目录和链接依赖 target_link_libraries(test PRIVATE docopt::docopt)
方法2:找对正确的变量名(旧版本兼容)
如果你的docopt版本比较老,确实用变量的话,可能变量名是单数的DOCOPT_LIBRARY,而不是复数的DOCOPT_LIBRARIES。你可以试试替换成这个变量:
set(PROJECT_LIBS ${PROJECT_LIBS} ${DOCOPT_LIBRARY})
另外,现代CMake不推荐用include_directories(),如果用导入目标的话,头文件目录会自动关联到你的目标上,完全不用手动处理。
三、CMake链接库的最佳实践
- 优先用导入目标(格式一般是
XXX::XXX),这种方式会自动处理包含目录、编译选项、依赖链,比手动管理变量靠谱多了。 - 如果你必须用变量,一定要通过上面的方法确认变量的正确名称,别凭经验瞎猜。
- 尽量升级CMake到3.14以上的版本,对现代库的CMake配置支持更好。
内容的提问来源于stack exchange,提问作者Tom de Geus

