我正在尝试设置SCons以跟踪在构建期间自动生成的文件的依赖关系,并使用多线程构建正常工作。
我正在构建的项目是一个CIM提供程序,包括定义数据结构的MOF文件,来自MOF文件的自动生成的源文件和头文件,以及引用自动生成文件的手写源文件和头文件。为了使构建成功,自动生成步骤必须在编译任何手写文件之前运行完成,否则手写文件所依赖的标题将不存在并且将失败。自动生成步骤创建的.cpp文件也必须添加到源列表中并在最终构建中进行编译。
运行单线程构建时,一切正常,因为自动生成步骤始终在编译步骤之前完成,因此生成的头文件就位。但是,在运行构建多线程时,它会尝试在自动生成步骤完成之前编译手写文件,并且构建失败。我已经指定了一个显式依赖项,但SCons没有遵循它。
以下是我的SConscript文件的相关部分,我从cim_targets []中删除了单个文件名,因为列表非常长,但总而言之,cim_targets []是自动生成步骤的目标输出文件列表,provider_sources [] autogen步骤完成后返回的源列表,sources []是手写源文件列表,GenProvider()是外部定义的Command构建器,用于执行自动生成步骤,SharedLibrary()是外部定义的构建器,它执行的操作是什么听起来像,使用带有一些扩展名的SCons库构建器
# Define directory paths for the CIM schema
cim_dir = 'cim-schema-2.26.0'
var_smis_dir = Dir('.').abspath # src/lib/XXX in variant
cim_sources = [
Glob(os.path.join(cim_dir, '*qualifiers*.mof')),
Glob(os.path.join(cim_dir, 'Core') + '/CIM_*.mof'),
Glob(os.path.join(cim_dir, 'Device') + '/CIM_*.mof'),
Glob(os.path.join(cim_dir, 'Event') + '/CIM_*.mof'),
Glob(os.path.join(cim_dir, 'XXXXXX') + '/XXX_*.mof'),
Glob(os.path.join(cim_dir, 'Interop') + '/CIM_*.mof'),
Glob(os.path.join(cim_dir, 'Physical') + '/CIM_*.mof'),
Glob(os.path.join(cim_dir, 'System') + '/CIM_*.mof'),
]
cim_sources_flat = []
for cim in cim_sources:
for src in cim:
cim_sources_flat.append(src)
cim_targets = [
......
]
sources = [
'driver.cpp',
'device.cpp',
'cim_static_data.cpp',
'module.cpp',
'diag_log.cpp',
'profile_element.cpp',
]
staticlibs = [
......
]
dynamiclibs = [
.....
]
var_cim_sources = this_env.Install(var_smis_dir, cim_sources_flat)
cim_mof = 'cimv226.mof'
cim_linux_mof = os.path.join(cim_dir, 'cimv226-gen-flat.mof')
var_cim_sources.extend(this_env.Command(cim_mof, cim_linux_mof, Copy('$TARGET', '$SOURCE')))
# first generate the provider infrastructure using cimple
provider_sources = this_env.GenProvider(cim_targets, var_cim_sources, name, var_smis_dir)
# make sure these files don't build until AFTER the provider files have been created
this_env.Depends(sources, provider_sources)
sources_full = provider_sources + sources
# now we can compile the provider
this_env.SharedLibrary(libname, source=sources_full, staticlibs=staticlibs, dynamiclibs=dynamiclibs, installpath=install_dir)
我尝试设置一个显式依赖项,以便在创建所有生成的源(this_env.Depends(sources,provider_sources))之前不会编译手写源,但是当运行多线程时,SCons会忽略此依赖项并尝试编译手写自动生成步骤完成之前的文件。
答案 0 :(得分:3)
答案 1 :(得分:-1)
我能够通过将生成的文件设为Command
的目标来解决此问题。例如,假设您有一个文件foo.c
:
#include <stdio.h>
#include "foo.h"
int main() {}
并说foo.h
必须先生成,然后才能构建foo.c
。您可以这样做:
import time
def build_foo(target, source, env):
print("Generating foo source files")
time.sleep(5)
with open("foo.h", "w") as f:
f.write("")
# Generate bar.so, which we need later for X, blah blah blah
print("Done generating")
env = Environment()
env.Command(['foo.h', 'bar.so'], 'foo.in', build_foo)
env.Program('foo', 'foo.c')
构建输出如下:
$ scons -Q -j4
build_foo(["foo.h", "foo.so"], ["foo.in"])
Generating foo source files
Done generating
gcc -o foo.o -c foo.c
gcc -o foo foo.o
如果省略foo.h
作为目标(即env.Command(['bar.so'], 'foo.in', build_foo)
,则构建输出如下所示:
$ scons -Q -j4
gcc -o foo.o -c foo.c
build_foo(["foo.so"], ["foo.in"])
Generating foo source files
foo.c:2:10: fatal error: foo.h: No such file or directory
#include "foo.h"
^~~~~~~
compilation terminated.
scons: *** [foo.o] Error 1
Done generating