运行SConscript之前复制变体目录

时间:2016-10-03 07:18:41

标签: scons

我有SConscripts,它在SConscript目录中包含的所有目录中递归调用SConscripts。

这不适用于变体构建,因为在评估子SConscripts之前,不会将整个源目录复制到variant目录。

实施例

.
├── SConstruct
└── src
    ├── a
    │   ├── a.c
    │   ├── a.h
    │   ├── SConscript
    │   ├── x
    │   │   ├── ax.h
    │   │   └── SConscript
    │   └── y
    │       ├── ay.h
    │       └── SConscript
    ├── b
    │   ├── b.c
    │   ├── b.h
    │   ├── SConscript
    │   ├── x
    │   │   ├── bx.h
    │   │   └── SConscript
    │   └── y
    │       ├── by.h
    │       └── SConscript
    ├── main.c
    └── SConscript

SConstruct

env = Environment()
objects = SConscript('src/SConscript', exports=['env'], variant_dir='build')
objects = [x for x in env.Flatten(objects) if x is not None]
program = env.Program(target='prog', source=objects)

所有其他SConscripts

import os

Import('env')
env.AppendUnique(CPPPATH=[Dir('.')])
objects = SConscript(
    dirs=[name for name in os.listdir('.')
          if os.path.isdir(os.path.join('.', name))],
    exports=['env'])
objects = objects + env.Object(env.Glob('*.c'))
Return('objects')

输出

$ scons . --tree=all
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o build/main.o -c -Ibuild build/main.c
build/main.c:1:15: fatal error: a.h: No such file or directory
compilation terminated.
scons: *** [build/main.o] Error 1
+-.
  +-SConstruct
  +-build
  | +-build/SConscript
  | +-build/main.c
  | +-build/main.o
  |   +-build/main.c
  |   +-/usr/bin/gcc
  +-prog
  | +-build/main.o
  | | +-build/main.c
  | | +-/usr/bin/gcc
  | +-/usr/bin/gcc
  +-src
    +-src/SConscript
    +-src/main.c
scons: building terminated because of errors.

在调用build / SConscript之前,src / a和src / b目录不会复制到build / a和build / b。因此,build / SConscript不会调用辅助SConscripts,因为那些目录还不存在。

从SConstruct中删除variant目录的输出

$ scons --tree=all
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o src/b/b.o -c -Isrc -Isrc/b -Isrc/b/x -Isrc/b/y -Isrc/a -Isrc/a/x -Isrc/a/y src/b/b.c
gcc -o src/a/a.o -c -Isrc -Isrc/b -Isrc/b/x -Isrc/b/y -Isrc/a -Isrc/a/x -Isrc/a/y src/a/a.c
gcc -o src/main.o -c -Isrc -Isrc/b -Isrc/b/x -Isrc/b/y -Isrc/a -Isrc/a/x -Isrc/a/y src/main.c
gcc -o prog src/b/b.o src/a/a.o src/main.o
+-.
  +-SConstruct
  +-prog
  | +-src/b/b.o
  | | +-src/b/b.c
  | | +-src/b/b.h
  | | +-src/b/x/bx.h
  | | +-src/b/y/by.h
  | | +-/usr/bin/gcc
  | +-src/a/a.o
  | | +-src/a/a.c
  | | +-src/a/a.h
  | | +-src/a/x/ax.h
  | | +-src/a/y/ay.h
  | | +-/usr/bin/gcc
  | +-src/main.o
  | | +-src/main.c
  | | +-src/a/a.h
  | | +-src/b/b.h
  | | +-/usr/bin/gcc
  | +-/usr/bin/gcc
  +-src
    +-src/SConscript
    +-src/a
    | +-src/a/SConscript
    | +-src/a/a.c
    | +-src/a/a.h
    | +-src/a/a.o
    | | +-src/a/a.c
    | | +-src/a/a.h
    | | +-src/a/x/ax.h
    | | +-src/a/y/ay.h
    | | +-/usr/bin/gcc
    | +-src/a/x
    | | +-src/a/x/SConscript
    | | +-src/a/x/ax.h
    | +-src/a/y
    |   +-src/a/y/SConscript
    |   +-src/a/y/ay.h
    +-src/b
    | +-src/b/SConscript
    | +-src/b/b.c
    | +-src/b/b.h
    | +-src/b/b.o
    | | +-src/b/b.c
    | | +-src/b/b.h
    | | +-src/b/x/bx.h
    | | +-src/b/y/by.h
    | | +-/usr/bin/gcc
    | +-src/b/x
    | | +-src/b/x/SConscript
    | | +-src/b/x/bx.h
    | +-src/b/y
    |   +-src/b/y/SConscript
    |   +-src/b/y/by.h
    +-src/main.c
    +-src/main.o
      +-src/main.c
      +-src/a/a.h
      +-src/b/b.h
      +-/usr/bin/gcc
scons: done building targets.

有没有办法让SCons在运行辅助SConscripts之前复制源目录,或者让辅助SConscripts引用源目录。

编辑:我想保持动态生成目录列表。硬编码目录名称有效,但这不是一个可行的解决方案,因为我拥有的目录数量很大并且会不断变化。

1 个答案:

答案 0 :(得分:0)

基于https://stackoverflow.com/a/29218216/2694385,SConscripts必须引用文件和文件夹,就好像它们已经在变体目录中一样,即使它们实际上也不是。

源和变体目录可以保存在环境中,每个SConscript都可以找到相应源目录的路径(基于变体目录中的深度)。

修改过的文件是

SConstruct

import os

env = Environment()
env['VARIANT_DIR'] = Dir("build")
env['SOURCE_DIR'] = Dir("src")
objects = SConscript(os.path.join(env['SOURCE_DIR'].path, 'SConscript'),
                     exports=['env'],
                     variant_dir=env['VARIANT_DIR'])
objects = [x for x in env.Flatten(objects) if x is not None]
program = env.Program(target='prog', source=objects)

所有SConscripts

import os

Import('env')
env.AppendUnique(CPPPATH=[Dir('.')])

dir_depth_from_variant = env['VARIANT_DIR'].rel_path(Dir('.'))
corresponding_src_dir = os.path.join(Dir('.').rel_path(env['SOURCE_DIR']),
                                     dir_depth_from_variant)
dirs = [name for name in os.listdir(corresponding_src_dir)
        if os.path.isdir(os.path.join(corresponding_src_dir, name))]
objects = SConscript(
    dirs=dirs,
    exports=['env'])
objects = objects + env.Object(env.Glob('*.c'))
Return('objects')