Как я могу получить проекты, чтобы поместить их результаты сборки в один каталог с Scons? - PullRequest
15 голосов
/ 11 ноября 2008

Фон

Я опробую Scons, настроив базовый пример проекта C ++ с двумя подпроектами:

  • Prj1 - это EXE, который зависит от Prj2
  • Prj2 - это DLL, которая экспортирует некоторые функции

Проблема, с которой я сталкиваюсь, состоит в том, что библиотека создает свои файлы .obj, .pdb, .lib, .dll и т. Д. В том же каталоге, что и файл SConscript, а EXE создает свои файлы в том же каталоге, что и файл. его SConscript. Приложение успешно строит как зависимость Prj2, так и себя. Однако вы не можете запустить полученный EXE, потому что он не может найти нужную ему библиотеку, потому что он находится в другом каталоге.

Вопрос

Как получить несколько проектов с зависимостями для вывода их двоичных файлов и отладочной информации в общий каталог, чтобы их можно было выполнять и отлаживать?

Потенциальные решения

Это то, о чем я думал до сих пор:

  • Я пытался использовать VariantDir (ранее назывался BuildDir), но, похоже, это не работает. Возможно, я что-то здесь испортила.
  • Потенциально я мог бы явно указать компилятору и компоновщику (например, через Fo / Fd), куда их файлы сбрасывать (это лучшее или единственное решение ???)
  • Выполнить команду копирования в полученных двоичных файлах (это выглядит как хак и довольно сложно управлять / поддерживать)

Обновление

Я обновил структуру файла и содержимое файла ниже, чтобы отразить рабочее решение во всей его полноте. Спасибо, горевать за его понимание.

Команда

При такой конфигурации вы, к сожалению, должны выполнить сборку, перейдя в каталог сборки и затем выполнив следующую команду. Мне нужно правильно настроить псевдоним, чтобы обойти это.


build> scons ../bin/project1.exe

Структура файла

    /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 для 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 для 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 )

Ответы [ 2 ]

6 голосов
/ 11 ноября 2008

Хорошо. Третья попытка - это шарм. Я просто помещаю это в новый ответ, чтобы сохранить его чище. Я говорил с моим местным гуру scons, и он заявил, что метод установки должен работать, но есть гораздо более простой способ.

Просто определите полный путь, куда вы хотите, чтобы исполняемый файл (или DLL) пошел. Итак:

prj2_env.Program(target = os.path.join(BIN_DIR,PROG), source = SOURCES )

Если вы не хотите делать это везде, вы можете сделать глобальную функцию:

def PrefixProgram(env, trgt, srcs):
    env.Program(target = os.path.join(env.["MY_OUTPUT_DIR"], trgt), source = srcs)

Тогда в вашем SConscript, что-то вроде:

import ('PrefixProgram')
# stuff ...
PrefixProgram(prj2_env, PROG, SOURCES)

Обратите внимание, что вы можете добавить свой собственный атрибут в среду, где

env["MY_OUTPUT_DIR"]

взято из. Я списал это с ног на голову, так что ожидайте незначительных синтаксических ошибок, а что нет. Очевидно, вы можете применить один и тот же прием к общим и статическим библиотекам.

В интересах полного раскрытия я предложил своему местному гуру-секретарю ответить на этот вопрос сам, но он испугался, что станет зависимым от сайта и отказался. :)

3 голосов
/ 11 ноября 2008

VariantDir - способ сделать это. Как ваш Sconstruct называет ваши файлы Sconscript? Также читали ли вы этот раздел документации: http://www.scons.org/doc/1.1.0/HTML/scons-user/c3271.html (я полагаю, у вас есть).


Чем больше я думаю об этом, тем больше я думаю, что вы хотите использовать комбинацию По умолчанию и Установка

В ваших SConscripts звоните

env.Install("../bin", <your target exe or dll>)

тогда в вашем вызове Sconstruct

env.Alias('install', "../bin")
Default('install')

Это должно сработать, и я думаю, что ссылки проясняют, как все это работает вместе.

...