发布网友 发布时间:2023-08-31 16:27
共1个回答
热心网友 时间:2024-12-14 14:37
created in 2019-03-03 11:44:11
updated in 2019-3-28 14:31:21
前面两篇从cmake源码中命令行入口参数、Caffe源码顶层CMakeLists.txt进行了解读,整体有了一个印象。在此基础上,考虑实际中最常遇到的问题:基于CMake构建Caffe,如何确保每一个依赖被正确找到?尽管用了CMake用了 find_package() ,也看到了Caffe官方的CI构建脚本 scripts/install-deps.sh ,但是自己机器不是docker环境、如何切换多个版本的依赖包?
find_package() 命令是用来查找依赖包的,理想情况下,一句 find_package() 把一整个依赖包的头文件包含路径、库路径、库名字、版本号等情况都获取到,后续只管用就好了。但实际中往往CMake失败就是出在 find_package() 的失败上(这里不考虑后续make/nmake/msbuild以及编译器、链接器直接执行时的编译、链接出错,只讨论cmake根据CMakeLists.txt执行时候的情况),例如:
上面列出的opencv和protobuf是重灾区,还有没有列出来的比如boost版本问题等。解决起来也不难:
根据cmake官方文档可以知道, find_package() 有Mole模式(基本用法,basic signature)和Config模式(full signature,完全用法),其中Mole模式是基础,Config模式则更复杂高级些。
Mole模式也就是基础用法(Basic Signature,这里Signature表示“用法”,而不是“签名”),Config模式也就是高级用法(Full Signature)。
也就是说,只有这3种情况下才是Config模式:
换句话说,只要我不指定"CONFIG",不指定“NO_MODULE",也不使用"full signature"中的关键字,那我就是在Mole模式。排查 find_package() 的第一步,应当判断它是Mole模式还是Config模式。
Mole模式下,相比于Config模式,可选配置参数少一些,并且如果按用户指定的配置却找不到包,就会自动进入Config模式(如上图所示)。
关键字解释
version 和 EXACT : 都是可选的, version 指定的是版本,如果指定就必须检查找到的包的版本是否和 version 兼容。如果指定 EXACT 则表示必须完全匹配的版本而不是兼容版本就可以。
QUIET 可选字段,表示如果查找失败,不会在屏幕进行输出(但是如果指定了 REQUIRED 字段,则 QUIET 无效,仍然会输出查找失败提示语)。
MODULE 可选字段。前面提到说“如果Mole模式查找失败则回退到Config模式进行查找”,但是假如设定了 MODULE 选项,那么就只在Mole模式查找,如果Mole模式下查找失败并不回落到Config模式查找。
REQUIRED 可选字段。表示一定要找到包,找不到的话就立即停掉整个cmake。而如果不指定 REQUIRED 则cmake会继续执行。
COMPONENTS , components :可选字段,表示查找的包中必须要找到的组件(components),如果有任何一个找不到就算失败,类似于 REQUIRED ,导致cmake停止执行。
OPTIONAL_COMPONENTS 和 components :可选的模块,找不到也不会让cmake停止执行。
Mole模式查找顺序
Mole模式下是要查找到名为 Find<PackageName>.cmake 的文件。
先在 CMAKE_MODULE_PATH 变量对应的路径中查找。如果路径为空,或者路径中查找失败,则在cmake mole directory(cmake安装时的Moles目录,比如 /usr/local/share/cmake/Moles )查找。
Config模式下的查找顺序,比Mole模式下要多得多。而且,新版本的CMake比老版本的有更多的查找顺序(新增的在最优先的查找顺序)。它要找的文件名字也不一样,Config模式要找 <PackageName>Config.cmake 或 <lower-case-package-name>-config.cmake 。查找顺序为:
实际上会找到opencv300,也就是 OpenCV_DIR 这一cmake变量的值最先起作用。