 +      sources_predepends.append(
 +        self.WriteActions(local_name, spec['actions'], extra_sources))
 +
++    if 'rules' in spec:
++      self.WriteRules(local_name, spec['rules'], extra_sources)
++
 +    link_deps = []
 +    sources = spec.get('sources', []) + extra_sources
 +    if sources:

===================================================================
--- pylib/gyp/generator/ninja.py	(revision 0)
+++ pylib/gyp/generator/ninja.py	(revision 0)
@@ -0,0 +1,367 @@
+#!/usr/bin/python
+
+# Copyright (c) 2010 Google Inc. All rights reserved.

+    stamp = self.OutputPath(self.FullPath(local_name + '.actions.stamp'))
+    self.WriteEdge([stamp], 'stamp', all_outputs)
+    return stamp
+
+  def WriteRules(self, local_name, rules, extra_sources):
+    all_outputs = []
+    for rule in rules:
+      # First write out a rule for the action.
+      # XXX we shouldn't need to qualify names; we do it because currently
+      # the rule namespace is global, but it really should be scoped to the
+      # subninja.
+      name = local_name + '.' + rule['rule_name'].replace(' ', '_')
+      action = rule['action']
+      command = gyp.common.EncodePOSIXShellList(rule['action'])
+      if self.base_dir:
+        command = 'cd %s; %s' % (self.base_dir, command)
+      self.WriteRule(name=name, command=command)
+      self.WriteLn('# %s' % repr(rule))
+      print repr(rule)
+
+      # For each source file, write an edge that generates all the outputs.
+      outputs = rule['outputs']
+      for source in rule.get('rule_sources', []):
+        self.WriteEdge(outputs, name, [source])
+      self.WriteLn()
+
+    return None
+
+  def WriteSources(self, config, sources, predepends):
+    self.WriteVariableList('defines', ['-D' + d for d in config.get('defines', [])],
