blob: 4ab5db58e06ec39e4b094d4990c10fa41017b3f8 [file] [log] [blame]
Peter Collingbourned5395fb2012-01-08 22:09:58 +00001import ninja_syntax
2import os
3
4# Simple meta-build system.
5
6class Make(object):
7 def __init__(self):
8 self.output = open(self.output_filename(), 'w')
9 self.rules = {}
10 self.rule_text = ''
11 self.all_targets = []
Peter Collingbournebae68332012-06-01 17:29:59 +000012 self.default_targets = []
Peter Collingbourned5395fb2012-01-08 22:09:58 +000013 self.clean_files = []
14 self.distclean_files = []
15 self.output.write("""all::
16
17ifndef VERBOSE
18 Verb = @
19endif
20
21""")
22
23 def output_filename(self):
24 return 'Makefile'
25
26 def rule(self, name, command, description=None, depfile=None,
27 generator=False):
28 self.rules[name] = {'command': command, 'description': description,
29 'depfile': depfile, 'generator': generator}
30
31 def build(self, output, rule, inputs=[], implicit=[], order_only=[]):
32 inputs = self._as_list(inputs)
33 implicit = self._as_list(implicit)
34 order_only = self._as_list(order_only)
35
36 output_dir = os.path.dirname(output)
37 if output_dir != '' and not os.path.isdir(output_dir):
38 os.makedirs(output_dir)
39
40 dollar_in = ' '.join(inputs)
41 subst = lambda text: text.replace('$in', dollar_in).replace('$out', output)
42
43 deps = ' '.join(inputs + implicit)
44 if order_only:
45 deps += ' | '
46 deps += ' '.join(order_only)
47 self.output.write('%s: %s\n' % (output, deps))
48
49 r = self.rules[rule]
50 command = subst(r['command'])
51 if r['description']:
52 desc = subst(r['description'])
53 self.output.write('\t@echo %s\n\t$(Verb) %s\n' % (desc, command))
54 else:
55 self.output.write('\t%s\n' % command)
56 if r['depfile']:
57 depfile = subst(r['depfile'])
58 self.output.write('-include '+depfile+'\n')
59 self.output.write('\n')
60
61 self.all_targets.append(output)
62 if r['generator']:
63 self.distclean_files.append(output)
Tom Stellard9fabcb32013-10-23 02:49:33 +000064 if r['depfile']:
65 self.distclean_files.append(depfile)
Peter Collingbourned5395fb2012-01-08 22:09:58 +000066 else:
67 self.clean_files.append(output)
Tom Stellard9fabcb32013-10-23 02:49:33 +000068 if r['depfile']:
69 self.distclean_files.append(depfile)
70
Peter Collingbourned5395fb2012-01-08 22:09:58 +000071
72 def _as_list(self, input):
73 if isinstance(input, list):
74 return input
75 return [input]
76
Peter Collingbournebae68332012-06-01 17:29:59 +000077 def default(self, paths):
78 self.default_targets += self._as_list(paths)
79
Peter Collingbourned5395fb2012-01-08 22:09:58 +000080 def finish(self):
Peter Collingbournebae68332012-06-01 17:29:59 +000081 self.output.write('all:: %s\n\n' % ' '.join(self.default_targets or self.all_targets))
Peter Collingbourned5395fb2012-01-08 22:09:58 +000082 self.output.write('clean: \n\trm -f %s\n\n' % ' '.join(self.clean_files))
83 self.output.write('distclean: clean\n\trm -f %s\n' % ' '.join(self.distclean_files))
84
85class Ninja(ninja_syntax.Writer):
86 def __init__(self):
87 ninja_syntax.Writer.__init__(self, open(self.output_filename(), 'w'))
88
89 def output_filename(self):
90 return 'build.ninja'
91
92 def finish(self):
93 pass
94
95def from_name(name):
96 if name == 'make':
97 return Make()
98 if name == 'ninja':
99 return Ninja()
100 raise LookupError, 'unknown generator: %s; supported generators are make and ninja' % name