Estoy teniendo un problema para refactorizar un sistema de compilación basado en scons. Tenemos un árbol fuente C/C++ con varios objetos de salida diferentes (dlls, ejecutables, ejecutables de prueba) y un diseño un tanto heterogéneo para nuestros archivos fuente (aunque la mayoría está en directorios 'module' con directorios src/
y inc/
).scons herencia del entorno de construcción
Uno de mis mayores problemas con la configuración actual es que realmente queremos que todos estos productos de compilación se construyan con opciones de compilador consistentes de forma predeterminada. Nuestro diseño actual tiene un archivo master SConstruct que invoca muchos archivos subConscription en subdirectorios que luego compilan piezas de los productos de compilación más grandes (por ejemplo, .a
). Por defecto, la función SConscript()
en scons no pasa ni hereda el objeto de entorno de construcción actual al archivo llamado SConstruct. Eso significa que actualmente todos esos archivos SConstript secundarios están utilizando sus propios entornos de construcción diferentes.
El nuevo diseño que estoy tratando de armar tiene un entorno de construcción maestro que se ensambla en la raíz del árbol fuente con todos los CFLAGS necesarios y las definiciones de construcción que necesitamos. Me gustaría que este entorno de construcción se transmita a los archivos subConscript para que sepa que cada archivo .c
y .cpp
en nuestro árbol de compilación se está construyendo con la misma línea de comandos.
No estoy seguro de cómo hacer esto en scons, sin embargo. Están las funciones Import()
y Export()
, pero esas son básicamente variables globales feas: el archivo SConstruct llamante no tiene mucho control sobre lo que hace el archivo SConstruct secundario con la variable global Export()
'ed. ¿Hay alguna forma limpia de entregar el archivo de subConscript el entorno de construcción actual como parámetro, sin dejar que necesariamente lo modifique? Algo tal vez como:
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
sé que podría hacer algo torpe y especie de bruto como esto:
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')
¿Hay una manera elegante de hacer esto?
Actualización:
así que he jugado un poco con esto un poco más, y parece que el tiempo que hago esto en el archivo maestro 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)
y luego en somelib/SConscript
Import('env')
env.Append(CXXFLAGS=['-weirdoption1', ... ])
lib = env.StaticLibrary('somelib', source=['source1.cpp', 'source2.cpp', ...])
Return("lib")
entonces el master_env
en el SConstruct principal se deja sin contaminar. Era importante para mí que el Export(env=env.Clone())
funcionara porque no quería confiar en todos los SConscripts secundarios para hacer la seguridad (Clone() 'ing), esa política debería ser archivos SConscript/SConstruct principales.
Aún así, es un poco feo tener que tener env
como nombre de parámetro por política.
Gracias Tom. Una cosa para agregar: si 'env' no es necesariamente el segundo argumento, se puede usar la sintaxis: 'exports = 'env''. –
Desafortunadamente, esto aún deja la clonación al módulo discreción del niño, por lo que no hay garantía de la siguiente módulo que va a hacer. –