当生成头文件时,我正在努力使并行make正常运行。 C文件的构建通常在头文件被完全写入之前开始,从而导致各种故障。我找不到任何避免比赛的方法。
让我提供血腥细节。我认为根本的问题不在于这些细节。但为了公平/准确,就在这里。这是一个相对简单,跟随您鼻子的类型设置。所以...有一个文件,AtomTypes.cmake
包含
FILE(WRITE "tmp.h" "/* stuff stuff and more stuff */")
FILE(APPEND "tmp.h" "/* its done now */")
# Make sure writing is completed, before file is visible!
FILE(RENAME "tmp.h" "foo.h")
为了简化上述内容的使用(实际上是又大又笨重的,有一个宏:
MACRO(ADD_TYPES SCRIPT_FILE HEADER_FILE)
ADD_CUSTOM_COMMAND (
COMMAND "${CMAKE_COMMAND}" -P AtomTypes.cmake
OUTPUT "${HEADER_FILE}"
DEPENDS "${SCRIPT_FILE}"
)
ENDMACRO()
然后我可以在某个rando目录的“普通” CMakefile中使用它:
ADD_TYPES(some_types.script foo.h)
# A custom target for use in other (dependent) directories.
ADD_CUSTOM_TARGET(my_types DEPENDS foo.h)
# The local library, in this directory
ADD_LIBRARY(foo
bar.cc
baz.cc)
# All the blogs say I need this, but it doesn't work
# (doesn't do anything)
ADD_DEPENDENCIES(foo my_types)
bar.cc
和baz.cc
可能与您猜测的一样:
#include <some/path/foo.h>
/* stuff*/
如果我运行非并行make,则一切正常:没有来自cmake或make的错误,foo.h
是自动生成的,一切都能编译,没有错误。并且甚至仅在触摸foo.h
时才重新生成types.script
,因此依赖项起作用。但是,如果我运行并行make,则构建竞赛。 bar.cc
的编译在写入foo.h
之前开始。像这样:
bar.cc:30: fatal error: some/path/foo.h: No such file or directory
#include <some/path/foo.h>
^~~~~~~~~~~~~~~~~
compilation terminated.
当然,第二次运行make
解决了该错误。 (失败的构建遗留了foo.h
的副本。)
如果我尝试手动调试,则通过查看./CMakeFiles/foo.dir/depend.make
,显然存在缺少的依赖项!!很多东西,例如
CMakeFiles/foo.dir/bar.cc.o: some/other/header.h
但绝对不依赖foo.h
!!!! ???怎么可能?很明显,在源代码中...
此冒险由cmake version 3.13.4
在Debian马stable中带给您。
我会尝试这个简单的解决方案:
ADD_LIBRARY(foo
bar.cc
baz.cc
foo.h # or ${HEADER_FILE}
)
头文件被编译器忽略,但是将头文件包含在目标的源列表中有两个目的:一个用于生成的头文件,例如'config.h'或您的。另一个是在某些头文件已更改时触发目标的重建。这就是为什么不建议使用file(GLOB)
来建立来源列表的原因。