我正在重构一个基于scons的构建系统时遇到了一些问题。我们有一个包含多个不同输出对象(dll、可执行文件、测试可执行文件)的C/C++源代码树,并且源文件的布局有些异构(尽管大部分在“模块”目录中,其中包括src/
和inc/
目录)。
目前设置中最大的问题之一是,我们希望所有这些构建产品都默认使用一致的编译器选项进行构建。我们当前的布局有一个主SConstruct文件,在子目录中调用许多子SConscript文件,然后构建较大构建产品的各个部分(例如.a
)。默认情况下,scons中的SConscript()
函数不会将当前构建环境对象传递或继承到被调用的SConstruct文件中。这意味着当前所有这些子SConscript文件都在使用自己不同的构建环境。
我正在尝试组合的新布局在源代码树根处放置了一个主构建环境,其中包含了我们需要的所有CFLAGS和构建定义。我想将此构建环境传递给子SConscript文件,以便我知道我们构建树中的每个.c
和.cpp
文件都使用相同的命令行进行构建。
然而,我不确定如何在scons中实现这一点。有Import()
和Export()
函数,但这些基本上是丑陋的全局变量——调用SConstruct文件对于Export()
的全局变量没有太多控制权。是否有任何干净的方式将当前构建环境作为参数传递给子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" )
那么主SConstruct中的master_env
将保持不受污染。对我来说,Export( env=env.Clone() )
很重要,因为我不想依赖于所有子SConscripts进行安全的Clone()操作 - 这个策略应该由父SConscript/SConstruct文件来执行。
然而,按照政策要求将env
作为参数名称有点丑陋。
exports='env'
。 - arr_sea