recetas - scons los petersen
Cómo evitar “scons: warning: se especificaron dos entornos diferentes para el objetivo” (4)
Crear una biblioteca estática a partir del primer conjunto de archivos y vincular la biblioteca al siguiente conjunto de archivos (que tienen algunos archivos en común con el primer conjunto) para crear un trabajo objetivo también.
env.StaticLibrary ("a", ["a.c","util.c"], LIBS = "m")
env.Program ("b", ["b.c","util.c"], LIBS = ["c","a"])
Supongamos que tengo un archivo SConstruct
que se ve así:
env = Environment()
env.Program("a", ["a.c", "util.c"])
env.Program("b", ["b.c", "util.c"])
Esta compilación funciona correctamente sin mensajes de advertencia de SCons. Sin embargo, si modifico esto para especificar diferentes bibliotecas para cada compilación del Program
(las bibliotecas reales no son relevantes):
env.Program("a", ["a.c", "util.c"], LIBS="m")
env.Program("b", ["b.c", "util.c"], LIBS="c")
entonces me sale la advertencia:
scons: warning: Two different environments were specified for target util.o, but they appear to have the same action: $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES
Esto parece deberse a que el creador del Program
crea automáticamente un nuevo entorno para generar las fuentes , aunque solo la variable LIBS
es diferente (y por lo tanto, solo el paso del enlace debe tener un entorno diferente). Puedo solucionar esto haciendo algo como:
util = env.Object("util.c")
env.Program("a", ["a.c"] + util, LIBS="m")
env.Program("b", ["b.c"] + util, LIBS="c")
Esto utiliza un único generador de Object
para util.c
, luego usar el archivo de objetos precompilados en cada compilación del Program
, evitando así la advertencia. Sin embargo, esto no debería ser realmente necesario. ¿Hay una manera más elegante de solucionar este problema? ¿O es esto realmente un error en SCons que debería ser arreglado?
Contexto: Tengo casi 2000 archivos fuente en C compilados en aproximadamente 20 bibliotecas y 120 ejecutables con muchas fuentes compartidas. SConstruct
archivo SConstruct
del sistema de compilación propietario anterior utilizando un script de conversión que escribí. Hay alrededor de 450 mensajes de advertencia "Dos entornos diferentes" producidos por SCons para una compilación completa usando mi actual SConstruct
.
Encontré una solución que no implica la creación de variables adicionales para contener los nodos del archivo de objeto:
env.Program("a", ["a.c", env.Object("util.c")], LIBS="m")
env.Program("b", ["b.c", env.Object("util.c")], LIBS="c")
Esto aísla la construcción de util.c
dentro de un solo entorno. Aunque se especifica dos veces, una para cada Program
, SCons no advierte sobre esto porque es la misma fuente creada con el mismo objeto env
. Por supuesto, SCons solo compila la fuente una vez en este caso.
Puede usar la función Dividir y un asistente personalizado para simplificar el proceso de construcción para proyectos grandes:
def create_objs(SRCS, path=""):
return [env.Object(path+src+".cpp") for src in SRCS]
prg1 = Split("file_1 file_2 file_N")
prg2 = Split("file_2 file_5 file_8")
env.Program("a", create_objs(prg1), LIBS="x")
env.Program("b", create_objs(prg2), LIBS="y")
Los archivos de objetos se crean una sola vez y se pueden usar en varias compilaciones. Espero que esto ayude...
Un problema que encontré en mi código fue que no estaba usando la ruta del objeto de destino correctamente. O en otras palabras, tenía una directiva direccional variante, pero en lugar de usar BUILDPATH terminé usando mi ruta de código fuente original. De esta manera, Scons estaba encontrando el objeto generado en el destino BUILDPATH y la ruta de origen.