2012-12-19 22 views
7

Birden çok hedefi (SConscript içinde bilinmeyen numara) oluşturmak için SCons almaya çalışıyorum. Bunların her birini istediğim için ben içeriği headers/ dizinden dosyaları almak üzerine SConscript dayandırarak headers_list.txt okumak istiyorum ŞimdiDeğişken hedef sayısı oluşturmak için SCons

headers/ 
    Header1.h 
    Header2.h 
    Header3.h 
    Header4.h 
meta/ 
    headers_list.txt 

(yani sadece Header1 ve Header3 içerebilir):

ben gibi dizin var bazı işlevleri kullanarak kaynak oluşturmak için.

ben bunu env.Command kullanmaya çalışıyorlar, ama meselenin env.Command çağrılırken bilinen nedenlerle bilinmemektedir hedefler listesini belirtmek için arayan gerektirir.

for header in parse(headers_file): 
    source = mangle_source_name_for_header(header) 
    env.Command(source, header, generator_action) 

Ama bu ben scons çağırmak her zaman parse(headers_file) çalışıyor olması anlamına geliyor: Aklıma

tek şey çalışıyor. Ayrıştırma maliyetli ve dosya genellikle değiştirilmezse, bu adım kolayca önbelleğe alınabilir.

Hangi önbelleklemeye ulaşmak için eksik SConsc yapı/sınıf/teknik var?

düzenleme:

Benim soru Build-time determination of SCons targets benzer görünüyor, ama yapay kukla dosyası olmadan bir teknik yok?

Ayrıca, geçici bir dosyada bile,değişkeni Command değişkeninden geçirip, bunların üzerinde yinelenen ikinci hedefe farklı sayıda hedef oluşturduğumu görmüyorum.

düzenlemek 2:

This umut verici görünüyor.

cevap

3

Bunu yapabileceğimin tek yolu, emitter ile.Örneğin Aşağıda 3 dosyadan oluşur:

./ 
|-SConstruct 
|-src/ 
| |-SConscript 
| |-source.txt 
|-build/ 

SConstruct

env = Environment() 

dirname = 'build' 
VariantDir(dirname, 'src', duplicate=0) 

Export('env') 

SConscript(dirname+'/SConscript') 

src/SConscript

Import('env') 

def my_emitter(env, target, source): 
    data = str(source[0]) 
    target = [] 
    with open(data, 'r') as lines: 
     for line in lines: 
      line = line.strip() 
      name, contents = line.split(' ', 1) 
      if not name: continue 

      generated_source = env.Command(name, [], 'echo "{0}" > $TARGET'.format(contents)) 
      source.extend(generated_source) 
      target.append(name+'.c') 

    return target, source 

def my_action(env, target, source): 
    for t,s in zip(target, source[1:]): 
     with open(t.abspath, 'w') as tf: 
      with open(s.abspath, 'r') as sf: 
       tf.write(sf.read()) 

SourcesGenerator = env.Builder(action = my_action, emitter = my_emitter) 
generated_sources = SourcesGenerator(env, source = 'source.txt') 

lib = env.Library('functions', generated_sources) 

src/source.txt

a int a(){} 
b int b(){} 
c int c(){} 
d int d(){} 
g int g(){} 

Çıktı:

$ scons 
scons: Reading SConscript files ... 
scons: done reading SConscript files. 
scons: Building targets ... 
echo "int a(){}" > build/a 
echo "int b(){}" > build/b 
echo "int c(){}" > build/c 
echo "int d(){}" > build/d 
echo "int g(){}" > build/g 
my_action(["build/a.c", "build/b.c", "build/c.c", "build/d.c", "build/g.c"], ["src/source.txt", "build/a", "build/b", "build/c", "build/d", "build/g"]) 
gcc -o build/a.o -c build/a.c 
gcc -o build/b.o -c build/b.c 
gcc -o build/c.o -c build/c.c 
gcc -o build/d.o -c build/d.c 
gcc -o build/g.o -c build/g.c 
ar rc build/libfunctions.a build/a.o build/b.o build/c.o build/d.o build/g.o 
ranlib build/libfunctions.a 
scons: done building targets. 

Ayrıca, bu her scons yürütme ile headers_list.txt arasında ayrıştırma I gerçekten sevmiyorum bir şey vardır. Sadece dosya değiştiyse onu ayrıştırmanın bir yolu olmalı diye düşünüyorum. El ile önbelleğe alabilirim, ama yine de SCons'un benim için önbelleğe almasını sağlayan bir numara olduğunu umuyorum.

Ve dosyaları çoğaltmanın bir yolunu bulamadım (a ve a.c aynıdır). Tek yol, kaynak yerine my_action'da kütüphane oluşturmaktır (bu, son çözümümde kullandığım yaklaşımdır).

İlgili konular