У меня возникла небольшая проблема с рефакторингом системы сборки на основе scons. У нас есть исходное дерево C/C++ с несколькими различными объектами вывода (dll, исполняемые файлы, тестовые исполняемые файлы )и несколько разнородный макет для наших исходных файлов (, хотя большая часть его находится в каталогах «модуль» с src/
и inc/
каталоги ).
Одна из моих самых больших проблем с текущей настройкой заключается в том, что мы действительно хотим, чтобы все эти продукты сборки были собраны с согласованными параметрами компилятора по умолчанию. Наш текущий макет имеет основной файл SConstruct, вызывающий множество вложенных -файлов SConscript в подкаталогах, которые затем создают части более крупных продуктов сборки (.a
. например ). По умолчанию функция SConscript()
в scons не передает и не наследует текущий объект среды построения вызываемому файлу SConstruct. Это означает, что в настоящее время все эти субфайлы -SConstript используют свои собственные среды построения.
В новом макете, который я пытаюсь собрать, основная среда конструирования собирается в корне исходного дерева -со всеми необходимыми CFLAGS и определениями сборки, которые нам нужны. Я бы хотел, чтобы эта среда построения передавалась в подфайлы -SConscript, чтобы я знал, что каждый отдельный файл .c
и .cpp
в нашем дереве сборки создается с помощью одной и той же командной строки.
Однако я не уверен, как это сделать в scons. Есть функции Import()
и Export()
, но это, по сути, уродливые глобальные переменные -вызывающий файл SConstruct не имеет большого контроля над тем, что делает подчиненный файл -SConstruct с глобальной переменной, которая Export()
изд. Есть ли какой-либо чистый способ, по существу, передать файл sub -SConscript текущей среды построения в качестве параметра, не позволяя ему обязательно изменять его?Что-то вроде:
master_env = Environment()
master_env.Append( CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC',... ] )
### add other stuff that we want everything to use
SConscript( 'somelibrary/SConstruct', inherited_environment=master_env.Clone() )
### master_env has now been used to build a
###.dll in somelibrary/, but any variations
### made to somelibrary/SConstruct's inherited
### env haven't contaminated master_env
Я знаю, что мог бы сделать что-то неуклюжее и грубое:
clobber_env = Environment()
master_env = Environment()
master_env.Append( CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC',... ] )
call_somelibrary_sconstruct( master_env )
def call_somelibrary_sconstruct(env):
param_env = env.Clone()
Export( 'param_env' )
SConstript( 'somelibrary/SConstruct' )
# because we don't want any contamination of our global variable
# between SConscript calls. I'm not even sure if this is necessary
# or does what I think it does because I'm not sure how this ugly
# Export()'d global variable environment works with locals like
# param_env here.
param_env = clobber_env
Export( 'param_env' )
Есть ли элегантный способ сделать это?
Обновление:
Итак, я поиграл с этим еще немного, и похоже, что пока я делаю это в главном файле SConstruct:
def build_somelib( env ):
Export( env=env.Clone() )
somelib = SConscript( 'somelib/SConscript' )
return somelib
master_env = Environment()
master_env.Append( CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC',... ] )
build_somelib( master_env )
а затем вsomelib/SConscript
Import( 'env' )
env.Append( CXXFLAGS=['-weirdoption1',... ] )
lib = env.StaticLibrary( 'somelib', source=['source1.cpp', 'source2.cpp',...] )
Return( "lib" )
тогда master_env
в основном SConstruct остается незагрязненным. Для меня было важно, чтобы Export( env=env.Clone() )
работало, потому что я не хотел полагаться на все подчиненные -SConscripts для обеспечения безопасности -Клонировать ()'уведомление -о том, что политика должна быть родительской SConscript/ Файлы SConstruct.
Тем не менее, немного некрасиво иметь env
в качестве имени параметра в соответствии с политикой.