提问人:einpoklum 提问时间:7/11/2022 更新时间:7/12/2022 访问量:918
如何避免与使用FetchContent_MakeAvailable“导入”的目标发生冲突?
How can I avoid clashes with targets "imported" with FetchContent_MakeAvailable?
问:
假设我正在编写一个应用程序,并使用 CMake 管理其构建;我还想通过 FetchContent 机制使用库 mylib。
现在,我自己定义了一堆目标,mylib 的也是如此。如果我要安装 mylib,那么 ,我只会得到它导出的目标,甚至那些目标也会以(至少通常是这样)为前缀。但是使用 FetchContent 时,我的应用程序和 mylib(内部和导出目标)目标都在“全局命名空间”中,并且可能会发生冲突。CMakeLists.txt
CMakeLists.txt
find_package(mylib)
mylib::
那么,除了精心命名我自己的应用程序的所有目标之外,我还能做些什么来区分这些目标呢?
如果有可能以某种方式将所有 mylib 目标“推入”我选择的命名空间,我真的很喜欢它。
答:
正如@AlexReinking,事实上,克雷格·斯科特(Craig Scott)所建议的那样,目前没有像样的解决方案。
您可以遵循以下 CMake 问题,通过这些问题可能会实现解决方案:
评论
Halide
Halide_Runtime
Halide_ImageIO
Halide::Halide
Halide::Runtime
Halide::ImageIO
在当前的 CMake (<=3.24) 世界中,没有其他黑盒项目中用于调整目标名称的功能,无论是通过 、 还是 。因此,就目前而言,您有责任避免目标、安装组件、测试名称以及其他任何可能成为问题的地方的名称冲突。find_package
add_subdirectory
FetchContent
克雷格·斯科特(Craig Scott)在CppCon 2019的(非常好)演讲中说了同样多的话,请参阅此处:https://youtu.be/m0DwB4OvDXk?t=2186
他建议的约定是使用以 . 为前缀的名称。他不建议从字面上使用 ,我也不会,因为这样做会使代码更难阅读(这对于理解第 3 方构建非常有用)。SomeProj_
${PROJECT_NAME}_
grep
然而,要成为一个好人或公民,仅仅将你的目标命名为是不够的;您还必须提供一个目标 .这有几个原因:add_subdirectory
FetchContent
SomeProj_Target
ALIAS
SomeProj::Target
- 您从中导入的目标几乎肯定会被命名为 。库的使用者应该可以在不更改其代码的其他部分的情况下轻松切换。ALIAS 目标允许您在这两种情况下公开相同的接口。当 CMake 3.24 推出其新的重定向功能时,这将变得尤为紧迫。
find_package
SomeProj::Target
FetchContent
find_package
find_package
FetchContent
- CMake 的函数始终将包含的名称视为目标名称,如果目标不存在,则会引发 configure-time 错误。如果没有 ,它将优先被视为目标,但如果目标不存在,它将变成链接器标志。因此,最好链接到名称中带有的目标。
target_link_libraries
::
::
::
- 然而,只有和目标可能在其名称中。
IMPORTED
ALIAS
::
点 (2) 和 (3) 足以让我定义别名。
不幸的是,许多(大多数?CMake 构建不是好的 FetchContent 公民,并且会炫耀这个约定。遵循这个约定可以减少你的项目与任何其他项目之间出现集成问题的机会,但显然不能防止两个第三方项目之间可能定义冲突目标的问题。在这些情况下,你只是运气不好。
定义一个名为 that will good with FetchContent 的库的示例:Target
add_library(SomeProj_Target ${sources})
add_library(SomeProj::Target ALIAS SomeProj_Target)
set_target_properties(
SomeProj_Target
PROPERTIES
EXPORT_NAME Target
OUTPUT_NAME Target # optional: makes the file libTarget.so on disk
)
install(TARGETS SomeProj_Target EXPORT SomeProj_Targets)
install(EXPORT SomeProj_Targets NAMESPACE SomeProj::)
有关安装组件、包含路径和双重共享/静态导入的更完整示例,请参阅我的博客文章。
请参阅这些上游问题,以跟踪这些问题的进度/讨论。
评论