Bug 1407403 - Handle IPDL code generation in the tup backend; r?build-peer draft
authorMike Shal <mshal@mozilla.com>
Mon, 23 Oct 2017 10:44:11 -0400
changeset 686860 9ced9ef0e317f4e02c83c643397f0eab9f910205
parent 686335 a97fb1c39d51a7337b46957bde4273bd308b796a
child 737501 744924fd84acfd5a40d53fa89c903e155cdec85b
push id86325
push userbmo:mshal@mozilla.com
push dateThu, 26 Oct 2017 14:30:11 +0000
reviewersbuild-peer
bugs1407403
milestone58.0a1
Bug 1407403 - Handle IPDL code generation in the tup backend; r?build-peer IPDL generation consists of a single ipdl.py invocation on all the *.ipdl and *.ipdlh files in the tree. Unfortunately the headers that are generated are placed into directories corresponding to the namespaces declared within the IDPL, and can't be determined solely based on the input filename. As such, we have to do a quick parsing of the AST in order to grab the namespaces and calculate the filenames for the .h files. The downside of this approach is that all *.ipdl/*.ipdlh files are considered inputs for the tup backend, so editing one will perform moz.build generation before running ipdl.py. This could be fixed by either standardizing the generated header layout, or fixing tup to somehow allow unspecified outputs. MozReview-Commit-ID: DzF2ryLEsrg
python/mozbuild/mozbuild/backend/tup.py
--- a/python/mozbuild/mozbuild/backend/tup.py
+++ b/python/mozbuild/mozbuild/backend/tup.py
@@ -1,15 +1,16 @@
 # 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/.
 
 from __future__ import absolute_import, unicode_literals
 
 import os
+import sys
 
 import mozpack.path as mozpath
 from mozbuild.base import MozbuildObject
 from mozbuild.backend.base import PartialBackend, HybridBackend
 from mozbuild.backend.recursivemake import RecursiveMakeBackend
 from mozbuild.shellutil import quote as shell_quote
 from mozbuild.util import OrderedDefaultDict
 
@@ -440,19 +441,63 @@ class TupOnly(CommonBackend, PartialBack
             inputs=[input_file],
             display='Preprocess %o',
             cmd=cmd,
             outputs=[output],
         )
 
     def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources,
                              unified_ipdl_cppsrcs_mapping):
-        # TODO: This isn't implemented yet in the tup backend, but it is called
-        # by the CommonBackend.
-        pass
+        # Preferably we wouldn't have to import ipdl, but we need to parse the
+        # ast in order to determine the namespaces since they are used in the
+        # header output paths.
+        sys.path.append(mozpath.join(self.environment.topsrcdir, 'ipc', 'ipdl'))
+        import ipdl
+
+        backend_file = self._get_backend_file('ipc/ipdl')
+        outheaderdir = '_ipdlheaders'
+        cmd = [
+            '$(PYTHON_PATH)',
+            '$(PLY_INCLUDE)',
+            '%s/ipdl.py' % backend_file.srcdir,
+            '--sync-msg-list=%s/sync-messages.ini' % backend_file.srcdir,
+            '--msg-metadata=%s/message-metadata.ini' % backend_file.srcdir,
+            '--outheaders-dir=%s' % outheaderdir,
+            '--outcpp-dir=.',
+        ]
+        ipdldirs = sorted(set(mozpath.dirname(p) for p in sorted_ipdl_sources))
+        cmd.extend(['-I%s' % d for d in ipdldirs])
+        cmd.extend(sorted_ipdl_sources)
+
+        outputs = ['IPCMessageTypeName.cpp', mozpath.join(outheaderdir, 'IPCMessageStart.h'), 'ipdl_lextab.py', 'ipdl_yacctab.py']
+
+        for filename in sorted_ipdl_sources:
+            filepath, ext = os.path.splitext(filename)
+            dirname, basename = os.path.split(filepath)
+            dirname = mozpath.relpath(dirname, self.environment.topsrcdir)
+
+            extensions = ['']
+            if ext == '.ipdl':
+                extensions.extend(['Child', 'Parent'])
+
+            with open(filename) as f:
+                ast = ipdl.parse(f.read(), filename, includedirs=ipdldirs)
+                self.backend_input_files.add(filename)
+            headerdir = os.path.join(outheaderdir, *([ns.name for ns in ast.namespaces]))
+
+            for extension in extensions:
+                outputs.append("%s%s.cpp" % (basename, extension))
+                outputs.append(mozpath.join(headerdir, '%s%s.h' % (basename, extension)))
+
+        backend_file.rule(
+            display='IPDL code generation',
+            cmd=cmd,
+            outputs=outputs,
+            check_unchanged=True,
+        )
 
     def _handle_webidl_build(self, bindings_dir, unified_source_mapping,
                              webidls, expected_build_output_files,
                              global_define_files):
         backend_file = self._get_backend_file('dom/bindings')
         backend_file.export_shell()
 
         for source in sorted(webidls.all_preprocessed_sources()):