Bug 629668 - make ipdl.py check timestamps to determine whether parsing/codegen is necessary; r=bent
authorNathan Froyd <froydnj@mozilla.com>
Mon, 22 Jul 2013 14:28:53 -0400
changeset 139531 a1e66f46133179f4b7c7763158951dc13c961925
parent 139530 4b2da1603c0464ca26a4cd69d91dbe1de5b510c6
child 139532 2e57ec157214a1a6f24224e97a2c109f2b3226b6
push id24996
push useremorley@mozilla.com
push dateTue, 23 Jul 2013 12:59:05 +0000
treeherdermozilla-central@b717a7945dfb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs629668
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 629668 - make ipdl.py check timestamps to determine whether parsing/codegen is necessary; r=bent
ipc/ipdl/ipdl.py
ipc/ipdl/ipdl/lower.py
--- a/ipc/ipdl/ipdl.py
+++ b/ipc/ipdl/ipdl.py
@@ -37,16 +37,70 @@ options, files = op.parse_args()
 _verbosity = options.verbosity
 headersdir = options.headersdir
 cppdir = options.cppdir
 includedirs = [ os.path.abspath(incdir) for incdir in options.includedirs ]
 
 if not len(files):
     op.error("No IPDL files specified")
 
+ipcmessagestartpath = os.path.join(headersdir, 'IPCMessageStart.h')
+
+# Compiling the IPDL files can take a long time, even on a fast machine.
+# Check to see whether we need to do any work.
+latestipdlmod = max(os.stat(f).st_mtime for f in files)
+
+def outputModTime(f):
+    # A non-existant file is newer than everything.
+    if not os.path.exists(f):
+        return 0
+    return os.stat(f).st_mtime
+
+# Because the IPDL headers are placed into directories reflecting their
+# namespace, collect a list here so we can easily map output names without
+# parsing the actual IPDL files themselves.
+headersmap = {}
+for (path, dirs, headers) in os.walk(headersdir):
+    for h in headers:
+        base = os.path.basename(h)
+        if base in headersmap:
+            root, ext = os.path.splitext(base)
+            print >>sys.stderr, 'A protocol named', root, 'exists in multiple namespaces'
+            sys.exit(1)
+        headersmap[base] = os.path.join(path, h)
+
+def outputfiles(f):
+    base = os.path.basename(f)
+    root, ext = os.path.splitext(base)
+
+    suffixes = ['']
+    if ext == '.ipdl':
+        suffixes += ['Child', 'Parent']
+
+    for suffix in suffixes:
+        yield os.path.join(cppdir, "%s%s.cpp" % (root, suffix))
+        header = "%s%s.h" % (root, suffix)
+        # If the header already exists on disk, use that.  Otherwise,
+        # just claim that the header is found in headersdir.
+        if header in headersmap:
+            yield headersmap[header]
+        else:
+            yield os.path.join(headersdir, header)
+
+def alloutputfiles():
+    for f in files:
+        for s in outputfiles(f):
+            yield s
+    yield ipcmessagestartpath
+
+earliestoutputmod = min(outputModTime(f) for f in alloutputfiles())
+
+if latestipdlmod < earliestoutputmod:
+    sys.exit(0)
+
 log(2, 'Generated C++ headers will be generated relative to "%s"', headersdir)
 log(2, 'Generated C++ sources will be generated in "%s"', cppdir)
 
 allprotocols = []
 
 def normalizedFilename(f):
     if f == '-':
         return '<stdin>'
@@ -109,10 +163,9 @@ print >>ipcmsgstart, """
   LastMsgIndex
 };
 
 COMPILE_ASSERT(LastMsgIndex <= 65536, need_to_update_IPC_MESSAGE_MACRO);
 
 #endif // ifndef IPCMessageStart_h
 """
 
-ipdl.writeifmodified(ipcmsgstart.getvalue(),
-                     os.path.join(headersdir, 'IPCMessageStart.h'))
+ipdl.writeifmodified(ipcmsgstart.getvalue(), ipcmessagestartpath)
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -20,16 +20,18 @@ EMIT_LOGGING_CODE = ('win32' == sys.plat
 ##
 class LowerToCxx:
     def lower(self, tu):
         '''returns |[ header: File ], [ cpp : File ]| representing the
 lowered form of |tu|'''
         # annotate the AST with IPDL/C++ IR-type stuff used later
         tu.accept(_DecorateWithCxxStuff())
 
+        # Any modifications to the filename scheme here need corresponding
+        # modifications in the ipdl.py driver script.
         name = tu.name
         pheader, pcpp = File(name +'.h'), File(name +'.cpp')
 
         _GenerateProtocolCode().lower(tu, pheader, pcpp)
         headers = [ pheader ]
         cpps = [ pcpp ]
 
         if tu.protocol: