我正在尝试设置SCons以跟踪在构建过程中自动生成的文件的依赖关系,并正确处理多线程构建。 我正在构建的项目是CIM提供程序,由定义数据结构的MOF文件、从MOF文件生成的自动生成的源文件和头文件以及引用自动生成文件的手写源文件和头文件组成。为了使构建成功,必须在编译任何手写文件之前完成自动生成步骤,否则手写文件依赖的头文件将不存在并且构建将失败。由自动生成步骤创建的.cpp文件还必须添加到源列表中,并在最终构建中进行编译。
当运行单线程构建时,一切都正常,因为自动生成步骤始终在编译步骤之前完成,因此生成的头文件已经就位。但是,在运行多线程构建时,它会在自动生成步骤完成之前尝试编译手写文件,导致构建失败。我已经指定了显式依赖关系,但SCons没有遵循它。
这是我的SConscript文件的相关部分,我从cim_targets[]中删除了单个文件名,因为列表非常长,但总结一下,cim_targets[]是自动生成步骤的目标输出文件列表,provider_sources[]是自动化生成步骤完成后返回的源文件列表,sources[]是手写源文件列表,GenProvider()是在外部定义的Command builder,用于执行自动生成步骤,SharedLibrary()是在外部定义的builder,使用SCons库builder和一些扩展。
当运行单线程构建时,一切都正常,因为自动生成步骤始终在编译步骤之前完成,因此生成的头文件已经就位。但是,在运行多线程构建时,它会在自动生成步骤完成之前尝试编译手写文件,导致构建失败。我已经指定了显式依赖关系,但SCons没有遵循它。
这是我的SConscript文件的相关部分,我从cim_targets[]中删除了单个文件名,因为列表非常长,但总结一下,cim_targets[]是自动生成步骤的目标输出文件列表,provider_sources[]是自动化生成步骤完成后返回的源文件列表,sources[]是手写源文件列表,GenProvider()是在外部定义的Command builder,用于执行自动生成步骤,SharedLibrary()是在外部定义的builder,使用SCons库builder和一些扩展。
# 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会忽略此依赖关系,并尝试在自动生成步骤完成之前编译手写文件。