CMake 命名空间实际上有什么意义吗?

问题描述 投票:0回答:1

在现代 CMake 中,习惯上在命名空间内导出目标,例如有您的

foo
项目导出
foo::foo
也许还有
foo::bar

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

::
分隔的名称组件?

如果前者是正确的,你可以说“命名空间中的所有目标”之类的东西,或者以其他方式使用命名空间吗?

cmake namespaces semantics
1个回答
6
投票

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

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

::
调用中使用包含
target_link_libraries(…)
的目标名称将确保 CMake 仅将其解析为通过 find_package(…) 找到的所谓的
IMPORTED 目标
。它可以防止通常的后备机制尝试将其解析为磁盘上的库文件名(就像
-lName
在磁盘上查找
libName.so
一样)。

该行为记录在CMake 策略 0028 中。不一定在所有地方都启用,但如果不启用,CMake ≥3.0.2 会发出警告。

也很有用。我刚刚遇到了一个由 CMake 的后备行为引起的令人困惑的问题(see)。因此,我将严格使用命名空间目标名称以及

::
中的
target_link_libraries(…)

可悲的是,从另一篇 CMake 文档来看,识别 IMPORTED 目标的这一功能可能是 CMake 命名空间的唯一含义:

导出安装目标时指定带有双冒号的

NAMESPACE

。当下游通过 
IMPORTED
 命令使用该名称时,这种双冒号约定会向 CMake 提示该名称是 
target_link_libraries()
 目标。这样,如果尚未找到提供诊断的包,CMake 可以发出诊断。

封装组件是另一回事

乍一看,在我看来,每个 CMake 包都有一个命名空间,每个包组件在该命名空间中有一个目标名称。这样,在

find_package(noms COMPONENTS fruit veg)

 之后,您将拥有 
noms::fruit
noms::veg
 可用于 
target_link_libraries(…)
。但这只是当前广泛(且有用)的做法。从技术上讲,包组件不一定映射到一个目标(
详细信息)。

© www.soinside.com 2019 - 2024. All rights reserved.