问题描述
我正在使用 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 (将#修改为@)