SCons:使用分层构建单独调试/发布构建目录

Pav*_*vel 4 scons

我刚开始学习使用SCons,期待它解决了我的一些问题.我正在创建一个源层次结构来理解SCons的基础知识.

让我们从这个文件夹结构开始:

  • test/foo:包含main.cpp,main.h
  • test/bar:包含自己的main.cpp,main.h
  • test/common:包含foo和bar使用的utils.cpp和utils.h
  • test/external/moo:一些外部库的源代码,包含'configure',它产生'Makefile'(不使用SCons),所以SCons需要在'configure'之后调用'make'; 我怀疑使用构建目录时这部分可能会很棘手
  • test/build/debug:为调试构建dir
  • test/build/release:build dir for release

这是我想做的事情:

  • 有两种类型的构建: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'])
    
    Run Code Online (Sandbox Code Playgroud)

上面的基本SConstruct/SConscript文件会是什么样的?即使只是正确方向的指针也会很棒!

提前致谢 :-)

ric*_*chq 6

我这样做是为了多个平台的构建(而不是调试/发布),但概念是相同的.基本思想是项目根目录中需要2个文件 - 一个SConstruct来设置构建目录(或者在scons中已知的"变体目录"),然后是描述实际构建步骤的SConscript.

在SConstruct文件中,您将指定variant目录及其相应的源目录:

SConscript(dirs='.',
           variant_dir=variant_dir,
           duplicate=False,
           exports="env")
Run Code Online (Sandbox Code Playgroud)

现在你想要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")
Run Code Online (Sandbox Code Playgroud)

AddOption是最容易使用的,但是如果你使用Variables,那么你可以在运行之间缓存结果,而不是每次都拼出"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...
Run Code Online (Sandbox Code Playgroud)

这是我发现设置不同构建目录而不会出现奇怪错误的最简单方法.它也非常灵活 - 您可以通过修改顶级脚本中的"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'])
Run Code Online (Sandbox Code Playgroud)

当前工作目录位于构建层次结构中的某个位置时,从源目录运行配置步骤是不方便的.make步骤不那么混乱,但仍需要了解当前的构建目录.由于您指定"libmoo.a"作为make步骤的输出,libmoo.a作为程序的输入,所有依赖项Just Work,因此并行构建工作正常.并行构建只会在您过多地捏造依赖项时才会崩溃.