Merge m-c to fx-team.
[gecko.git] / dom / bindings / BindingGen.py
blobf12dfe7cf85ad6bf60c1257d9cb1eb6e4a4cd6f0
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 # You can obtain one at http://mozilla.org/MPL/2.0/.
5 import os
6 import cPickle
7 from Configuration import Configuration
8 from Codegen import CGBindingRoot, replaceFileIfChanged
9 from mozbuild.makeutil import Makefile
10 from mozbuild.pythonutil import iter_modules_in_path
11 from buildconfig import topsrcdir
14 def generate_binding_files(config, outputprefix, srcprefix, webidlfile):
15 """
16 |config| Is the configuration object.
17 |outputprefix| is a prefix to use for the header guards and filename.
18 """
20 depsname = ".deps/" + outputprefix + ".pp"
21 root = CGBindingRoot(config, outputprefix, webidlfile)
22 replaceFileIfChanged(outputprefix + ".h", root.declare())
23 replaceFileIfChanged(outputprefix + ".cpp", root.define())
25 mk = Makefile()
26 # NOTE: it's VERY important that we output dependencies for the FooBinding
27 # file here, not for the header or generated cpp file. These dependencies
28 # are used later to properly determine changedDeps and prevent rebuilding
29 # too much. See the comment explaining $(binding_dependency_trackers) in
30 # Makefile.in.
31 rule = mk.create_rule([outputprefix])
32 rule.add_dependencies(os.path.join(srcprefix, x) for x in root.deps())
33 rule.add_dependencies(iter_modules_in_path(topsrcdir))
34 with open(depsname, 'w') as f:
35 mk.dump(f)
37 def main():
38 # Parse arguments.
39 from optparse import OptionParser
40 usagestring = "usage: %prog [header|cpp] configFile outputPrefix srcPrefix webIDLFile"
41 o = OptionParser(usage=usagestring)
42 o.add_option("--verbose-errors", action='store_true', default=False,
43 help="When an error happens, display the Python traceback.")
44 (options, args) = o.parse_args()
46 configFile = os.path.normpath(args[0])
47 srcPrefix = os.path.normpath(args[1])
49 # Load the configuration
50 f = open('ParserResults.pkl', 'rb')
51 config = cPickle.load(f)
52 f.close()
54 def readFile(f):
55 file = open(f, 'rb')
56 try:
57 contents = file.read()
58 finally:
59 file.close()
60 return contents
61 allWebIDLFiles = readFile(args[2]).split()
62 changedDeps = readFile(args[3]).split()
64 if all(f.endswith("Binding") or f == "ParserResults.pkl" for f in changedDeps):
65 toRegenerate = filter(lambda f: f.endswith("Binding"), changedDeps)
66 if len(toRegenerate) == 0 and len(changedDeps) == 1:
67 # Work around build system bug 874923: if we get here that means
68 # that changedDeps contained only one entry and it was
69 # "ParserResults.pkl". That should never happen: if the
70 # ParserResults.pkl changes then either one of the globalgen files
71 # changed (in which case we wouldn't be in this "only
72 # ParserResults.pkl and *Binding changed" code) or some .webidl
73 # files changed (and then the corresponding *Binding files should
74 # show up in changedDeps). Since clearly the build system is
75 # confused, just regenerate everything to be safe.
76 toRegenerate = allWebIDLFiles
77 else:
78 toRegenerate = map(lambda f: f[:-len("Binding")] + ".webidl",
79 toRegenerate)
80 else:
81 toRegenerate = allWebIDLFiles
83 for webIDLFile in toRegenerate:
84 assert webIDLFile.endswith(".webidl")
85 outputPrefix = webIDLFile[:-len(".webidl")] + "Binding"
86 generate_binding_files(config, outputPrefix, srcPrefix, webIDLFile);
88 if __name__ == '__main__':
89 main()