summaryrefslogtreecommitdiff
path: root/build/metabuild.py
blob: c675e093c5d27e275990aaf80cf3f4afdc3ca637 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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)
    else:
      self.clean_files.append(output)

  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