Cmake 通过“查找包”获取导入的目标?
使用Cmake 通过“查找包”获取导入的目标?,cmake,Cmake,使用find_包,并显示: 为每个Qt模块创建导入的目标。应首选导入的目标名称,而不是在诸如target_link_库之类的CMake命令中使用变量,如Qt5_库 它是Qt专用的还是find_package为所有库生成导入的目标?报告说: 当发现包时,通过包本身记录的变量和导入的目标提供包特定的信息 报告说: 使用find_package的结果要么是一组导入的目标,要么是一组与构建相关信息相对应的变量 但是我没有看到另一个FindXXX.cmake-脚本,文档中说创建了导入的目标。实际上,对于f
find_包
,并显示:
为每个Qt模块创建导入的目标。应首选导入的目标名称,而不是在诸如target_link_库之类的CMake命令中使用变量,如Qt5_库
它是Qt专用的还是find_package
为所有库生成导入的目标?报告说:
当发现包时,通过包本身记录的变量和导入的目标提供包特定的信息
报告说:
使用find_package
的结果要么是一组导入的目标,要么是一组与构建相关信息相对应的变量
但是我没有看到另一个FindXXX.cmake
-脚本,文档中说创建了导入的目标。实际上,对于find\u包的结果没有“魔力”:这个命令只是搜索适当的FindXXX.cmake
脚本并执行它
如果Find script设置了XXX\u库
变量,则调用者可以使用此变量
若Find脚本创建了导入的目标,那个么调用者可以使用这些目标
如果查找脚本既不设置XXX\u库
变量,也不创建导入的目标。。。嗯,那么脚本的用法就不同了
find\u包的文档描述了find脚本的常用用法。但在任何情况下,您都需要查阅有关具体脚本的文档(该文档通常包含在脚本本身中)。find\u包现在是一个双头野兽:
CMake为两种形式的软件包提供直接支持,
及
那到底是什么意思
查找模块包可能是您最熟悉的包。他们执行一个CMake代码脚本(如),该脚本对函数(如和)执行一系列调用,以确定库的位置
这种方法的最大优点是它非常通用。只要文件系统上有东西,我们就可以找到它。最大的缺点是,它通常提供的信息比该东西的物理位置多不了多少。也就是说,查找模块操作的结果通常只是一组文件系统路径。这意味着建模诸如可传递依赖项或多个构建配置之类的东西相当困难
如果您试图找到的东西本身是用CMake构建的,那么这会变得特别痛苦。在这种情况下,您已经在构建脚本中建模了一堆东西,现在需要为find脚本艰苦地重新构建这些东西,以便它可以用于下游项目
这就是配置文件包的位置。与find模块不同,运行脚本的结果不仅仅是一组路径,而是创建功能齐全的CMake目标。对于依赖项目来说,依赖项似乎是作为同一项目的一部分构建的
这样可以以非常方便的方式传输更多的信息。明显的缺点是,配置文件脚本比查找脚本复杂得多。因此,您不希望自己编写它们,而是让CMake为您生成它们。或者让依赖项提供一个配置文件作为其部署的一部分,然后您只需使用find_包
调用加载该文件即可。而这正是Qt5所做的
这也意味着,如果你自己的项目是一个库,考虑一下。这不是CMake最直接的特性,但是结果非常强大
下面是两种方法在CMake代码中的典型外观的快速比较:
查找模块样式
配置文件样式
tl;dr:如果依赖项提供配置文件包,则始终首选它们。如果没有,请使用查找脚本。那么为什么cmake会首先查找模块,然后在配置上回退?似乎配置模式提供了更好的信息,应该先完成。但是,如果配置模式和模块模式导入的目标具有不同的名称,则会很糟糕。如果您依赖于唯一找到的配置模式,并且后来在cmake中添加了一个模块,但该模块没有按预期导入目标,则这可能会产生严重问题。@johnb003这是出于历史原因,不会破坏与现有脚本的向后兼容性。通过将config
或NO\u模块
传递到find\u包
调用,可以强制CMake进入配置样式。在任何情况下,电话通常都不应该含糊不清。在绝大多数情况下,只能找到一种类型的脚本,因此不存在冲突。对于存在歧义的少数情况,您应该明确说明希望在哪个模式下运行find_package
。您可以强制使用配置模式,但这很尴尬。发生这种情况的简单示例是,如果您通过可重新定位的安装路径分发一组第三方软件包。问题是,您不想开始将第三方库的所有find_包调用攻击为“CONFIG”模式,它应该可以正常工作。CMake docs甚至主张,大多数情况下,您应该只使用锥形形式:find_包([major[.minor]][EXACT][REQUIRED | QUIET])
一些find模块包,例如Boost,包括多个库。配置文件包说明了这一点吗?一个foo
是否可以解析为多个库,比如上面的target\u link\u libraries(bar-foo)
示例?来自FindBoost.cmake:Boost::-特定组件依赖性的目标(共享或静态库);小写
。例如:Boost::filesystem
。
find_package(foo)
target_link_libraries(bar ${FOO_LIBRARIES})
target_include_directories(bar ${FOO_INCLUDE_DIR})
# [...] potentially lots of other stuff that has to be set manually
find_package(foo)
target_link_libraries(bar foo)
# magic!