Я делаю это для сборок для нескольких платформ (а не для отладки / выпуска), но концепция та же. Основная идея заключается в том, что вам нужно 2 файла в корне проекта - SConstruct для настройки каталогов сборки (или «альтернативных каталогов», как они известны в scons), а затем SConscript, который описывает фактические шаги сборки.
В файле SConstruct вы должны указать каталог вариантов и соответствующий ему каталог исходного кода:
SConscript(dirs='.',
variant_dir=variant_dir,
duplicate=False,
exports="env")
Теперь вы хотите, чтобы option_dir зависел от флага. Вы бы использовали AddOption или Переменные, чтобы сделать это. Вот один пример полной SConstruct верхнего уровня, чтобы сделать это:
# build with `scons --debug-build` for debug.
AddOption(
'--debug-build',
action='store_true',
help='debug build',
default=False)
env = Environment()
if GetOption('debug_build'):
env.ParseFlags('-DDEBUG')
variant_dir = 'build/debug'
else:
variant_dir = 'build/release'
SConscript(dirs='.',
variant_dir=variant_dir,
duplicate=False,
exports="env")
AddOption проще всего использовать, но если вы используете переменные, вы можете кэшировать результат между запусками, вместо того, чтобы каждый раз произносить "scons --debug-build".
Все настройки каталогов и связанные с ними помехи находятся в SConstruct. Теперь файл SConscript довольно прост и ему не нужно беспокоиться о каталогах сборки.
Import('env')
env.Program(target='foo_prog', source=['foo/main.cpp', 'lib/libmoo.a'])
# foo_prog since foo already exists as the name of the directory...
Это самый простой способ настроить разные каталоги сборки без каких-либо странных ошибок. Он также довольно гибкий - вы можете добавлять различные сборки платформы, просто изменив «env» в скрипте верхнего уровня, не изменяя фактическое ядро сборки.
Единственный гаечный ключ в работах по вашему вопросу - это способ компиляции проектов в стиле автоконф непосредственно из SCons. Самый простой способ, вероятно, с парой вызовов Command (), но SCons любит знать о входах и выходах каждого шага, так что это может быть хакерским. Кроме того, вы должны полагаться на сборку autoconf с правильной настройкой VPATH - некоторые проекты не будут работать, если вы попытаетесь скомпилировать вне исходного кода. В любом случае, способ компиляции проектов autoconf будет выглядеть примерно так:
import os
Import('env')
# get the path to the configure script from the "moo" source directory
conf = env.File('moo/configure').srcnode().abspath
# Create the "moo" build directory in the build dir
build_dir = env.Dir('.').path
moo_dir = os.path.join(build_dir, 'moo')
Mkdir(moo_dir)
# run configure from within the moo dir
env.Command('moo/Makefile', 'moo/Makefile.am',
conf, chdir=moo_dir)
# run make in the moo dir
env.Command('moo/libmoo.a', 'moo/Makefile',
'make', chdir=moo_dir)
env.Program(target='foo_prog', source=['foo/main.cpp', 'moo/libmoo.a'])
Выполнение шага настройки из исходного каталога, когда текущий рабочий каталог находится где-то в иерархии сборки, неудобно. Шаг make не так сложен, но все же нужно знать о текущем каталоге сборки. Поскольку вы указываете «libmoo.a» в качестве выходных данных шага make и libmoo.a в качестве входных данных для программы, все зависимости просто работают, поэтому параллельная сборка работает нормально. Параллельные сборки ломаются только тогда, когда вы слишком много выдумываете зависимости.