c++ - ¿Cómo puedo obtener proyectos para colocar su salida de compilación en el mismo directorio con Scons?
build (2)
Ok, el tercer intento es un encanto. Solo estoy colocando esto en una nueva respuesta para mantenerlo más limpio. Hablé con mi gurú scons local, y afirmó que el método de instalación debería funcionar, pero que hay una manera mucho más sencilla.
Simplemente defina la ruta completa a la que desea que vaya el ejecutable (o dll). Asi que:
prj2_env.Program(target = os.path.join(BIN_DIR,PROG), source = SOURCES )
Si no desea tener que hacer esto en todos los lugares, puede realizar una función global:
def PrefixProgram(env, trgt, srcs):
env.Program(target = os.path.join(env.["MY_OUTPUT_DIR"], trgt), source = srcs)
Luego, en su SCONScript, algo como:
import (''PrefixProgram'')
# stuff ...
PrefixProgram(prj2_env, PROG, SOURCES)
Tenga en cuenta que puede agregar su propio atributo al entorno, que es donde
env["MY_OUTPUT_DIR"]
viene de. Lo escribí de la manga, así que espere algunos errores de sintaxis menores y lo que no. Obviamente, puede aplicar el mismo truco para bibliotecas compartidas y estáticas.
Con el interés de la revelación completa, le ofrecí a mi gurú scons local la oportunidad de responder él solo, pero tenía miedo de que se volviera adicto al sitio y lo rechazara. :)
Fondo
Estoy probando Scons configurando un proyecto de muestra básico de C ++ que tiene dos subproyectos:
- Prj1 es un EXE que depende de Prj2
- Prj2 es una DLL que exporta algunas funciones
El problema al que me estoy enfrentando es que la biblioteca crea sus archivos .obj, .pdb, .lib, .dll, etc. en el mismo directorio que su archivo SConscript mientras el EXE crea sus archivos en el mismo directorio que SConscript. La aplicación construye con éxito tanto la dependencia Prj2 como ella misma. Sin embargo, no puede ejecutar el EXE resultante porque no puede encontrar la biblioteca que necesita porque está en el otro directorio.
Pregunta
¿Cómo puedo obtener múltiples proyectos que tienen dependencias para generar sus binarios y depurar información en un directorio común para que puedan ser ejecutados y depurados?
Soluciones potenciales
Esto es lo que he pensado hasta ahora:
- Traté de usar VariantDir (anteriormente llamado BuildDir) sin embargo, esto no parece funcionar. Quizás estoy estropeando algo aquí.
- Podría decirle al compilador y al enlazador explícitamente (a través de Fo / Fd por ejemplo) dónde soltar sus archivos (¿es esta la mejor o la única solución?)
- Ejecute un comando de copia en los binarios resultantes (esto parece un truco y un gran dolor para administrar / mantener)
Actualizar
Actualicé la estructura del archivo y el contenido del archivo a continuación para reflejar la solución de trabajo en su totalidad. Gracias a la pena por su visión.
Mando
Con esta configuración, desafortunadamente debe ejecutar la compilación haciendo clic en el directorio de compilación y luego ejecutando el siguiente comando. Necesito tener una configuración de alias que funcione correctamente para evitar esto.
build> scons ../bin/project1.exe
Estructura de archivo
/scons-sample
/bin
/release
/debug
/build
SConstruct
scons_helper.py
/prj1
SConscript
/include
/src
main.cpp
/prj2
SConscript
/include
functions.h
/src
functions.cpp
SConstruct
import os.path
BIN_DIR = ''../bin''
OBJ_DIR = ''./obj''
#--------------------------------------
# CxxTest Options
#--------------------------------------
CXXTEST_DIR = ''../extern/CxxTest/CxxTest-latest''
PERL = ''perl -w''
TESTS = ''*.h''
TESTGEN = PERL + CXXTEST_DIR + ''/cxxtestgen.pl''
CXXTESTGEN_FLAGS = ''--runner=ParenPrinter /
--abort-on-fail /
--have-eh''
#--------------------------------------
# Options
#--------------------------------------
SetOption( ''implicit_cache'', 1 )
# command line options
opts = Options()
opts.AddOptions(
EnumOption(
''debug'',
''Debug version (useful for developers only)'',
''no'',
allowed_values = (''yes'', ''no''),
map = { },
ignorecase = 1
)
)
#--------------------------------------
# Environment
#--------------------------------------
env = Environment(
options = opts,
#--------------------------------------
# Linker Options
#--------------------------------------
LIBPATH = [
''../extern/wxWidgets/wxWidgets-latest/lib/vc_dll''
],
LIBS = [
# ''wxmsw28d_core.lib'',
# ''wxbase28d.lib'',
# ''wxbase28d_odbc.lib'',
# ''wxbase28d_net.lib'',
''kernel32.lib'',
''user32.lib'',
''gdi32.lib'',
''winspool.lib'',
''comdlg32.lib'',
''advapi32.lib'',
''shell32.lib'',
''ole32.lib'',
''oleaut32.lib'',
''uuid.lib'',
''odbc32.lib'',
''odbccp32.lib''
],
LINKFLAGS = ''/nologo /subsystem:console /incremental:yes /debug /machine:I386'',
#--------------------------------------
# Compiler Options
#--------------------------------------
CPPPATH = [
''./include/'',
''../extern/wxWidgets/wxWidgets-latest/include'',
''../extern/wxWidgets/wxWidgets-latest/vc_dll/mswd''
],
CPPDEFINES = [
''WIN32'',
''_DEBUG'',
''_CONSOLE'',
''_MBCS'',
''WXUSINGDLL'',
''__WXDEBUG__''
],
CCFLAGS = ''/W4 /EHsc /RTC1 /MDd /nologo /Zi /TP /errorReport:prompt''
)
env.Decider( ''MD5-timestamp'' ) # For speed, use timestamps for change, followed by MD5
Export( ''env'', ''BIN_DIR'' ) # Export this environment for use by the SConscript files
#--------------------------------------
# Builders
#--------------------------------------
SConscript( ''../prj1/SConscript'' )
SConscript( ''../prj2/SConscript'' )
Default( ''prj1'' )
scons_helper.py
import os.path
#--------------------------------------
# Functions
#--------------------------------------
# Prepends the full path information to the output directory so that the build
# files are dropped into the directory specified by trgt rather than in the
# same directory as the SConscript file.
#
# Parameters:
# env - The environment to assign the Program value for
# outdir - The relative path to the location you want the Program binary to be placed
# trgt - The target application name (without extension)
# srcs - The list of source files
# Ref:
# Credit grieve and his local SCons guru for this:
# http://stackoverflow.com/questions/279860/how-do-i-get-projects-to-place-their-build-output-into-the-same-directory-with
def PrefixProgram(env, outdir, trgt, srcs):
env.Program(target = os.path.join(outdir, trgt), source = srcs)
# Similar to PrefixProgram above, except for SharedLibrary
def PrefixSharedLibrary(env, outdir, trgt, srcs):
env.SharedLibrary(target = os.path.join(outdir, trgt), source = srcs)
def PrefixFilename(filename, extensions):
return [(filename + ext) for ext in extensions]
# Prefix the source files names with the source directory
def PrefixSources(srcdir, srcs):
return [os.path.join(srcdir, x) for x in srcs]
SConscript para Prj1
import os.path
import sys
sys.path.append( ''../build'' )
from scons_helper import *
Import( ''env'', ''BIN_DIR'' ) # Import the common environment
prj1_env = env.Clone() # Clone it so we don''t make changes to the global one
#--------------------------------------
# Project Options
#--------------------------------------
PROG = ''project1''
#--------------------------------------
# Header Files
#--------------------------------------
INC_DIR = [
''../prj2/include''
]
HEADERS = [
''''
]
#--------------------------------------
# Source Files
#--------------------------------------
SRC_DIR = ''./src''
SOURCES = [
''main.cpp''
]
# Prefix the source files names with the source directory
SOURCES = PrefixSources( SRC_DIR, SOURCES )
#--------------------------------------
# Compiler and Linker Overrides
#--------------------------------------
prj1_env.Append(
CPPPATH = INC_DIR,
LIBS = ''project2'',
LIBPATH = BIN_DIR,
# Microsoft Visual Studio Specific
PDB = os.path.join( BIN_DIR, PROG + ''.pdb'' )
)
#--------------------------------------
# Builders
#--------------------------------------
PrefixProgram( prj1_env, BIN_DIR, PROG, SOURCES )
SConscript para Prj2
import os.path
import sys
sys.path.append( ''../build'' )
from scons_helper import *
Import( ''env'', ''BIN_DIR'' ) # Import the common environment
prj2_env = env.Clone() # Clone it so we don''t make changes to the global one
#--------------------------------------
# Project Options
#--------------------------------------
PROG = ''project2''
#--------------------------------------
# Header Files
#--------------------------------------
INC_DIR = [
''''
]
HEADERS = [
''functions.h''
]
#--------------------------------------
# Source Files
#--------------------------------------
SRC_DIR = ''./src/''
SOURCES = [
''functions.cpp''
]
# Prefix the source files names with the source directory
SOURCES = PrefixSources( SRC_DIR, SOURCES )
#--------------------------------------
# Compiler and Linker Overrides
#--------------------------------------
# Update the environment with the project specific information
prj2_env.Append(
CPPPATH = INC_DIR,
# Microsoft Visual Studio Specific
PDB = os.path.join( BIN_DIR, PROG + ''.pdb'' )
)
#--------------------------------------
# Builders
#--------------------------------------
PrefixSharedLibrary( prj2_env, BIN_DIR, PROG, SOURCES )
VariantDir es la forma de hacer esto. ¿Cómo llama tu Sconstruct tus archivos de Sconscript? También ha leído esta sección de la documentación: http://www.scons.org/doc/1.1.0/HTML/scons-user/c3271.html (supongo que tiene).
Cuanto más lo pienso, más creo que quieres usar una combinación de Predeterminado e Instalar
En su llamada SConscripts
env.Install("../bin", <your target exe or dll>)
luego en tu llamada Sconstruct
env.Alias(''install'', "../bin")
Default(''install'')
Eso debería ser el truco, y creo que los enlaces dejan en claro cómo funciona todo junto.