2016-10-03 6 views
0

Ich habe SConscripts, die SConscripts in allen Verzeichnissen im SConscript-Verzeichnis rekursiv aufrufen.Doppeltes Variantenverzeichnis vor dem Ausführen von SConscript

Dies funktioniert nicht mit Varianten-Builds, da das gesamte Quellverzeichnis nicht in das Variantenverzeichnis kopiert wird, bevor die SConscripts ausgewertet werden.

Beispiel

. 
├── 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) 

Alle anderen 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') 

Ausgabe

$ 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. 

Die Verzeichnisse src/a und src/b werden vor dem Aufruf von build/SConscript nicht in build/a und build/b kopiert. Daher ruft build/SConscript die Tochter SConscripts nicht auf, da diese Verzeichnisse noch nicht existieren.

Ausgang, wo die Variante Verzeichnis von SConstruct entfernt

$ 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. 

So ist es eine Möglichkeit, SCons das Quellverzeichnis zu machen duplizieren VOR Tochtergesellschaft SConscripts ausgeführt wird, oder eine Möglichkeit, die Tochtergesellschaft SConscripts in das Quellverzeichnis beziehen sich auf machen .


EDIT: Ich möchte die dynamische Generierung der Liste der Verzeichnisse behalten. Hardcoding der Verzeichnisnamen funktioniert, aber das ist keine praktikable Lösung, da die Anzahl der Verzeichnisse, die ich habe, riesig ist und sich ständig ändern wird.

+0

Ja, durch die grundlegende Einrichtung folgende wie in Kap. 14 "Hierarchische Builds" und Kap. 15 "Quell- und Build-Verzeichnisse trennen" im [UserGuide] (http://scons.org/doc/production/HTML/scons-user.html). – dirkbaechle

+0

@dirkbaechle Die Beispiele in der SCons-Dokumentation berücksichtigen nicht den Fall, in dem die Unterverzeichnisse dynamisch generiert werden, indem os.listdir() verwendet wird. Hardcoding aller Verzeichnisnamen ist keine Lösung, da die Anzahl der Verzeichnisse zunimmt. – user80551

+0

Es ist sehr wenig Wert zu tun, was Sie tun? Warum nicht einfach die oberste Ebene SConstruct gehen Sie Ihren Verzeichnisbaum und suchen Sie alle SConscripts und rufen Sie sie auf, anstatt rekursiv. – bdbaddog

Antwort

0

Basierend auf https://stackoverflow.com/a/29218216/2694385 müssen sich die SConscripts auf Dateien und Ordner beziehen, als ob sie bereits im Variantenverzeichnis vorhanden wären, obwohl dies tatsächlich nicht der Fall ist.

Die Quell- und Variantenverzeichnisse können in der Umgebung gespeichert werden, und jeder SCONScript kann den Pfad zum entsprechenden Quellverzeichnis (basierend auf seiner Tiefe im Variantenverzeichnis) finden.

Die modifizierten Dateien sind

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) 

Alle 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') 
Verwandte Themen