CMake 命名空间真的有意义吗?

Do CMake namespaces actually mean anything?

在现代 CMake 中,习惯于在命名空间内导出目标,例如将您的 foo 项目导出 foo::foo,也许还有 foo::bar

我的问题是:这些名称空间本身是否真正意味着什么,或者它们只是一个名称的一部分,没有 CMake 分隔 ::-分隔的名称组件?

如果前者为真,您能否说“命名空间中的所有目标”或以其他方式使用命名空间?

我(还)没有看到任何允许单独处理命名空间导出目标的名称组件的 CMake 功能。但是我发现CMake的命名空间还是有一个含义,影响CMake的行为:

命名空间目标永远不是文件名

target_link_libraries(…) 调用中使用包含 :: 的目标名称将确保 CMake 仅将其解析为通过 find_package(…) 找到的所谓 IMPORTED targets。它阻止了通常的回退机制也尝试将其解析为磁盘上的库文件名(例如 -lName 将在磁盘上查找 libName.so)。

该行为记录在 CMake Policy 0028 中。不一定到处都启用,但CMake≥3.0.2如果不启用会警告。

这也很有用。我刚刚遇到了一个由 CMake 的后备行为 (see) 引起的令人困惑的问题。因此,我将在 target_link_libraries(…).

中严格使用带有 :: 的命名空间目标名称

遗憾的是,从 another piece of CMake documentation 看来,识别 IMPORTED 目标的这一特征可能是 CMake 命名空间的唯一含义:

A NAMESPACE with double-colons is specified when exporting the targets for installation. This convention of double-colons gives CMake a hint that the name is an IMPORTED target when it is used by downstreams with the target_link_libraries() command. This way, CMake can issue a diagnostic if the package providing it has not yet been found.

包组件是另一回事

乍一看,在我看来,每个 CMake 包都有一个命名空间,每个包组件在该命名空间中都有一个目标名称。因此,在 find_package(noms COMPONENTS fruit veg) 之后,您将有 noms::fruitnoms::veg 可用于 target_link_libraries(…)。但这只是一种广泛(且有用)的当前做法。从技术上讲,包组件不一定映射到一个目标 ()。