2011-11-22 10 views
5

Piszę funkcję Pythona taką jak zamiana ciągów znaków i wywoływana w scons skrypt.SCONS: Jak wywołać samookreśloną funkcję Pythona w skrypcie scons i wykonać prawidłą zależność

def Replace(env, filename, old, new): 
    with open(filename,"r+") as f: 
    d = f.read() 
    d = d.replace(old, new) 
    f.truncate(0) 
    f.seek(0) 
    f.write(d) 
    f.close() 
env.AddMethod(Replace,'Replace') 

W SConscript

lib = env.SharedLibrary('lib', object, extra_libs) 
tmp = env.Command([],[],[env.Replace(somefile, 'A', 'b')]) 
env.Depends(tmp,lib) 

czego oczekuję, to uruchomienie metody replace() po lib zbudowany. ale scons zawsze uruchamiaj Replace() w pierwszej rundzie parsowania frazy. Wygląda na to, że brakuje mi zależności.

Odpowiedz

4

Uważam, że prawdopodobnie szukasz builders that execute python functions.

Trudne jest to, że SCons tak naprawdę nie chce pracować w taki sposób, w jaki go zmusisz. Działania budujące powinny być powtarzalne i nieniszczące, w kodzie faktycznie niszczysz oryginalną zawartość somefile. Zamiast tego możesz użyć paradygmatu docelowego/źródłowego i jakiegoś pliku szablonu, aby osiągnąć ten sam wynik.

import os 
import re 

def replace_action(target, source, env): 
    # NB. this is a pretty sloppy way to write a builder, but 
    #  for things that are used internally or infrequently 
    #  it should be more than sufficient 
    assert(len(target) == 1) 
    assert(len(source) == 1) 
    srcf = str(source[0]) 
    dstf = str(target[0]) 
    with open(srcf, "r") as f: 
     contents = f.read() 
     # In cases where this builder fails, check to make sure you 
     # have correctly added REPLST to your environment 
     for old, new in env['REPLST']: 
      contents = re.sub(old, new, contents) 
     with open(dstf, "w") as outf: 
      outf.write(contents) 

replace_builder = Builder(action = replace_action) 

env = Environment(ENV = os.environ) 
env.Append(BUILDERS = {'Replace' : replace_builder }) 
b = env.Replace('somefile', ['somefile.tmpl'], REPLST=[('A','b')]) 
lib = env.SharedLibrary('lib', object + [b], extra_libs) 

Należy zauważyć, że w moich testów, funkcja zastąpić nie grał ładnie z danymi multi-line, więc ja tylko zamieniłem do korzystania z pełnych wyrażeń regularnych (re.sub). Jest to prawdopodobnie wolniej, ale oferuje znacznie większą elastyczność.

Powiązane problemy