Bug 1227892 - Emit a specialized object for chrome.manifest entries. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 26 Nov 2015 16:29:55 +0900
changeset 308916 8421887c804231f92b542314e8db3fa19e8eabb5
parent 308915 2a2355e3d1005136441f5862e29be33d1571c0af
child 308917 573992ac6b3d304b62fd070c4a7b466f24df5bf1
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1227892
milestone45.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 1227892 - Emit a specialized object for chrome.manifest entries. r=gps This new ChromeManifestEntry object type is generic and can hold any kind of chrome manifest entry, but we currently only emit them for binary components. References to sub-directory manifests is left to the backend, for now, until all manifest entries are emitted by the frontend.
config/makefiles/target_binaries.mk
python/mozbuild/mozbuild/backend/fastermake.py
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/frontend/emitter.py
--- a/config/makefiles/target_binaries.mk
+++ b/config/makefiles/target_binaries.mk
@@ -1,29 +1,16 @@
 # -*- makefile -*-
 # vim:set ts=8 sw=8 sts=8 noet:
 #
 # 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/.
 
 ifndef NO_DIST_INSTALL
-ifdef SHARED_LIBRARY
-ifdef IS_COMPONENT
-target:: $(SUBMAKEFILES) $(SHARED_LIBRARY)
-	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
-ifndef NO_COMPONENTS_MANIFEST
-	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest components/components.manifest')
-	$(call py_action,buildlist,$(FINAL_TARGET)/components/components.manifest 'binary-component $(SHARED_LIBRARY)')
-endif
-endif # IS_COMPONENT
-endif # SHARED_LIBRARY
-endif # !NO_DIST_INSTALL
-
-ifndef NO_DIST_INSTALL
 
 ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS)))
 PROGRAMS_EXECUTABLES = $(SIMPLE_PROGRAMS) $(PROGRAM)
 PROGRAMS_DEST ?= $(FINAL_TARGET)
 PROGRAMS_TARGET := target
 INSTALL_TARGETS += PROGRAMS
 endif
 
@@ -32,22 +19,20 @@ ifdef DIST_INSTALL
 ifdef IS_COMPONENT
 $(error Shipping static component libs makes no sense.)
 endif
 endif # DIST_INSTALL
 endif # LIBRARY
 
 
 ifdef SHARED_LIBRARY
-ifndef IS_COMPONENT
 SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
-SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
+SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)$(if $(IS_COMPONENT),/components)
 SHARED_LIBRARY_TARGET = target
 INSTALL_TARGETS += SHARED_LIBRARY
-endif # ! IS_COMPONENT
 endif # SHARED_LIBRARY
 
 ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)$(HOST_PROGRAM)))
 HOST_PROGRAMS_EXECUTABLES = $(HOST_SIMPLE_PROGRAMS) $(HOST_PROGRAM)
 HOST_PROGRAMS_DEST ?= $(DIST)/host/bin
 HOST_PROGRAMS_TARGET = host
 INSTALL_TARGETS += HOST_PROGRAMS
 endif
