diff options
Diffstat (limited to 'libclc/build/metabuild.py')
-rw-r--r-- | libclc/build/metabuild.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/libclc/build/metabuild.py b/libclc/build/metabuild.py new file mode 100644 index 0000000..4ab5db5 --- /dev/null +++ b/libclc/build/metabuild.py @@ -0,0 +1,100 @@ +import ninja_syntax +import os + +# Simple meta-build system. + +class Make(object): + def __init__(self): + self.output = open(self.output_filename(), 'w') + self.rules = {} + self.rule_text = '' + self.all_targets = [] + self.default_targets = [] + self.clean_files = [] + self.distclean_files = [] + self.output.write("""all:: + +ifndef VERBOSE + Verb = @ +endif + +""") + + def output_filename(self): + return 'Makefile' + + def rule(self, name, command, description=None, depfile=None, + generator=False): + self.rules[name] = {'command': command, 'description': description, + 'depfile': depfile, 'generator': generator} + + def build(self, output, rule, inputs=[], implicit=[], order_only=[]): + inputs = self._as_list(inputs) + implicit = self._as_list(implicit) + order_only = self._as_list(order_only) + + output_dir = os.path.dirname(output) + if output_dir != '' and not os.path.isdir(output_dir): + os.makedirs(output_dir) + + dollar_in = ' '.join(inputs) + subst = lambda text: text.replace('$in', dollar_in).replace('$out', output) + + deps = ' '.join(inputs + implicit) + if order_only: + deps += ' | ' + deps += ' '.join(order_only) + self.output.write('%s: %s\n' % (output, deps)) + + r = self.rules[rule] + command = subst(r['command']) + if r['description']: + desc = subst(r['description']) + self.output.write('\t@echo %s\n\t$(Verb) %s\n' % (desc, command)) + else: + self.output.write('\t%s\n' % command) + if r['depfile']: + depfile = subst(r['depfile']) + self.output.write('-include '+depfile+'\n') + self.output.write('\n') + + self.all_targets.append(output) + if r['generator']: + self.distclean_files.append(output) + if r['depfile']: + self.distclean_files.append(depfile) + else: + self.clean_files.append(output) + if r['depfile']: + self.distclean_files.append(depfile) + + + def _as_list(self, input): + if isinstance(input, list): + return input + return [input] + + def default(self, paths): + self.default_targets += self._as_list(paths) + + def finish(self): + self.output.write('all:: %s\n\n' % ' '.join(self.default_targets or self.all_targets)) + self.output.write('clean: \n\trm -f %s\n\n' % ' '.join(self.clean_files)) + self.output.write('distclean: clean\n\trm -f %s\n' % ' '.join(self.distclean_files)) + +class Ninja(ninja_syntax.Writer): + def __init__(self): + ninja_syntax.Writer.__init__(self, open(self.output_filename(), 'w')) + + def output_filename(self): + return 'build.ninja' + + def finish(self): + pass + +def from_name(name): + if name == 'make': + return Make() + if name == 'ninja': + return Ninja() + raise LookupError, 'unknown generator: %s; supported generators are make and ninja' % name |