我刚开始学习使用SCons,期待它解决了我的一些问题。我正在创建一个源层次结构来理解SCons的基础知识。
让我们从这个文件夹结构开始:
这是我想做的事情:
有两种类型的构建:debug / release,唯一的区别是debug指定-DDEBUG到g ++
使用构建目录,以便在源树中不创建.o文件。让我们将这些构建目录称为“构建/调试”和“构建/发布”
能够调用./configure并在另一个不使用SCons的项目上创建,然后链接它生成的libmoo.a
让构建完全平行(scons -j9为8核?)
有一些与调试/发布无关的方法来指定要链接的库。类似的东西:
env.Program(target='foo', source=['foo/main.cpp', '#build/(DEBUG_OR_RELEASE)/lib/libsomething.a'])
上面的基本SConstruct / SConscript文件会是什么样的?即使只是正确方向的指针也会很棒!
提前致谢: - )
答案 0 :(得分:6)
我为多个平台的构建(而不是调试/发布)执行此操作,但概念是相同的。基本思想是在项目根目录中需要2个文件 - 一个用于设置构建目录的SConstruct(或者在scons中已知的“变体目录”),然后是描述实际构建步骤的SConscript。
在SConstruct文件中,您可以指定variant目录及其相应的源目录:
SConscript(dirs='.',
variant_dir=variant_dir,
duplicate=False,
exports="env")
现在你想要variant_dir依赖于一个标志。您可以使用AddOption或Variables来执行此操作。以下是完成顶级SConstruct的一个示例:
# build with `scons --debug-build` for debug.
AddOption(
'--debug-build',
action='store_true',
help='debug build',
default=False)
env = Environment()
if GetOption('debug_build'):
env.ParseFlags('-DDEBUG')
variant_dir = 'build/debug'
else:
variant_dir = 'build/release'
SConscript(dirs='.',
variant_dir=variant_dir,
duplicate=False,
exports="env")
AddOption是最容易使用的,但是如果你使用变量,那么你可以在运行之间缓存结果,而不是每次都拼出“scons --debug-build”。
所有目录设置和相关的cruft都在SConstruct中。现在SConscript文件非常简单,根本不需要担心构建目录。
Import('env')
env.Program(target='foo_prog', source=['foo/main.cpp', 'lib/libmoo.a'])
# foo_prog since foo already exists as the name of the directory...
这是我发现设置不同构建目录而不会出现奇怪错误的最简单方法。它也非常灵活 - 您可以通过修改顶级脚本中的“env”来添加不同的平台构建,而无需更改构建的实际内容。
你问题中唯一正在使用的扳手是直接从SCons编译autoconf风格项目的方法。最简单的方法可能是使用几个Command()调用,但是SCons喜欢了解每个步骤的输入和输出,所以这可能会变得很棘手。此外,您必须依赖具有正确VPATH设置的autoconf构建 - 如果您尝试在源树外部进行编译,则某些项目不起作用。无论如何,编译autoconf项目的方法是这样的:
import os
Import('env')
# get the path to the configure script from the "moo" source directory
conf = env.File('moo/configure').srcnode().abspath
# Create the "moo" build directory in the build dir
build_dir = env.Dir('.').path
moo_dir = os.path.join(build_dir, 'moo')
Mkdir(moo_dir)
# run configure from within the moo dir
env.Command('moo/Makefile', 'moo/Makefile.am',
conf, chdir=moo_dir)
# run make in the moo dir
env.Command('moo/libmoo.a', 'moo/Makefile',
'make', chdir=moo_dir)
env.Program(target='foo_prog', source=['foo/main.cpp', 'moo/libmoo.a'])
当源工作目录位于构建层次结构中的某个位置时,从源目录运行配置步骤是不方便的。 make步骤不那么混乱,但仍需要了解当前的构建目录。由于您指定“libmoo.a”作为make步骤的输出,libmoo.a作为程序的输入,所有依赖项Just Work,因此并行构建工作正常。当您过多地捏造依赖关系时,并行构建只会中断。
答案 1 :(得分:1)
我知道这是一个老问题,我只想添加一个替代方案:
在sconstruct
文件(父级)中,我们定义一个名为ListVariable
的{{1}},其中包含我们允许的变体列表(例如variants
)。< / p>
然后,为了能够知道['release', 'debug']
文件中的当前变体,我们只是循环我们定义的选项并将其导出到sconscript
。
我使用sconscript
作为变量名称来表示全局环境:
genv
在# sconstruct
opts = Variables()
opts.AddVariables(
ListVariable('variants', 'list of variants to build', 'all', names = ['debug','release']),
)
genv = Environment( options = opts )
for variant in genv['variants']:
SConscript('sconscript', exports=['genv', 'variant'], variant_dir='#build/'+variant, duplicate=False)
文件中我们sconscript
de Clone
我们可以使用genv
变量在本地环境variant
中进行设置:
env
使用# sconscript
Import('*')
import os.path
env = genv.Clone()
if variant == 'debug':
env.Append( CPPFLAGS = ['/Zi'])
src = 'src/hello.cpp'
app,ext = os.path.splitext(os.path.basename(src))
obj = env.Object ('obj/'+app, src)
bin = env.Program('bin/'+app, obj)
可以拨打
ListVariable
或
scons variants=release
或
scons variants=debug
最后一个命令(和默认命令)构建所有变体。
答案 2 :(得分:0)
在SCons Wiki中定义多种构建模式('debug','release')有一个很好的解决方案:
http://www.scons.org/wiki/SconstructMultiple
这就是richq SConstruct文件的样子:
#get the mode flag from the command line
#default to 'release' if the user didn't specify
mymode = ARGUMENTS.get('mode', 'release')
#check if the user has been naughty: only 'debug' or 'release' allowed
if not (mymode in ['debug', 'release']):
print "Error: expected 'debug' or 'release', found: " + mymode
Exit(1)
#tell the user what we're doing
print '**** Compiling in ' + mymode + ' mode...'
env = Environment()
if mode == 'debug':
env.Append(CPPDEFINES = ['DEBUG'])
variant_dir = 'build/debug'
else:
variant_dir = 'build/release'
SConscript(dirs = '.', variant_dir = variant_dir, duplicate = False, exports = "env")
然后,您可以致电scons mode=release
(或仅scons
,因为发布是默认模式)或scons mode=debug
。