Я пытаюсь настроить SCons, чтобы следить за зависимостями от файлов, которые генерируются автоматически во время сборки, и правильно работать с многопоточной сборкой.
Проект, который я создаю, представляет собой поставщик CIM, состоящий из файлов MOF, определяющих структуры данных, автогенерированных исходных и заголовочных файлов, которые поступают из файлов MOF, а также рукописных файлов источника и заголовка, которые ссылаются на автогенерированные файлы. Для того, чтобы сборка была успешной, шаг автогенерации должен завершиться до того, как любой из рукописных файлов будет скомпилирован, иначе заголовки, на которые опираются рукописные файлы, еще не будут существовать, и это не сработает. Файлы .cpp, созданные на этапе автогенерации, также должны быть добавлены в исходный список и скомпилированы в окончательной сборке.
При запуске однострочной сборки все работает отлично, потому что шаг автогенерации всегда завершен до этапа компиляции, поэтому созданные заголовки находятся на своем месте. Однако при запуске многопоточной сборки он пытается скомпилировать рукописные файлы до завершения этапа автогенерации, и сборка завершилась неудачей. Я указал явную зависимость, но SCons не следует за ней.
Вот соответствующая часть моего файла SConscript, я удалил отдельные имена файлов из cim_targets [], потому что список ОЧЕНЬ длинный, но, чтобы суммировать, cim_targets [] - это список целевых выходных файлов для этапа автогенерации, provider_sources [] - это возвращаемый список источников после завершения этапа автогена, sources [] - список рукописных исходных файлов, GenProvider() - это построитель команд, определенный извне, который выполняет шаг автогенерации, а 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 игнорирует эту зависимость и пытается скомпилировать рукописный текст файлов до завершения этапа автогенерации.