From b0da1037290d555e80620c89e42a1cbc380aacbd Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 16 Feb 2013 21:14:04 +0200 Subject: [PATCH] Regenerate build info if definition files change. --- builder.py | 14 ++++++-------- environment.py | 6 +++++- generators.py | 13 ++++++++++++- interpreter.py | 14 +++++++++++++- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/builder.py b/builder.py index 69c7e8805..9017be40f 100755 --- a/builder.py +++ b/builder.py @@ -51,10 +51,11 @@ parser.add_option('--strip', action='store_true', dest='strip', default=False,\ class BuilderApp(): - def __init__(self, dir1, dir2, options): + def __init__(self, dir1, dir2, script_file, options): (self.source_dir, self.build_dir) = self.validate_dirs(dir1, dir2) if options.prefix[0] != '/': raise RuntimeError('--prefix must be an absolute path.') + self.builder_script_file = script_file self.options = options def has_builder_file(self, dirname): @@ -85,13 +86,9 @@ class BuilderApp(): raise RuntimeError('Neither directory contains a builder file %s.' % environment.builder_filename) def generate(self): - code = open(os.path.join(self.source_dir, environment.builder_filename)).read() - if len(code.strip()) == 0: - raise interpreter.InvalidCode('Builder file is empty.') - assert(isinstance(code, str)) - env = environment.Environment(self.source_dir, self.build_dir, options) + env = environment.Environment(self.source_dir, self.build_dir, self.builder_script_file, options) b = build.Build(env) - intr = interpreter.Interpreter(code, b) + intr = interpreter.Interpreter(b) intr.run() if options.generator == 'shell': g = generators.ShellGenerator(b, intr) @@ -112,7 +109,8 @@ if __name__ == '__main__': dir2 = args[2] else: dir2 = '.' - builder = BuilderApp(dir1, dir2, options) + this_file = os.path.abspath(__file__) + builder = BuilderApp(dir1, dir2, this_file, options) print ('Source dir: ' + builder.source_dir) print ('Build dir: ' + builder.build_dir) os.chdir(builder.build_dir) diff --git a/environment.py b/environment.py index 3d760f190..4031d32ab 100755 --- a/environment.py +++ b/environment.py @@ -198,9 +198,10 @@ class ArLinker(): header_suffixes = ['h', 'hh', 'hpp', 'hxx', 'H'] class Environment(): - def __init__(self, source_dir, build_dir, options): + def __init__(self, source_dir, build_dir, builder_script_file, options): self.source_dir = source_dir self.build_dir = build_dir + self.builder_script_file = builder_script_file self.options = options self.scratch_dir = os.path.join(build_dir, 'builder-private') os.makedirs(self.scratch_dir, exist_ok=True) @@ -216,6 +217,9 @@ class Environment(): self.static_lib_prefix = 'lib' self.object_suffix = 'o' + def get_builder_command(self): + return self.builder_script_file + def get_c_compiler_exelist(self): ccachelist = self.detect_ccache() evar = 'CC' diff --git a/generators.py b/generators.py index 05f566670..2da5d68c9 100755 --- a/generators.py +++ b/generators.py @@ -253,7 +253,6 @@ class NinjaGenerator(Generator): datafile.write(self.get_target_filename(t.get_exe()) + '\n') datafile.close() - def generate_rules(self, outfile): outfile.write('# Rules for compiling.\n\n') self.generate_compile_rules(outfile) @@ -264,6 +263,11 @@ class NinjaGenerator(Generator): outfile.write('rule CUSTOM_COMMAND\n') outfile.write(' command = $COMMAND\n') outfile.write(' restat = 1\n\n') + outfile.write('rule REGENERATE_BUILD\n') + c = (ninja_quote(self.environment.get_builder_command()), + ninja_quote(self.environment.get_source_dir()), + ninja_quote(self.environment.get_build_dir())) + outfile.write(" command = '%s' '%s' '%s' -G ninja\n\n" % c) def generate_static_link_rules(self, outfile): static_linker = self.build.static_linker @@ -415,6 +419,13 @@ class NinjaGenerator(Generator): default = 'default all\n\n' outfile.write(build) outfile.write(default) + deps = [ ninja_quote(os.path.join(self.build_to_src, df)) \ + for df in self.interpreter.get_build_def_files()] + depstr = ' '.join(deps) + buildregen = 'build build.ninja: REGENERATE_BUILD | %s\n\n' % depstr + ignore_missing = 'build %s: phony\n\n' % depstr + outfile.write(buildregen) + outfile.write(ignore_missing) class ShellGenerator(Generator): def __init__(self, build, interp): diff --git a/interpreter.py b/interpreter.py index c353dbe03..7cc90e77c 100755 --- a/interpreter.py +++ b/interpreter.py @@ -335,8 +335,13 @@ class Test(InterpreterObject): class Interpreter(): - def __init__(self, code, build): + def __init__(self, build): self.build = build + code = open(os.path.join(build.environment.get_source_dir(),\ + environment.builder_filename)).read() + if len(code.strip()) == 0: + raise InvalidCode('Builder file is empty.') + assert(isinstance(code, str)) self.ast = bparser.build_ast(code) self.sanity_check_ast() self.variables = {} @@ -344,6 +349,7 @@ class Interpreter(): self.builtin['host'] = Host() self.environment = build.environment self.build_func_dict() + self.build_def_files = [environment.builder_filename] self.subdir = '' def build_func_dict(self): @@ -362,6 +368,9 @@ class Interpreter(): 'include_directories' : self.func_include_directories, 'add_global_arguments' : self.func_add_global_arguments, } + + def get_build_def_files(self): + return self.build_def_files def get_variables(self): return self.variables @@ -511,6 +520,7 @@ class Interpreter(): prev_subdir = self.subdir self.subdir = os.path.join(prev_subdir, args[0]) buildfilename = os.path.join(self.subdir, environment.builder_filename) + self.build_def_files.append(buildfilename) code = open(os.path.join(self.environment.get_source_dir(), buildfilename)).read() assert(isinstance(code, str)) codeblock = bparser.build_ast(code) @@ -530,6 +540,8 @@ class Interpreter(): def func_configure_file(self, node, args, kwargs): self.validate_arguments(args, 2, [str, str]) + conffile = os.path.join(self.subdir, args[0]) + self.build_def_files.append(conffile) c = ConfigureFile(self.subdir, args[0], args[1], kwargs) self.build.configure_files.append(c)