添加不存在的目标时强制 CMake target_link_libraries 失败

Posted

技术标签:

【中文标题】添加不存在的目标时强制 CMake target_link_libraries 失败【英文标题】:Force CMake target_link_libraries to fail when adding nonexistent target 【发布时间】:2020-05-08 14:41:25 【问题描述】:

CMake 有一个令人讨厌的默认值(我想,我的 CMake 配置中没有任何神奇之处,但我可能是错的,因为我对 CMake 知之甚少)当您将目标添加到项目时,他会默默地忽略该行为,即使那目标不存在,例如:

项目(堆栈溢出)

// 另一个 CMakeLists.txt

项目(东西)

target_link_libraries(东西 PUBLIC StackOverlow )

有没有办法强制 CMake 检查您在 target_link_libraries 中链接的所有项目是否必须存在?

【问题讨论】:

您的示例中不存在的目标是什么?您的示例中 target_link_libraries() 的语法不正确。具体来说,第一个参数必须是一个现有的目标,否则你会收到一个错误。您还没有创建目标*** @squareskittles 对不起,我把我真正的 CMakeLists.txt 减少了太多,谢谢你的错误报告 :) 【参考方案1】:

在 CMake 中,您不会将项目链接到其他项目。相反,您将目标链接到其他目标。

CMake 目标通过一些命令(例如add_libraryadd_executableadd_custom_target)创建。 project 命令不会创建 CMake 目标,它只是声明一个项目。

此外,target_link_libraries() 命令在作用域关键字之后接受以下参数:

库目标名称 库文件的完整路径 简单的库名 链接标志 生成器表达式 debugoptimizedgeneral 关键字

它不接受项目名称,但如果您输入项目名称,它会改为在您的系统上查找 CMake 目标 或库文件那个名字

要了解我认为您要问的问题的根源:如果您向 target_link_libraries() 提供的链接项名称与现有目标不匹配,则该命令将简单地搜索 库文件 代替那个名字。

要在尝试链接目标之前检查目标是否存在,您可以这样做:

if (TARGET ***)
    target_link_libraries(Stuff PUBLIC ***)
endif()

如果您想了解有关此命令功能的更多详细信息,我建议您阅读链接的 target_link_libraries() 文档。

【讨论】:

啊,这绝对不理想......是的,你是对的,我从未考虑过 target_link_libraries 会寻找库而不是失败的“后备”(或默认)。 现在我也发现了我想要的这个功能请求:cmake.org/pipermail/cmake/2019-February/068983.html 看起来被忽略了。 :) @NoSenseEtAl 可以在here 找到活动的 CMake 问题,尽管通过快速搜索我没有看到与此问题相关的任何内容。 CMake 为保持向后兼容性做出了令人难以置信的努力,我认为这样的更改会打破这一点。也许,他们可以添加一个 CMake 策略,以便在链接非目标链接项时选择性地产生警告...... 我看不出添加新的内置函数 (target_add_targets) 会如何破坏 bw 兼容性,但是就像我说的那样,CMake 对我来说主要是一个黑盒子。【参考方案2】:

如果您链接 ALIAS 目标,CMake 可能会失败。例如

在第一个 CMakeLists.txt

add_library(*** STATIC lib.cpp)
add_library(***::*** ALIAS ***)

在第二个 CMakeLists.txt

target_link_libraries(Stuff PUBLIC ***::***)

如果未定义 ***::***,CMake 将失败并出现错误。

https://cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#alias-targets

【讨论】:

以上是关于添加不存在的目标时强制 CMake target_link_libraries 失败的主要内容,如果未能解决你的问题,请参考以下文章

使用 custom_target 创建的 cmake 目标失败

柯南和 Cmake:目标已经存在

CMake基础教程(21)add_custom_target添加一个伪目标执行定制操作

在 CMake 中使用 target_sources() 添加源文件后删除它

如何在cmake 2.8.12中删除每个目标的定义

cmake 强制链接静态库