cmake add_custom_command 引入了错误的依赖,除非还使用了 add_custom_target

问题描述

我正在使用 cmake 构建一些库,所有这些库都生成了它们的一些文件

我已经使用 add_custom_command() 创建了生成文件,但我发现了一些似乎是错误依赖的东西。如果下游库具有生成文件链接到上游库,则在上游库完全构建之前,下游库源不会开始编译。由于我的项目中有许多库(超过 50 个),这种错误的依赖会导致构建中的序列化。

奇怪的是,我还注意到,如果生成文件的显式 add_custom_target() 与 add_dependencies() 一起使用,则虚假依赖不再存在,下游库中的文件将与上游图书馆。所以我有一个解决方法,但这是预期的行为吗?

使用 Cmake 1.19,Ninja 1.10.2。

以下是显示发生了什么的最小 CMakeLists.txt 文件。 WORKS 选项有条件地添加 add_custom_target() 和 add_dependencies() 子句,使其工作(快速)。文件 foo.c 和 bar.c 是空的,我在 CMakeLists.txt 目录的子目录中构建。

我放置了一个名为 /tmp/x 的文件,它是 cc 的包装器,它休眠以显示序列化发生:

#!/bin/bash -e

echo "mycc" $(date)
sleep 4
exec /usr/bin/cc $*

这是 CMakeLists.txt:

cmake_minimum_required(VERSION 3.19)

project(test)
option(WORKS "false dependency gone if WORKS set to ON" OFF)

add_library(foo
  foo.c
  )

add_library(bar
  bar.c
  bargen.h
  )

target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
add_custom_command(OUTPUT bargen.h
        COMMAND touch bargen.h
   )
if (${WORKS})
  add_custom_target(generate_file
        DEPENDS bargen.h
  )
  add_dependencies(bar generate_file)
endif()

target_link_libraries(bar PUBLIC foo)

像这样构建,您将看到序列化:bar.c 将在 foo.c 编译完成后才开始编译(实际上,直到 foo 库构建完成后才会开始编译)。 (我明确选择了“-j 4”以确保 Ninja 会尝试并行构建)。

cmake -DWORKS=OFF -G Ninja -DCMAKE_C_COMPILER=/tmp/x .. && ninja clean && ninja -j 4 -v | grep mycc

显示了以下输出

-- Configuring done
-- Generating done
-- Build files have been written to: /Users/rhb/Downloads/cmake-anomaly/build
[1/1] Cleaning all built files...
Cleaning... 5 files.
mycc Sat Jan 2 15:15:25 EST 2021
mycc Sat Jan 2 15:15:29 EST 2021

现在像这样构建它,你会看到 bar.c 与 foo.c 同时编译:

cmake -DWORKS=ON -G Ninja -DCMAKE_C_COMPILER=/tmp/x .. && ninja clean && ninja -j 4 -v | grep mycc

-- Configuring done
-- Generating done
-- Build files have been written to: /Users/rhb/Downloads/cmake-anomaly/build
[1/1] Cleaning all built files...
Cleaning... 5 files.
mycc Sat Jan 2 15:15:37 EST 2021
mycc Sat Jan 2 15:15:37 EST 2021

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)