dom/bindings/BindingGen.py
author Mike Hommey <mh+mozilla@glandium.org>
Fri, 23 Aug 2013 08:09:17 +0900
changeset 156891 bfc0c8ad96081291c22d633c23918d6fe1631288
parent 144629 ca3cba56b35e1602a1b68e9b8c094e6748eb56a6
child 157530 855d24ed747f40decef7b05c2086b9acce8d8285
permissions -rw-r--r--
Bug 904743 - Use makefile creation helper in BindingGen.py, cl.py and xpidl-process.py. r=gps While at it, fix dependencies generated by BindingGen.py

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

import os
import cPickle
from Configuration import Configuration
from Codegen import CGBindingRoot, replaceFileIfChanged
from mozbuild.makeutil import Makefile
from mozbuild.pythonutil import iter_modules_in_path
from buildconfig import topsrcdir


def generate_binding_files(config, outputprefix, srcprefix, webidlfile):
    """
    |config| Is the configuration object.
    |outputprefix| is a prefix to use for the header guards and filename.
    """

    depsname = ".deps/" + outputprefix + ".pp"
    root = CGBindingRoot(config, outputprefix, webidlfile)
    replaceFileIfChanged(outputprefix + ".h", root.declare())
    replaceFileIfChanged(outputprefix + ".cpp", root.define())

    mk = Makefile()
    rule = mk.create_rule([outputprefix + '.h', outputprefix + '.cpp'])
    rule.add_dependencies(os.path.join(srcprefix, x) for x in root.deps())
    rule.add_dependencies(iter_modules_in_path(topsrcdir))
    with open(depsname, 'w') as f:
        mk.dump(f)

def main():
    # Parse arguments.
    from optparse import OptionParser
    usagestring = "usage: %prog [header|cpp] configFile outputPrefix srcPrefix webIDLFile"
    o = OptionParser(usage=usagestring)
    o.add_option("--verbose-errors", action='store_true', default=False,
                 help="When an error happens, display the Python traceback.")
    (options, args) = o.parse_args()

    configFile = os.path.normpath(args[0])
    srcPrefix = os.path.normpath(args[1])

    # Load the configuration
    f = open('ParserResults.pkl', 'rb')
    config = cPickle.load(f)
    f.close()

    def readFile(f):
        file = open(f, 'rb')
        try:
            contents = file.read()
        finally:
            file.close()
        return contents
    allWebIDLFiles = readFile(args[2]).split()
    changedDeps = readFile(args[3]).split()

    if all(f.endswith("Binding") or f == "ParserResults.pkl" for f in changedDeps):
        toRegenerate = filter(lambda f: f.endswith("Binding"), changedDeps)
        if len(toRegenerate) == 0 and len(changedDeps) == 1:
            # Work around build system bug 874923: if we get here that means
            # that changedDeps contained only one entry and it was
            # "ParserResults.pkl".  That should never happen: if the
            # ParserResults.pkl changes then either one of the globalgen files
            # changed (in which case we wouldn't be in this "only
            # ParserResults.pkl and *Binding changed" code) or some .webidl
            # files changed (and then the corresponding *Binding files should
            # show up in changedDeps).  Since clearly the build system is
            # confused, just regenerate everything to be safe.
            toRegenerate = allWebIDLFiles
        else:
            toRegenerate = map(lambda f: f[:-len("Binding")] + ".webidl",
                               toRegenerate)
    else:
        toRegenerate = allWebIDLFiles

    for webIDLFile in toRegenerate:
        assert webIDLFile.endswith(".webidl")
        outputPrefix = webIDLFile[:-len(".webidl")] + "Binding"
        generate_binding_files(config, outputPrefix, srcPrefix, webIDLFile);

if __name__ == '__main__':
    main()