在现代 CMake 中,习惯上在命名空间内导出目标,例如有您的
foo
项目导出 foo::foo
也许还有 foo::bar
等
我的问题是:这些命名空间本身是否真的意味着什么,或者它们只是单个名称的一部分,而没有 CMake 分隔
::
分隔的名称组件?
如果前者是正确的,你可以说“命名空间中的所有目标”之类的东西,或者以其他方式使用命名空间吗?
我还没有看到任何允许单独处理命名空间导出目标的名称组件的 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 可以发出诊断。
find_package(noms COMPONENTS fruit veg)
之后,您将拥有
noms::fruit
和
noms::veg
可用于
target_link_libraries(…)
。但这只是当前广泛(且有用)的做法。从技术上讲,包组件不一定映射到一个目标(详细信息)。