Bug 928709 - Add support for adding include directories from the objdir in moz.build files, r=mshal
authorBrian O'Keefe <bokeefe@alum.wpi.edu>
Wed, 02 Oct 2013 13:17:55 -0400
changeset 166712 aa7cc951e8210f621d13dd54525ed5c01e65bfa0
parent 166711 af63dffeb63f8f196668e5b81fa4ebc6bd843302
child 166713 c031747aac8ac274af484e0bd46d86c1f119c66b
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmshal
bugs928709
milestone27.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 928709 - Add support for adding include directories from the objdir in moz.build files, r=mshal
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/frontend/sandbox_symbols.py
python/mozbuild/mozbuild/test/backend/common.py
python/mozbuild/mozbuild/test/backend/data/generated_includes/moz.build
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
python/mozbuild/mozbuild/test/frontend/data/generated_includes/moz.build
python/mozbuild/mozbuild/test/frontend/test_emitter.py
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -22,16 +22,17 @@ import mozpack.path as mozpath
 
 from .common import CommonBackend
 from ..frontend.data import (
     ConfigFileSubstitution,
     Defines,
     DirectoryTraversal,
     Exports,
     GeneratedEventWebIDLFile,
+    GeneratedInclude,
     GeneratedWebIDLFile,
     InstallationTarget,
     IPDLFile,
     LocalInclude,
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     Program,
     SandboxDerived,
@@ -405,16 +406,19 @@ class RecursiveMakeBackend(CommonBackend
             self._process_program(obj.program, backend_file)
 
         elif isinstance(obj, TestManifest):
             self._process_test_manifest(obj, backend_file)
 
         elif isinstance(obj, LocalInclude):
             self._process_local_include(obj.path, backend_file)
 
+        elif isinstance(obj, GeneratedInclude):
+            self._process_generated_include(obj.path, backend_file)
+
         elif isinstance(obj, InstallationTarget):
             self._process_installation_target(obj, backend_file)
 
         self._backend_files[obj.srcdir] = backend_file
 
     def _fill_root_mk(self):
         """
         Create two files, root.mk and root-deps.mk, the first containing
@@ -988,16 +992,23 @@ class RecursiveMakeBackend(CommonBackend
 
     def _process_local_include(self, local_include, backend_file):
         if local_include.startswith('/'):
             path = '$(topsrcdir)'
         else:
             path = '$(srcdir)/'
         backend_file.write('LOCAL_INCLUDES += -I%s%s\n' % (path, local_include))
 
+    def _process_generated_include(self, generated_include, backend_file):
+        if generated_include.startswith('/'):
+            path = self.environment.topobjdir.replace('\\', '/')
+        else:
+            path = ''
+        backend_file.write('LOCAL_INCLUDES += -I%s%s\n' % (path, generated_include))
+
     def _write_manifests(self, dest, manifests):
         man_dir = os.path.join(self.environment.topobjdir, '_build_manifests',
             dest)
 
         # We have a purger for the manifests themselves to ensure legacy
         # manifests are deleted.
         purger = FilePurger()
 
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -354,16 +354,28 @@ class LocalInclude(SandboxDerived):
         'path',
     )
 
     def __init__(self, sandbox, path):
         SandboxDerived.__init__(self, sandbox)
 
         self.path = path
 
+class GeneratedInclude(SandboxDerived):
+    """Describes an individual generated include path."""
+
+    __slots__ = (
+        'path',
+    )
+
+    def __init__(self, sandbox, path):
+        SandboxDerived.__init__(self, sandbox)
+
+        self.path = path
+
 class InstallationTarget(SandboxDerived):
     """Describes the rules that affect where files get installed to."""
 
     __slots__ = (
         'xpiname',
         'subdir',
         'target',
         'enabled'
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -18,16 +18,17 @@ import manifestparser
 from mozpack.files import FileFinder
 
 from .data import (
     ConfigFileSubstitution,
     Defines,
     DirectoryTraversal,
     Exports,
     GeneratedEventWebIDLFile,
+    GeneratedInclude,
     GeneratedWebIDLFile,
     InstallationTarget,
     IPDLFile,
     LocalInclude,
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     Program,
     ReaderSummary,
@@ -195,16 +196,17 @@ class TreeMetadataEmitter(LoggingMixin):
         if program:
             yield Program(sandbox, program, sandbox['CONFIG']['BIN_SUFFIX'])
 
         simple_lists = [
             ('GENERATED_EVENTS_WEBIDL_FILES', GeneratedEventWebIDLFile),
             ('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
             ('IPDL_SOURCES', IPDLFile),
             ('LOCAL_INCLUDES', LocalInclude),
+            ('GENERATED_INCLUDES', GeneratedInclude),
             ('PREPROCESSED_TEST_WEBIDL_FILES', PreprocessedTestWebIDLFile),
             ('PREPROCESSED_WEBIDL_FILES', PreprocessedWebIDLFile),
             ('TEST_WEBIDL_FILES', TestWebIDLFile),
             ('WEBIDL_FILES', WebIDLFile),
         ]
         for sandbox_var, klass in simple_lists:
             for name in sandbox.get(sandbox_var, []):
                 yield klass(sandbox, name)
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -179,16 +179,21 @@ VARIABLES = {
     'FORCE_SHARED_LIB': (bool, bool, False,
         """Whether the library in this directory is a shared library.
         """, None),
 
     'FORCE_STATIC_LIB': (bool, bool, False,
         """Whether the library in this directory is a static library.
         """, None),
 
+    'GENERATED_INCLUDES' : (StrictOrderingOnAppendList, list, [],
+        """Directories generated by the build system to be searched for include
+        files by the compiler.
+        """, None),
+
     'GTEST_C_SOURCES': (StrictOrderingOnAppendList, list, [],
         """C code source files for GTest unit tests.
 
         This variable contains a list of C GTEST unit test source files to
         compile.
         """, 'compile'),
 
     'GTEST_CMM_SOURCES': (StrictOrderingOnAppendList, list, [],
--- a/python/mozbuild/mozbuild/test/backend/common.py
+++ b/python/mozbuild/mozbuild/test/backend/common.py
@@ -83,16 +83,21 @@ CONFIGS = {
         'non_global_defines': [],
         'substs': [],
     },
     'local_includes': {
         'defines': [],
         'non_global_defines': [],
         'substs': [],
     },
+    'generated_includes': {
+        'defines': [],
+        'non_global_defines': [],
+        'substs': [],
+    },
     'final_target': {
         'defines': [],
         'non_global_defines': [],
         'substs': [],
     },
 }
 
 
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/backend/data/generated_includes/moz.build
@@ -0,0 +1,5 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+GENERATED_INCLUDES += ['/bar/baz', 'foo']
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -512,16 +512,33 @@ class TestRecursiveMakeBackend(BackendTe
         expected = [
             'LOCAL_INCLUDES += -I$(topsrcdir)/bar/baz',
             'LOCAL_INCLUDES += -I$(srcdir)/foo',
         ]
 
         found = [str for str in lines if str.startswith('LOCAL_INCLUDES')]
         self.assertEqual(found, expected)
 
+    def test_generated_includes(self):
+        """Test that GENERATED_INCLUDES are written to backend.mk correctly."""
+        env = self._consume('generated_includes', RecursiveMakeBackend)
+
+        backend_path = os.path.join(env.topobjdir, 'backend.mk')
+        lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
+
+        topobjdir = env.topobjdir.replace('\\', '/')
+
+        expected = [
+            'LOCAL_INCLUDES += -I%s/bar/baz' % topobjdir,
+            'LOCAL_INCLUDES += -Ifoo',
+        ]
+
+        found = [str for str in lines if str.startswith('LOCAL_INCLUDES')]
+        self.assertEqual(found, expected)
+
     def test_final_target(self):
         """Test that FINAL_TARGET is written to backend.mk correctly."""
         env = self._consume('final_target', RecursiveMakeBackend)
 
         final_target_rule = "FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)$(DIST_SUBDIR:%=/%)"
         print([x for x in os.walk(env.topobjdir)])
         expected = dict()
         expected[env.topobjdir] = []
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/frontend/data/generated_includes/moz.build
@@ -0,0 +1,5 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+GENERATED_INCLUDES += ['/bar/baz', 'foo']
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -11,16 +11,17 @@ from mozunit import main
 
 from mozbuild.frontend.data import (
     ConfigFileSubstitution,
     DirectoryTraversal,
     ReaderSummary,
     VariablePassthru,
     Defines,
     Exports,
+    GeneratedInclude,
     Program,
     IPDLFile,
     LocalInclude,
     TestManifest,
 )
 from mozbuild.frontend.emitter import TreeMetadataEmitter
 from mozbuild.frontend.reader import (
     BuildReader,
@@ -370,16 +371,29 @@ class TestEmitterBasic(unittest.TestCase
         local_includes = [o.path for o in objs if isinstance(o, LocalInclude)]
         expected = [
             '/bar/baz',
             'foo',
         ]
 
         self.assertEqual(local_includes, expected)
 
+    def test_generated_includes(self):
+        """Test that GENERATED_INCLUDES is emitted correctly."""
+        reader = self.reader('generated_includes')
+        objs = self.read_topsrcdir(reader)
+
+        generated_includes = [o.path for o in objs if isinstance(o, GeneratedInclude)]
+        expected = [
+            '/bar/baz',
+            'foo',
+        ]
+
+        self.assertEqual(generated_includes, expected)
+
     def test_defines(self):
         reader = self.reader('defines')
         objs = self.read_topsrcdir(reader)
 
         defines = {}
         for o in objs:
             if isinstance(o, Defines):
                 defines = o.defines