Мне нужно использовать scons для генерации релиза и отладки сборки для большого проекта. Как для релизной, так и для отладочной сборки он генерирует разделяемую и статическую библиотеку. После сборки структура каталогов должна выглядеть следующим образом:
project_dir/
|_ src
|_ include
|_ lib
|_ lib_rel
|_ lib_dbg
|_ dll
|_ dll_rel
|_ dll_dbg
Как я могу реализовать SConstruct и SConscript придерживаться вышеуказанных требований?
Реализация SConstruct:
env = Environment()
relEnv = env.clone(CCFLAGS = ['-O3', '-pthread')]
dbgEnv = env.clone(CCFLAGS = ['-O0', '-g', '-pthread')]
SConscript(dirs = 'src', name = 'SConscript', exports = {'env' : relEnv}, variant_dir = 'lib_rel', duplicate = 0)
SConscript(dirs = 'src', name = 'SConscript', exports = {'env' : dbgEnv}, variant_dir = 'lib_dbg', duplicate = 0)
Реализация src / SConscript:
Import('env')
src_list = Glob('*.cpp')
inc_list = ['dir_1/include', 'dir_2/include', 'common/include']
env.SharedLibrary(target = 'foo', source = src_list, CPP_PATH=inc_list)
env.StaticLibrary(target = 'foo', source = src_list, CPP_PATH=inc_list)
Используя приведенную выше реализацию, он может генерировать разделяемую и статическую библиотеку в папке lib_rel, а также связанные объектные файлы. Есть ли способ, которым я могу использовать вариант dir таким образом, чтобы для SharedLibrary он использовал целевой каталог как {dll / lib_rel, dll / lib_dbg} и для метода StaticLibrary он использует variable_dir как {lib / lib_rel, lib / lib_dbg}
Один из подходов, который может быть возможным, — это иметь отдельный SConscript для SharedLibrary и StaticLibrary. Но это очень типично, что для каждого метода сборки библиотеки требуются два разных файла.
Пожалуйста, предложите правильное решение для этого.
Я бы рассматривал Static-ness и Debug-ness как два измерения и вызывал SConscript четыре раза, вот так:
env = Environment()
relEnv = env.Clone(CCFLAGS = ['-O3', '-pthread'])
dbgEnv = env.Clone(CCFLAGS = ['-O0', '-g', '-pthread'])
SConscript(dirs = 'src', name = 'SConscript', exports = {'env' : relEnv, 'Library' : relEnv.StaticLibrary}, variant_dir = 'lib/lib_rel', duplicate = 0)
SConscript(dirs = 'src', name = 'SConscript', exports = {'env' : dbgEnv, 'Library' : dbgEnv.StaticLibrary}, variant_dir = 'lib/lib_dbg', duplicate = 0)
SConscript(dirs = 'src', name = 'SConscript', exports = {'env' : relEnv, 'Library' : relEnv.SharedLibrary}, variant_dir = 'dll/dll_rel', duplicate = 0)
SConscript(dirs = 'src', name = 'SConscript', exports = {'env' : dbgEnv, 'Library' : dbgEnv.SharedLibrary}, variant_dir = 'dll/dll_dbg', duplicate = 0)
Конечно, это ужасно, поэтому я бы использовал цикл:
env = Environment()
relEnv = env.Clone(CCFLAGS = ['-O3', '-pthread'])
dbgEnv = env.Clone(CCFLAGS = ['-O0', '-g', '-pthread'])
for env, envPath in ((relEnv, 'rel'), (dbgEnv, 'dbg')):
for lib, libPath in ((env.StaticLibrary, 'lib'), (env.SharedLibrary, 'dll')):
SConscript(dirs = 'src',
name = 'SConscript',
exports = {'env' : env, 'Library' : lib},
variant_dir = '{libPath}/{libPath}_{envPath}'.format(**locals()),
duplicate = 0)
SConscript необходимо импортировать Library
, конечно:
Import('env', 'Library')
src_list = Glob('*.cpp')
inc_list = ['dir_1/include', 'dir_2/include', 'common/include']
Library(target = 'foo', source = src_list, CPP_PATH=inc_list)
SConstruct
env = Environment()
relEnv = env.clone(CCFLAGS = ['-O3', '-pthread')]
dbgEnv = env.clone(CCFLAGS = ['-O0', '-g', '-pthread')]
SConscript(dirs = 'src', name = 'SConscript', exports = {'env' : relEnv, 'BUILD_TYPE'='rel'}, variant_dir = 'lib_rel', duplicate = 0)
SConscript(dirs = 'src', name = 'SConscript', exports = {'env' : dbgEnv, 'BUILD_TYPE'='dbg'}, variant_dir = 'lib_dbg', duplicate = 0)
SConscript
Import('env')
src_list = Glob('*.cpp')
inc_list = ['dir_1/include', 'dir_2/include', 'common/include']
env.SharedLibrary(target = '#/lib/lib_${BUILD_TYPE}/foo', source = src_list, CPP_PATH=inc_list)
env.StaticLibrary(target = '#/lib/lib_${BUILD_TYPE}/foo', source = src_list, CPP_PATH=inc_list)
Должно сработать. Не пробовал это.