Bug 629668 - Don't rebuild IPDL files when not necessary; r=cjones

This commit is contained in:
Benoit Girard 2011-12-15 15:10:35 +00:00
parent c73b1abc76
commit 0442739d48
4 changed files with 92 additions and 18 deletions

View File

@ -112,15 +112,19 @@ include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
-include $(ALL_IPDLSRCS:.ipdl=.ipdl.depends)
# NB: the IPDL compiler manages .ipdl-->.h/.cpp dependencies itself,
# which is why we don't have explicit .h/.cpp targets here
export:: $(ALL_IPDLSRCS)
export:: $(CPPSRCS)
$(CPPSRCS) : $(ALL_IPDLSRCS)
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/other-licenses/ply \
$(srcdir)/ipdl.py \
--outheaders-dir=_ipdlheaders \
--outcpp-dir=. \
--dependencies \
$(IPDLDIRS:%=-I$(topsrcdir)/%) \
$^

View File

@ -59,12 +59,15 @@ op.add_option('-o', '--outcpp-dir', dest='cppdir', default='.',
A protocol Foo in the namespace bar will cause the sources
cppdir/FooParent.cpp, cppdir/FooChild.cpp
to be generated""")
op.add_option('-m', '--dependencies', dest='emitdependencies', default=False, action='store_true',
help="Emit Makefile dependencies for incremental rebuilds")
options, files = op.parse_args()
_verbosity = options.verbosity
headersdir = options.headersdir
cppdir = options.cppdir
emitdependencies = options.emitdependencies
includedirs = [ os.path.abspath(incdir) for incdir in options.includedirs ]
if not len(files):
@ -106,13 +109,16 @@ for f in files:
log(3, ' pretty printed code:')
ipdl.genipdl(ast, codedir)
if emitdependencies == 1:
ipdl.genm(ast, cppdir, normalizedFilename(f))
# Second pass: generate code
for f in files:
# Read from parser cache
filename = normalizedFilename(f)
ast = ipdl.parse(None, filename, includedirs=includedirs)
ipdl.gencxx(filename, ast, headersdir, cppdir)
allprotocols.append('%sMsgStart' % ast.protocol.name)
allprotocols.sort()
@ -140,5 +146,5 @@ COMPILE_ASSERT(LastMsgIndex <= 65536, need_to_update_IPC_MESSAGE_MACRO);
#endif // ifndef IPCMessageStart_h
"""
ipdl.writeifmodified(ipcmsgstart.getvalue(),
ipdl.writetofile(ipcmsgstart.getvalue(),
os.path.join(headersdir, 'IPCMessageStart.h'))

View File

@ -30,12 +30,13 @@
#
# ***** END LICENSE BLOCK *****
__all__ = [ 'gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified' ]
__all__ = [ 'gencxx', 'genipdl', 'parse', 'typecheck', 'writetofile' ]
import os, sys
import os, sys, errno
from cStringIO import StringIO
from ipdl.cgen import IPDLCodeGen
from ipdl.mgen import DependGen
from ipdl.lower import LowerToCxx
from ipdl.parser import Parser
from ipdl.type import TypeCheck
@ -72,23 +73,32 @@ def gencxx(ipdlfilename, ast, outheadersdir, outcppdir):
+ [ resolveCpp(cpp) for cpp in cpps ]):
tempfile = StringIO()
CxxCodeGen(tempfile).cgen(ast)
writeifmodified(tempfile.getvalue(), filename)
writetofile(tempfile.getvalue(), filename)
def genipdl(ast, outdir):
return IPDLCodeGen().cgen(ast)
def writeifmodified(contents, file):
dir = os.path.dirname(file)
os.path.exists(dir) or os.makedirs(dir)
def genm(ast, dir, filename):
tempfile = StringIO()
DependGen(tempfile).mgen(ast)
filename = dir + "/" + os.path.basename(filename) + ".depends"
writetofile(tempfile.getvalue(), filename)
oldcontents = None
if os.path.exists(file):
fd = open(file, 'rb')
oldcontents = fd.read()
fd.close()
if oldcontents != contents:
fd = open(file, 'wb')
fd.write(contents)
fd.close()
def writetofile(contents, file):
dir = os.path.dirname(file)
# Guard against race condition by using Try instead
# of |os.path.exists(dir) or os.makedirs(dir)|
try:
os.makedirs(dir)
except OSError, ex:
if ex.errno != errno.EEXIST:
raise ex
# else directory already exists. silently ignore and continue
fd = open(file, 'wb')
fd.write(contents)
fd.close()

54
ipc/ipdl/ipdl/mgen.py Normal file
View File

@ -0,0 +1,54 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# Contributor(s):
# Benoit Girard <bgirard@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import sys
from ipdl.cgen import CodePrinter
from ipdl.cxx.ast import TypeArray, Visitor
class DependGen(CodePrinter, Visitor):
def __init__(self, outf=sys.stdout, indentCols=4):
CodePrinter.__init__(self, outf, indentCols)
def mgen(self, cxxfile):
cxxfile.accept(self)
def visitTranslationUnit(self, tu):
self.write(tu.filename)
self.write(": ")
for pinc in tu.protocolIncludes:
self.write(pinc.file)
self.write(" ")
self.println();