如何告诉CMake在链接命令中不传递重复的库。

5
我在两个静态库libA和libB之间存在循环依赖关系。
add_library(LibA STATIC a.c)
add_library(LibB STATIC b.c)

# Circular dependency: LibA <-> LibB
target_link_libraries(LibA PRIVATE LibB)
target_link_libraries(LibB PRIVATE LibA)

add_executable(Example main.c)
target_link_libraries(Example PRIVATE LibA LibB)


在生成构建配置时,CMake尝试通过将LibALibB两次传递给链接器来解决这些依赖关系。
ilinkarm.exe --silent CMakeFiles\Example.dir\main.c.o  LibA.lib  LibB.lib  LibA.lib  LibB.lib -o Example.exe

然而,我使用的IAR链接器已经通过库列表进行了多次遍历,如果只列出LibALibB一次,则足以满足要求。尽管带有重复项的链接仍然可以工作,但我会收到以下警告:

[build] Warning[Li065]: duplicate file: "LibA.lib"
[build] Warning[Li065]: duplicate file: "LibB.lib"

有没有可能告诉 CMake ,即使存在循环依赖关系,链接器命令中的每个库都必须是唯一的?

我尝试设置 CMAKE_C_LINK_EXECUTABLE ,但是我找不到替代 <LINK_LIBRARIES> 的方法,因为它似乎已经包含重复。这就是为什么此行会导致相同的警告:

set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>")

CMake 版本:3.26.3
Ninja 版本:1.10.2
IAR 版本:9.32.2


如果您删除 target_link_libraries(LibA PRIVATE LibB)target_link_libraries(LibB PRIVATE LibA),会产生什么结果? 依我的经验,ilinkarm 不用于“将库相互链接”。 - sharpgeek
为了让示例尽可能简单,我省略了LibALibBtarget_include_directories。如果删除target_link_libraries,CMake无法解析两个库之间的包含关系,从而导致构建失败。ilinkarm仅在最后一步用于链接可执行文件,在此时,CMake会添加重复项。 - JiaemTheCode
1个回答

2
通常这由LINK_INTERFACE_MULTIPLICITY属性控制。然而,CMake不尊重此属性值低于2的情况,因此在CMake 3.26中无法完成此操作。请参见此处的代码:

https://github.com/Kitware/CMake/blob/d9641980d2a223e0a6fe42ff23499e55f49fd6d5/Source/cmComputeLinkDepends.cxx#L1314-L1328

size_t cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
{
  size_t count = 2;
  for (size_t ni : nl) {
    if (cmGeneratorTarget const* target = this->EntryList[ni].Target) {
      if (cmLinkInterface const* iface =
            target->GetLinkInterface(this->Config, this->Target)) {
        if (iface->Multiplicity > count) {
          count = iface->Multiplicity;
        }
      }
    }
  }
  return count;
}

这里是CMake问题跟踪器的链接:https://gitlab.kitware.com/cmake/cmake/-/issues


1
据我的理解,LINK_INTERFACE_MULTIPLICITY属性是针对面临编译器错误的特定库或可执行文件进行构建的项目。 链接器只接受唯一库的事实应该在工具链/平台文件中表达。 因为该文件在项目创建库目标之前被解析,所以工具链/平台文件不应设置目标属性,而应该设置一些变量(普通或CACHE)。 - Tsyvarev
@AlexReinking 谢谢你的回答!虽然很遗憾听到 CMake 目前不支持这个... - JiaemTheCode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接