【问题标题】:CMAKE: Circular ... dependency droppedCMAKE:循环...依赖性下降
【发布时间】:2021-12-03 20:47:36
【问题描述】:

我在项目源代码树的 imported 文件夹中有一个第 3 方(预构建)可执行文件(名为 other)。基本上,项目的结构是这样的:

.
├── CMakeLists.txt
├── imported
│   ├── libother.so
│   └── other
└── main.cpp

为了让我的应用程序正常运行,必须将 other 可执行文件复制到 my 可执行文件旁边,我使用此脚本实现的目的:

cmake_minimum_required(VERSION 3.21)
project(myproject)
add_executable(myexe main.cpp)
set(path_in ${CMAKE_SOURCE_DIR}/imported/other)
set(path_out ${CMAKE_BINARY_DIR}/other)
add_executable(other_i IMPORTED)
set_target_properties(other_i PROPERTIES IMPORTED_LOCATION ${path_in})
add_custom_command(OUTPUT ${path_out}
    COMMAND ${CMAKE_COMMAND} -E copy ${path_in} ${path_out}
    DEPENDS other_i
    )
add_custom_target(other DEPENDS ${path_out})
add_dependencies(myexe other)

问题是每当在 Linux 上构建项目时,我都会从 gmake 收到奇怪的消息:

$ cmake -S . -B .build
...
$ cmake --build .build
gmake[2]: Circular CMakeFiles/other <- other dependency dropped.
gmake[2]: Circular other <- other dependency dropped.

虽然 other 被复制得很好,但只要我重新发出构建命令(即使没有任何更改),它总是被复制。这是不可取的,最困扰我的是它与 Windows 上的 MSVC 以及 Linux 上的共享库完美配合。例如。这工作正常:

cmake_minimum_required(VERSION 3.21)
project(myproject)
add_executable(myexe main.cpp)
set(path_in ${CMAKE_SOURCE_DIR}/imported/libother.so)
set(path_out ${CMAKE_BINARY_DIR}/libother.so)
add_library(other_i SHARED IMPORTED)
set_target_properties(other_i PROPERTIES IMPORTED_LOCATION ${path_in})
add_custom_command(OUTPUT ${path_out}
    COMMAND ${CMAKE_COMMAND} -E copy ${path_in} ${path_out}
    DEPENDS other_i
    )
add_custom_target(other DEPENDS ${path_out})
add_dependencies(myexe other)

我对正在发生的事情束手无策。是CMAKE的错误还是我遗漏了什么? 任何见解将不胜感激。

PS:请不要建议在主要目标上使用 POST_BUILD,因为这种方法有其自身的缺点。

【问题讨论】:

  • DEPENDS other_i 为什么要依赖库?
  • @KamilCuk, 'DEPENDS other_i' - 这是对目标的依赖,不管它是什么
  • 但是你依赖于文件,而不是目标DEPENDS ${path_in}。该命令不关心目标。另外,building myexe 是否依赖于复制到二进制目录的库?对我来说,您应该像另一个自定义目标一样创建,这取决于正在构建的 myexe 和复制的库,这些是单独的不相关操作。
  • 它应该:“如果参数是目标的名称(由 add_custom_target()、add_executable() 或 add_library() 命令创建),则创建目标级别的依赖项以确保使用此自定义命令在任何目标之前构建目标。” cmake.org/cmake/help/latest/command/add_custom_command.html

标签: cmake


【解决方案1】:

线

add_custom_target(other DEPENDS ${path_out})

${CMAKE_BINARY_DIR}/other 创建other 的依赖关系。 但是从 Make 的角度来看,这些是相同的东西:两者都指的是构建目录下的文件otherMakefile 所在的位置)。因此,您会收到消息

gmake[2]: Circular other <- other dependency dropped.

问题的核心在于,与 CMake 不同,Make 没有分离 targets(纯名称)和 files(位于磁盘上)。从使所有目标(甚至.PHONY 的目标)都是文件的角度来看。

为目标 other 使用另一个名称(例如 other_exe)将消除此问题。

【讨论】:

  • 确实,虽然这可能是 CMAKE 中的一个错误,但将目标的名称“其他”更改为不同的名称可以消除问题。非常感谢。
【解决方案2】:

这似乎是 CMake 中的一个错误!我是这样解决它的:

cmake_minimum_required(VERSION 3.21)
project(myproject)

set(path_in "${CMAKE_CURRENT_SOURCE_DIR}/imported/other")
set(path_out "${CMAKE_CURRENT_BINARY_DIR}/other")

add_custom_command(
    OUTPUT "${path_out}"
    COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${path_in}" "${path_out}"
    DEPENDS "${path_in}"
)
add_custom_target(other_update DEPENDS "${path_out}")

add_executable(myproject::other IMPORTED)
set_target_properties(myproject::other PROPERTIES IMPORTED_LOCATION "${path_out}")
add_dependencies(myproject::other other_update)

add_executable(myexe main.cpp)
add_dependencies(myexe myproject::other)

在指定依赖项时还有其他一些问题,所以我清理了这些问题。即便如此,我观察到将可执行目标(即使已导入)命名为与输出文件相同也会导致错误。您应该在上游打开 CMake 问题。

一般来说,利用 CMake 总是将包含 :: 的名称视为目标名称这一事实是一个好主意。

【讨论】:

  • CMake Error at ... (add_custom_target): 1> 目标名称“myproject::other”对于某些 CMake 功能(例如生成器表达式)已保留或无效,并且可能导致未定义的行为. - MSVC
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 2021-10-02
相关资源
最近更新 更多