如何使用多个使用存储库的SConstruct文件从树中的不同位置构建?

时间:2017-03-14 17:59:12

标签: build scons

我有以下目录结构:

root/
  SConstruct
  item0/
    SConstruct
    unit0/
      unit0.h
      private/
        unit0.c
      test/
        test_unit0.c
        SConstruct
        SConscript
    unit1/
      (repeat unit0 structure)
  item1/
    (repeat item0 structure)

我希望能够从root运行scons来构建它下面的所有内容,并从root/item0运行以构建它下面的所有内容等等。

顶级SConstruct看起来像:

SConscript('item0/SConstruct', duplicate=0)
SConscript('item1/SConstruct', duplicate=0)

项目级别SConstruct:

SConscript('unit0/SConstruct', duplicate=0)
SConscript('unit1/SConstruct', duplicate=0)

单元级SConstruct:

import os

proj_root = os.path.abspath('../../../../..')
proj_shared_path = os.path.join(proj_root,
    os.path.normpath('trunk/sys/shared'))

env = Environment()
SConscript(
    'SConscript',
    variant_dir='output',
    exports=['env', 'proj_shared_path'],
    duplicate=0)

单元级SConscript(仅限重要的东西):

Import('*')
# Setup Repositories to access out-of-current-directory-tree files.
lib1_path = os.path.join(proj_shared_path, 'lib1')
env.Repository('#/../private', lib1_path)

# Set general compilation and link flags.
env.Append(
    CFLAGS = '-Wall -Wextra -std=c99 -pedantic',
    CPPPATH = ['#/../..', proj_shared_path])

# These are the files we don't need to run gcovr on.
non_cov_srcs = [
    'testit.c',
    'lib1.c'
    ]

# Create a 'coverage' environment to build files that we will run gcovr on.
cov = env.Clone()
cov.Append(CFLAGS = '--coverage -O0')
cov_srcs = cov.Object('unit0.c')
SideEffect('unit0.gcno', cov_srcs)

# Our unit test program combines all the sources we've listed so far.
test_exe = env.Program(
    'test_unit0',
    [cov_srcs, non_cov_srcs],
    LIBS='gcov', LINKFLAGS='--coverage')

现在,当我从root/item0/unit0/test运行scons时,这一切都正常。但是,当我从rootroot/item0运行时,我会遇到各种类型的错误,例如下面的错误(从root/item0运行):

scons: done reading SConscript files.
scons: Building targets ...
scons: *** [unit0\test\output\unit0.obj] Source 'unit0\test\unit0.c' not found, needed by target 'unit0\test\output\unit0.obj'.
scons: building terminated because of errors.

显然unit0\test\unit0.c将不会被找到,因为它不存在,但我不确定为什么scons认为它必须存在,因为存储库被定义为'#/../private'并且没有私有信息显示在错误消息中。

编辑我发现它可能正在寻找unit0\test\unit0.c,因为unit0\testSConscript的“根”目录。我还猜测#/../private Repository位置仅在从scons运行unit0\test时才是正确的。但是,当我尝试以任何其他方式指定Repository时(包括使用os.path.abspath构建的绝对路径(并验证为正确)),scons似乎仍然不想要在那里寻找unit0.c。那是为什么?

1 个答案:

答案 0 :(得分:0)

在#scons IRC频道的@bdbaddog的帮助下,我能够确定以下内容:

  1. 我实际上想要实现的是确保每个来源的构建工件最终都在我的variant_dir
  2. SConstructSConscript位于同一目录中时,Repository在从unit0/test目录构建时最终实现了此目的。但是,我不知道为什么。
  3. 要正确实现(1),Repository不是正确的工具。相反,SConscript应如下所示:

    Import('*')
    
    # Set general compilation and link flags.
    env.Append(
        CFLAGS = '-Wall -Wextra -std=c99 -pedantic',
        CPPPATH = ['#/item0', '#/lib1'])
    
    # These are the files we don't need to run gcovr on.
    non_cov_objs = [
        Object(target='testit', source='testit.c'),
        Object(target='lib1', source='#/lib1/lib1.c'
        ]
    
    # Create a 'coverage' environment to build files that we will run gcovr on.
    cov = env.Clone()
    cov.Append(CFLAGS = '--coverage -O0')
    cov_objs = cov.Object(
        target='unit0', 
        source='#/item0/unit0/private/unit0.c')
    SideEffect('unit0.gcno', cov_srcs)
    
    # Our unit test program combines all the sources we've listed so far.
    test_exe = env.Program(
        'test_unit0',
        [cov_objs, non_cov_objs],
        LIBS='gcov', LINKFLAGS='--coverage')
    

    通过为每个target指定sourceObject,我可以根据{{1}中生成的目标文件(以及其他副作用)实现我想要的效果}}