--- a/python/mozbuild/mozbuild/backend/fastermake.py
+++ b/python/mozbuild/mozbuild/backend/fastermake.py
@@ -1,16 +1,17 @@
 # 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, print_function
 
 from mozbuild.backend.common import CommonBackend
 from mozbuild.frontend.data import (
+    ChromeManifestEntry,
     ContextDerived,
     Defines,
     DistFiles,
     FinalTargetFiles,
     JARManifest,
     JavaScriptModules,
     JsPreferenceFile,
     Resources,
@@ -162,16 +163,26 @@ class FasterMakeBackend(CommonBackend):
         elif isinstance(obj, DistFiles) and \
                 obj.install_target.startswith('dist/bin'):
             # We preprocess these, but they don't necessarily have preprocessor
             # directives, so tell the preprocessor to not complain about that.
             for f in obj.files:
                 self._add_preprocess(obj, f, '', defines=defines,
                                      silence_missing_directive_warnings=True)
 
+        elif isinstance(obj, ChromeManifestEntry) and \
+                obj.install_target.startswith('dist/bin'):
+            top_level = mozpath.join(obj.install_target, 'chrome.manifest')
+            if obj.path != top_level:
+                entry = 'manifest %s' % mozpath.relpath(obj.path,
+                                                        obj.install_target)
+                if entry not in self._manifest_entries[top_level]:
+                    self._manifest_entries[top_level].append(entry)
+            self._manifest_entries[obj.path].append(str(obj.entry))
+
         else:
             # We currently ignore a lot of object types, so just acknowledge
             # everything.
             return True
 
         self._seen_directories.add(obj.objdir)
         return True
 
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -32,16 +32,17 @@ from mozbuild.frontend.context import (
 from .common import CommonBackend
 from ..frontend.data import (
     AndroidAssetsDirs,
     AndroidResDirs,
     AndroidExtraResDirs,
     AndroidExtraPackages,
     AndroidEclipseProjectData,
     BrandingFiles,
+    ChromeManifestEntry,
     ConfigFileSubstitution,
     ContextDerived,
     ContextWrapped,
     Defines,
     DistFiles,
     DirectoryTraversal,
     Exports,
     ExternalLibrary,
@@ -626,16 +627,19 @@ class RecursiveMakeBackend(CommonBackend
             for p in sorted(set(p.full_path for p in obj.paths)):
                 backend_file.write('ANDROID_EXTRA_RES_DIRS += %s\n' % p)
 
         elif isinstance(obj, AndroidExtraPackages):
             # Order does not matter.
             for p in sorted(set(obj.packages)):
                 backend_file.write('ANDROID_EXTRA_PACKAGES += %s\n' % p)
 
+        elif isinstance(obj, ChromeManifestEntry):
+            self._process_chrome_manifest_entry(obj, backend_file)
+
         else:
             return False
 
         return True
 
     def _fill_root_mk(self):
         """
         Create two files, root.mk and root-deps.mk, the first containing
@@ -1386,16 +1390,39 @@ INSTALL_TARGETS += %(prefix)s
             raise Exception("Cannot install to " + target)
 
         for path, strings in files.walk():
             for f in strings:
                 source = mozpath.normpath(os.path.join(obj.srcdir, f))
                 dest = mozpath.join(reltarget, path, mozpath.basename(f))
                 install_manifest.add_symlink(source, dest)
 
+    def _process_chrome_manifest_entry(self, obj, backend_file):
+        fragment = Makefile()
+        rule = fragment.create_rule(targets=['misc:'])
+
+        top_level = mozpath.join(obj.install_target, 'chrome.manifest')
+        if obj.path != top_level:
+            args = [
+                mozpath.join('$(DEPTH)', top_level),
+                make_quote(shell_quote('manifest %s' %
+                                       mozpath.relpath(obj.path,
+                                                       obj.install_target))),
+            ]
+            rule.add_commands(['$(call py_action,buildlist,%s)' %
+                               ' '.join(args)])
+        args = [
+            mozpath.join('$(DEPTH)', obj.path),
+            make_quote(shell_quote(str(obj.entry))),
+        ]
+        rule.add_commands(['$(call py_action,buildlist,%s)' % ' '.join(args)])
+        fragment.dump(backend_file.fh, removal_guard=False)
+
+        self._no_skip['misc'].add(obj.relativedir)
+
     def _write_manifests(self, dest, manifests):
         man_dir = mozpath.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
@@ -14,16 +14,17 @@ Instead, what we have here are dumb cont
 contains the code for converting executed mozbuild files into these data
 structures.
 """
 
 from __future__ import absolute_import, unicode_literals
 
 from mozbuild.util import StrictOrderingOnAppendList
 from mozbuild.shellutil import quote as shell_quote
+from mozpack.chrome.manifest import ManifestEntry
 
 import mozpack.path as mozpath
 from .context import FinalTargetValue
 
 from ..util import (
     group_unified_files,
 )
 
@@ -994,8 +995,25 @@ class AndroidExtraPackages(ContextDerive
 
     __slots__ = (
         'packages',
     )
 
     def __init__(self, context, packages):
         ContextDerived.__init__(self, context)
         self.packages = packages
+
+class ChromeManifestEntry(ContextDerived):
+    """Represents a chrome.manifest entry."""
+
+    __slots__ = (
+        'entry',
+    )
+
+    def __init__(self, context, manifest_path, entry):
+        ContextDerived.__init__(self, context)
+        assert isinstance(entry, ManifestEntry)
+        self.path = mozpath.join(self.install_target, manifest_path)
+        # Ensure the entry is relative to the directory containing the
+        # manifest path.
+        entry = entry.rebase(mozpath.dirname(manifest_path))
+        # Then add the install_target to the entry base directory.
+        self.entry = entry.move(mozpath.dirname(self.path))
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -24,16 +24,17 @@ import reftest
 import mozinfo
 
 from .data import (
     AndroidAssetsDirs,
     AndroidExtraPackages,
     AndroidExtraResDirs,
     AndroidResDirs,
     BrandingFiles,
+    ChromeManifestEntry,
     ConfigFileSubstitution,
     ContextWrapped,
     Defines,
     DistFiles,
     DirectoryTraversal,
     Exports,
     FinalTargetFiles,
     GeneratedEventWebIDLFile,
@@ -70,16 +71,17 @@ from .data import (
     TestHarnessFiles,
     TestWebIDLFile,
     TestManifest,
     UnifiedSources,
     VariablePassthru,
     WebIDLFile,
     XPIDLFile,
 )
+from mozpack.chrome.manifest import ManifestBinaryComponent
 
 from .reader import SandboxValidationError
 
 from ..testing import (
     TEST_MANIFESTS,
     REFTEST_FLAVORS,
     WEB_PATFORM_TESTS_FLAVORS,
 )
@@ -504,16 +506,20 @@ class TreeMetadataEmitter(LoggingMixin):
                         'but SHARED_LIBRARY_NAME is the same as '
                         'STATIC_LIBRARY_NAME. Please change one of them.',
                         context)
 
             if shared_lib:
                 lib = SharedLibrary(context, libname, **shared_args)
                 self._libs[libname].append(lib)
                 self._linkage.append((context, lib, 'USE_LIBS'))
+                if is_component and not context['NO_COMPONENTS_MANIFEST']:
+                    yield ChromeManifestEntry(context,
+                        'components/components.manifest',
+                        ManifestBinaryComponent('components', lib.lib_name))
             if static_lib:
                 lib = StaticLibrary(context, libname, **static_args)
                 self._libs[libname].append(lib)
                 self._linkage.append((context, lib, 'USE_LIBS'))
 
             if lib_defines:
                 if not libname:
                     raise SandboxValidationError('LIBRARY_DEFINES needs a '
@@ -577,17 +583,16 @@ class TreeMetadataEmitter(LoggingMixin):
             'RCFILE',
             'RESFILE',
             'RCINCLUDE',
             'DEFFILE',
             'WIN32_EXE_LDFLAGS',
             'LD_VERSION_SCRIPT',
             'USE_EXTENSION_MANIFEST',
             'NO_JS_MANIFEST',
-            'NO_COMPONENTS_MANIFEST',
         ]
         for v in varlist:
             if v in context and context[v]:
                 passthru.variables[v] = context[v]
 
         if context.config.substs.get('OS_TARGET') == 'WINNT' and \
                 context['DELAYLOAD_DLLS']:
             context['LDFLAGS'].extend([('-DELAYLOAD:%s' % dll)
@@ -690,17 +695,18 @@ class TreeMetadataEmitter(LoggingMixin):
                         'does not exist: %s' % f, context)
 
             yield DistFiles(context, dist_files, context['FINAL_TARGET'])
 
         branding_files = context.get('BRANDING_FILES')
         if branding_files:
             yield BrandingFiles(context, branding_files)
 
-        self._handle_libraries(context)
+        for obj in self._handle_libraries(context):
+            yield obj
 
         for obj in self._process_test_manifests(context):
             yield obj
 
         for obj in self._process_jar_manifests(context):
             yield obj
 
         for name, jar in context.get('JAVA_JAR_TARGETS', {}).items():