Backed out 2 changesets (bug 1474028) per chmanchester`s request. a=backout
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Sun, 12 Aug 2018 21:22:45 +0300
changeset 486236 a4cff96e8c08ef5b7e07f68cee37b94feca49c90
parent 486235 e3cec7443adffef026b98c41bb709a4c48baecb9
child 486238 4b80658654037ce3c205c15c6df69e63e90765af
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1474028
milestone63.0a1
backs out52bd814d3589b8b7d6194e456b7fd7068af397e1
39a528147c34c988e990e9b7675f5a21e7756b10
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
Backed out 2 changesets (bug 1474028) per chmanchester`s request. a=backout Backed out changeset 52bd814d3589 (bug 1474028) Backed out changeset 39a528147c34 (bug 1474028)
build/gecko_templates.mozbuild
build/templates.mozbuild
config/makefiles/target_binaries.mk
config/recurse.mk
config/rules.mk
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/backend/tup.py
python/mozbuild/mozbuild/frontend/context.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/mach_commands.py
toolkit/library/gtest/Makefile.in
toolkit/library/gtest/moz.build
toolkit/library/gtest/rust/Makefile.in
toolkit/library/gtest/rust/moz.build
toolkit/library/moz.build
--- a/build/gecko_templates.mozbuild
+++ b/build/gecko_templates.mozbuild
@@ -102,33 +102,33 @@ def GeckoCppUnitTests(names, **kwargs):
     CppUnitTests(names)
 
     kwargs.setdefault('mozglue', 'program')
 
     GeckoBinary(**kwargs)
 
 
 @template
-def GeckoSharedLibrary(name, output_category=None, **kwargs):
+def GeckoSharedLibrary(name, **kwargs):
     '''Template for shared libraries related to Gecko.
 
     `name` identifies the library base name.
     See the documentation for `GeckoBinary` for other possible arguments.
     '''
-    SharedLibrary(name, output_category)
+    SharedLibrary(name)
 
     kwargs.setdefault('mozglue', 'library')
 
     GeckoBinary(**kwargs)
 
 
 @template
-def GeckoFramework(name, output_category=None, **kwargs):
+def GeckoFramework(name, **kwargs):
     '''Template for OSX frameworks related to Gecko.
 
     `name` identifies the library base name.
     See the documentation for `GeckoBinary` for other possible arguments.
     '''
-    Framework(name, output_category)
+    Framework(name)
 
     kwargs.setdefault('mozglue', 'library')
 
     GeckoBinary(**kwargs)
--- a/build/templates.mozbuild
+++ b/build/templates.mozbuild
@@ -53,51 +53,45 @@ def Library(name):
     '''Template for libraries.'''
     LIBRARY_NAME = name
 
 @template
 def AllowCompilerWarnings():
     COMPILE_FLAGS['WARNINGS_AS_ERRORS'] = []
 
 @template
-def RustLibrary(name, features=None, target_dir=None, output_category=None):
+def RustLibrary(name, features=None, target_dir=None):
     '''Template for Rust libraries.'''
     Library(name)
 
     IS_RUST_LIBRARY = True
     # Some Rust build scripts compile C/C++ sources, don't error on warnings for them.
     AllowCompilerWarnings()
 
     if features:
         RUST_LIBRARY_FEATURES = features
 
     if target_dir:
         RUST_LIBRARY_TARGET_DIR = target_dir
 
-    if output_category:
-        RUST_LIBRARY_OUTPUT_CATEGORY = output_category
-
 
 @template
-def SharedLibrary(name, output_category=None):
+def SharedLibrary(name):
     '''Template for shared libraries.'''
     Library(name)
 
     FORCE_SHARED_LIB = True
 
-    if output_category:
-        SHARED_LIBRARY_OUTPUT_CATEGORY = output_category
-
     Binary()
 
 
 @template
-def Framework(name, output_category=None):
+def Framework(name):
     '''Template for OSX Frameworks.'''
-    SharedLibrary(name, output_category)
+    SharedLibrary(name)
 
     IS_FRAMEWORK = True
 
 
 @template
 def HostProgram(name):
     '''Template for build tools executables.'''
     HOST_PROGRAM = name
--- a/config/makefiles/target_binaries.mk
+++ b/config/makefiles/target_binaries.mk
@@ -13,19 +13,17 @@ PROGRAMS_DEST ?= $(FINAL_TARGET)
 PROGRAMS_TARGET := target
 INSTALL_TARGETS += PROGRAMS
 endif
 
 
 ifdef SHARED_LIBRARY
 SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
 SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
-ifndef SHARED_LIBRARY_TARGET
 SHARED_LIBRARY_TARGET = target
-endif
 INSTALL_TARGETS += SHARED_LIBRARY
 endif # SHARED_LIBRARY
 
 ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)))
 HOST_PROGRAMS_EXECUTABLES = $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGRAMS)
 HOST_PROGRAMS_DEST ?= $(DIST)/host/bin
 HOST_PROGRAMS_TARGET = host
 INSTALL_TARGETS += HOST_PROGRAMS
--- a/config/recurse.mk
+++ b/config/recurse.mk
@@ -36,17 +36,17 @@ include root.mk
 
 # Special rule that does install-manifests (cf. Makefile.in) + compile
 binaries::
 	+$(MAKE) recurse_compile
 
 # Carefully avoid $(eval) type of rule generation, which makes pymake slower
 # than necessary.
 # Get current tier and corresponding subtiers from the data in root.mk.
-CURRENT_TIER := $(filter $(foreach tier,$(TIERS) $(non_default_tiers),recurse_$(tier) $(tier)-deps),$(MAKECMDGOALS))
+CURRENT_TIER := $(filter $(foreach tier,$(TIERS),recurse_$(tier) $(tier)-deps),$(MAKECMDGOALS))
 ifneq (,$(filter-out 0 1,$(words $(CURRENT_TIER))))
 $(error $(CURRENT_TIER) not supported on the same make command line)
 endif
 CURRENT_TIER := $(subst recurse_,,$(CURRENT_TIER:-deps=))
 
 # The rules here are doing directory traversal, so we don't want further
 # recursion to happen when running make -C subdir $tier. But some make files
 # further call make -C something else, and sometimes expect recursion to
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -441,17 +441,17 @@ GLOBAL_DEPS += Makefile $(addprefix $(DE
 ##############################################
 ifdef COMPILE_ENVIRONMENT
 OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
 
 compile:: host target
 
 host:: $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGRAMS) $(HOST_RUST_LIBRARY_FILE) $(HOST_SHARED_LIBRARY)
 
-target:: $(filter-out $(MOZBUILD_NON_DEFAULT_TARGETS),$(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_LIBRARY_FILE) $(RUST_PROGRAMS))
+target:: $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_LIBRARY_FILE) $(RUST_PROGRAMS)
 
 ifndef LIBRARY
 ifdef OBJS
 target:: $(OBJS)
 endif
 endif
 
 syms::
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -805,73 +805,37 @@ class RecursiveMakeBackend(CommonBackend
         #   they all end up rooting to nodes from the above category. But the
         #   way make works[1] is such that there can be benefits listing them
         #   as direct dependencies of the top recursion target, to somehow
         #   prioritize them.
         #   1. See bug 1262241 comment 5.
         compile_roots = [t for t, deps in self._compile_graph.iteritems()
                          if not deps or t not in all_compile_deps]
 
-        def add_category_rules(category, roots, graph):
-            rule = root_deps_mk.create_rule(['recurse_%s' % category])
-            rule.add_dependencies(roots)
-            for target, deps in sorted(graph.items()):
-                if deps:
-                    rule = root_deps_mk.create_rule([target])
-                    rule.add_dependencies(deps)
-
-        non_default_roots = defaultdict(list)
-        non_default_graphs = defaultdict(lambda: OrderedDefaultDict(set))
-
-        default_root_dirs = set()
-        for root in compile_roots:
-            # If this is a non-default target, separate the root from the
-            # rest of the compile graph.
-            target_name = mozpath.basename(root)
-
-            if target_name not in ('target', 'host'):
-                non_default_roots[target_name].append(root)
-                compile_roots.remove(root)
-                non_default_graphs[target_name][root] = self._compile_graph[root]
-                del self._compile_graph[root]
-            else:
-                dir_name = mozpath.dirname(root)
-                default_root_dirs.add(dir_name)
-
-        # If a directory only contains non-default compile targets, we don't
-        # attempt to dump symbols there.
-        self._no_skip['syms'] &= default_root_dirs
-
-        add_category_rules('compile', compile_roots, self._compile_graph)
-        for category, graph in non_default_graphs.iteritems():
-            add_category_rules(category, non_default_roots[category], graph)
+        rule = root_deps_mk.create_rule(['recurse_compile'])
+        rule.add_dependencies(compile_roots)
+        for target, deps in sorted(self._compile_graph.items()):
+            if deps:
+                rule = root_deps_mk.create_rule([target])
+                rule.add_dependencies(deps)
 
         root_mk = Makefile()
 
         # Fill root.mk with the convenience variables.
         for tier, filter in filters:
             all_dirs = self._traversal.traverse('', filter)
             root_mk.add_statement('%s_dirs := %s' % (tier, ' '.join(all_dirs)))
 
         # Need a list of compile targets because we can't use pattern rules:
         # https://savannah.gnu.org/bugs/index.php?42833
         root_mk.add_statement('compile_targets := %s' % ' '.join(sorted(
             set(self._compile_graph.keys()) | all_compile_deps)))
         root_mk.add_statement('syms_targets := %s' % ' '.join(sorted(
             set('%s/syms' % d for d in self._no_skip['syms']))))
 
-        root_mk.add_statement('non_default_tiers := %s' % ' '.join(sorted(
-            non_default_roots.keys())))
-
-        for category, graphs in non_default_graphs.iteritems():
-            category_dirs = [mozpath.dirname(target)
-                             for target in graphs.keys()]
-            root_mk.add_statement('%s_dirs := %s' % (category,
-                                                     ' '.join(category_dirs)))
-
         root_mk.add_statement('include root-deps.mk')
 
         with self._write_file(
                 mozpath.join(self.environment.topobjdir, 'root.mk')) as root:
             root_mk.dump(root, removal_guard=False)
 
         with self._write_file(
                 mozpath.join(self.environment.topobjdir, 'root-deps.mk')) as root_deps:
@@ -1283,39 +1247,27 @@ class RecursiveMakeBackend(CommonBackend
         for flag in per_source_flag.flags:
             backend_file.write('%s_FLAGS += %s\n' % (mozpath.basename(per_source_flag.file_name), flag))
 
     def _process_computed_flags(self, computed_flags, backend_file):
         for var, flags in computed_flags.get_flags():
             backend_file.write('COMPUTED_%s += %s\n' % (var,
                                                         ' '.join(make_quote(shell_quote(f)) for f in flags)))
 
-    def _process_non_default_target(self, libdef, target_name, backend_file):
-        backend_file.write("%s:: %s\n" % (libdef.output_category, target_name))
-        backend_file.write('MOZBUILD_NON_DEFAULT_TARGETS += %s\n' % target_name)
-
     def _process_shared_library(self, libdef, backend_file):
         backend_file.write_once('LIBRARY_NAME := %s\n' % libdef.basename)
         backend_file.write('FORCE_SHARED_LIB := 1\n')
         backend_file.write('IMPORT_LIBRARY := %s\n' % libdef.import_name)
         backend_file.write('SHARED_LIBRARY := %s\n' % libdef.lib_name)
         if libdef.soname:
             backend_file.write('DSO_SONAME := %s\n' % libdef.soname)
         if libdef.symbols_file:
             backend_file.write('SYMBOLS_FILE := %s\n' % libdef.symbols_file)
         if not libdef.cxx_link:
             backend_file.write('LIB_IS_C_ONLY := 1\n')
-        if libdef.output_category:
-            self._process_non_default_target(libdef, libdef.lib_name,
-                                             backend_file)
-            # Override the install rule target for this library. This is hacky,
-            # but can go away as soon as we start building libraries in their
-            # final location (bug 1459764).
-            backend_file.write('SHARED_LIBRARY_TARGET := %s\n' %
-                               libdef.output_category)
 
     def _process_static_library(self, libdef, backend_file):
         backend_file.write_once('LIBRARY_NAME := %s\n' % libdef.basename)
         backend_file.write('FORCE_STATIC_LIB := 1\n')
         backend_file.write('REAL_LIBRARY := %s\n' % libdef.lib_name)
         if libdef.no_expand_lib:
             backend_file.write('NO_EXPAND_LIBS := 1\n')
 
@@ -1326,31 +1278,26 @@ class RecursiveMakeBackend(CommonBackend
         # possible invocations of Cargo with this CARGO_TARGET_DIR.  Otherwise,
         # Cargo's dependency calculations don't work as we expect and we wind
         # up recompiling lots of things.
         target_dir = mozpath.join(backend_file.objdir, libdef.target_dir)
         target_dir = mozpath.normpath(target_dir)
         backend_file.write('CARGO_TARGET_DIR := %s\n' % target_dir)
         if libdef.features:
             backend_file.write('%s := %s\n' % (libdef.FEATURES_VAR, ' '.join(libdef.features)))
-        if libdef.output_category:
-            self._process_non_default_target(libdef, libdef.import_name, backend_file)
 
     def _process_host_library(self, libdef, backend_file):
         backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)
 
     def _process_host_shared_library(self, libdef, backend_file):
         backend_file.write('HOST_SHARED_LIBRARY = %s\n' % libdef.lib_name)
 
     def _build_target_for_obj(self, obj):
-        target_name = obj.KIND
-        if hasattr(obj, 'output_category') and obj.output_category:
-            target_name = obj.output_category
         return '%s/%s' % (mozpath.relpath(obj.objdir,
-            self.environment.topobjdir), target_name)
+            self.environment.topobjdir), obj.KIND)
 
     def _process_linked_libraries(self, obj, backend_file):
         def pretty_relpath(lib, name):
             return os.path.normpath(mozpath.join(mozpath.relpath(lib.objdir, obj.objdir),
                                                  name))
 
         topobjdir = mozpath.normsep(obj.topobjdir)
         # This will create the node even if there aren't any linked libraries.
--- a/python/mozbuild/mozbuild/backend/tup.py
+++ b/python/mozbuild/mozbuild/backend/tup.py
@@ -251,39 +251,33 @@ class TupBackend(CommonBackend):
             '*.inc',
             '*.msg',
             '*.py',
             '*.rs',
         )
 
         # These are 'group' dependencies - All rules that list these as an output
         # will be built before any rules that list this as an input.
-        self._installed_idls = self._output_group('installed-idls')
-        self._installed_files = self._output_group('installed-files')
-        self._rust_libs = self._output_group('rust-libs')
+        self._installed_idls = '$(MOZ_OBJ_ROOT)/<installed-idls>'
+        self._installed_files = '$(MOZ_OBJ_ROOT)/<installed-files>'
+        self._rust_libs = '$(MOZ_OBJ_ROOT)/<rust-libs>'
         # The preprocessor including source-repo.h and buildid.h creates
         # dependencies that aren't specified by moz.build and cause errors
         # in Tup. Express these as a group dependency.
-        self._early_generated_files = self._output_group('early-generated-files')
+        self._early_generated_files = '$(MOZ_OBJ_ROOT)/<early-generated-files>'
 
-        self._shlibs = self._output_group('shlibs')
-        self._default_group = self._output_group('default')
+        self._shlibs = '$(MOZ_OBJ_ROOT)/<shlibs>'
+        self._gtests = '$(MOZ_OBJ_ROOT)/<gtest>'
+        self._default_group = '$(MOZ_OBJ_ROOT)/<default>'
 
         self._rust_cmds = set()
 
         self._built_in_addons = set()
         self._built_in_addons_file = 'dist/bin/browser/chrome/browser/content/browser/built_in_addons.json'
 
-    def _output_group(self, label):
-        if label:
-            return '$(MOZ_OBJ_ROOT)/<%s>' % label
-
-    def _rust_output_group(self, label):
-        if label:
-            return self._output_group('rust-' + label)
 
     def _get_mozconfig_env(self, config):
         env = {}
         loader = MozconfigLoader(config.topsrcdir)
         mozconfig = loader.read_mozconfig(config.substs['MOZCONFIG'])
         make_extra = mozconfig['make_extra'] or []
         env = {}
         for line in make_extra:
@@ -344,18 +338,18 @@ class TupBackend(CommonBackend):
     def _lib_paths(self, objdir, libs):
         return [mozpath.relpath(mozpath.join(l.objdir, l.import_name), objdir)
                 for l in libs]
 
     def _gen_shared_library(self, backend_file):
         shlib = backend_file.shared_lib
 
         output_group = self._shlibs
-        if shlib.output_category:
-            output_group = self._output_group(shlib.output_category)
+        if 'toolkit/library/gtest' in backend_file.objdir:
+            output_group = self._gtests
 
         if shlib.cxx_link:
             mkshlib = (
                 [backend_file.environment.substs['CXX']] +
                 backend_file.local_flags['CXX_LDFLAGS']
             )
         else:
             mkshlib = (
@@ -372,26 +366,26 @@ class TupBackend(CommonBackend):
 
         objs, _, _, shared_libs, os_libs, static_libs = self._expand_libs(shlib)
         static_libs = self._lib_paths(backend_file.objdir, static_libs)
         shared_libs = self._lib_paths(backend_file.objdir, shared_libs)
 
         list_file_name = '%s.list' % shlib.name.replace('.', '_')
         list_file = self._make_list_file(backend_file.objdir, objs, list_file_name)
 
-        rust_linked = [l for l in backend_file.shared_lib.linked_libraries
-                       if isinstance(l, RustLibrary)]
+        rust_linked = self._lib_paths(backend_file.objdir,
+                                      (l for l in backend_file.shared_lib.linked_libraries
+                                       if isinstance(l, RustLibrary)))
 
         inputs = objs + static_libs + shared_libs
 
         extra_inputs = []
         if rust_linked:
-            extra_inputs = [self._rust_output_group(rust_linked[0].output_category) or
-                            self._rust_libs]
-            static_libs += self._lib_paths(backend_file.objdir, rust_linked)
+            extra_inputs = [self._rust_libs]
+            static_libs += rust_linked
 
         symbols_file = []
         if (shlib.symbols_file and
             backend_file.environment.substs.get('GCC_USE_GNU_LD')):
             inputs.append(shlib.symbols_file)
             symbols_file = ['-Wl,--version-script,%s' % shlib.symbols_file]
 
         cmd = (
@@ -740,17 +734,17 @@ class TupBackend(CommonBackend):
         if os.environ.get('MOZ_AUTOMATION'):
             # Build scripts generally read environment variables that are set
             # by cargo, however, some may rely on MOZ_AUTOMATION. We may need
             # to audit for others as well.
             env['MOZ_AUTOMATION'] = os.environ['MOZ_AUTOMATION']
 
         return env
 
-    def _gen_cargo_rules(self, backend_file, build_plan, cargo_env, output_group):
+    def _gen_cargo_rules(self, backend_file, build_plan, cargo_env):
         invocations = build_plan['invocations']
         processed = set()
 
         def get_libloading_outdir():
             for invocation in invocations:
                 if (invocation['package_name'] == 'libloading' and
                     invocation['outputs'][0].endswith('.rlib')):
                     return invocation['env']['OUT_DIR']
@@ -832,24 +826,24 @@ class TupBackend(CommonBackend):
                 # The two rust libraries in the tree share many prerequisites,
                 # so we need to prune common dependencies and therefore build
                 # all rust from the same Tupfile.
                 rust_backend_file = self._get_backend_file('toolkit/library/rust')
                 rust_backend_file.rule(
                     command,
                     inputs=sorted(inputs),
                     outputs=outputs,
-                    output_group=output_group,
+                    output_group=self._rust_libs,
                     extra_inputs=[self._installed_files],
                     display='%s %s' % (header, display_name(invocation)),
                     check_unchanged=check_unchanged,
                 )
 
                 for dst, link in invocation['links'].iteritems():
-                    rust_backend_file.symlink_rule(link, dst, output_group)
+                    rust_backend_file.symlink_rule(link, dst, self._rust_libs)
 
         for val in enumerate(invocations):
             _process(*val)
 
 
     def _gen_rust_rules(self, obj, backend_file):
         cargo_flags = self._get_cargo_flags(obj)
         cargo_env = self._get_cargo_env(obj, backend_file)
@@ -863,20 +857,17 @@ class TupBackend(CommonBackend):
             line_handler=accumulate_output,
             ensure_exit_code=False,
             explicit_env=cargo_env)
         if cargo_status:
             raise Exception("cargo --build-plan failed with output:\n%s" %
                             '\n'.join(output_lines))
 
         cargo_plan = json.loads(''.join(output_lines))
-
-        self._gen_cargo_rules(backend_file, cargo_plan, cargo_env,
-                              self._rust_output_group(obj.output_category) or
-                              self._rust_libs)
+        self._gen_cargo_rules(backend_file, cargo_plan, cargo_env)
         self.backend_input_files |= set(cargo_plan['inputs'])
 
 
     def _process_generated_file(self, backend_file, obj):
         if obj.script and obj.method:
             backend_file.export_shell()
             cmd = self._py_action('file_generate')
             if obj.localized:
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -1547,28 +1547,16 @@ VARIABLES = {
 
     'SHARED_LIBRARY_NAME': (unicode, unicode,
         """The name of the static library generated for a directory, if it needs to
         differ from the library code name.
 
         Implies FORCE_SHARED_LIB.
         """),
 
-    'SHARED_LIBRARY_OUTPUT_CATEGORY': (unicode, unicode,
-        """The output category for this context's shared library. If set this will
-        correspond to the build command that will build this shared library, and
-        the library will not be built as part of the default build.
-        """),
-
-    'RUST_LIBRARY_OUTPUT_CATEGORY': (unicode, unicode,
-        """The output category for this context's rust library. If set this will
-        correspond to the build command that will build this rust library, and
-        the library will not be built as part of the default build.
-        """),
-
     'IS_FRAMEWORK': (bool, bool,
         """Whether the library to build should be built as a framework on OSX.
 
         This implies the name of the library won't be prefixed nor suffixed.
         Implies FORCE_SHARED_LIB.
         """),
 
     'STATIC_LIBRARY_NAME': (unicode, unicode,
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -668,17 +668,16 @@ class RustLibrary(StaticLibrary):
     """Context derived container object for a static library"""
     __slots__ = (
         'cargo_file',
         'crate_type',
         'dependencies',
         'deps_path',
         'features',
         'target_dir',
-        'output_category',
     )
     TARGET_SUBST_VAR = 'RUST_TARGET'
     FEATURES_VAR = 'RUST_LIBRARY_FEATURES'
     LIB_FILE_VAR = 'RUST_LIBRARY_FILE'
 
     def __init__(self, context, basename, cargo_file, crate_type, dependencies,
                  features, target_dir, **args):
         StaticLibrary.__init__(self, context, basename, **args)
@@ -690,17 +689,16 @@ class RustLibrary(StaticLibrary):
         # many other things in the build system depend on that.
         assert self.crate_type == 'staticlib'
         self.lib_name = '%s%s%s' % (context.config.rust_lib_prefix,
                                      basename.replace('-', '_'),
                                      context.config.rust_lib_suffix)
         self.dependencies = dependencies
         self.features = features
         self.target_dir = target_dir
-        self.output_category = context.get('RUST_LIBRARY_OUTPUT_CATEGORY')
         # Skip setting properties below which depend on cargo
         # when we don't have a compile environment. The required
         # config keys won't be available, but the instance variables
         # that we don't set should never be accessed by the actual
         # build in that case.
         if not context.config.substs.get('COMPILE_ENVIRONMENT'):
             return
         build_dir = mozpath.join(target_dir,
@@ -710,17 +708,16 @@ class RustLibrary(StaticLibrary):
 
 
 class SharedLibrary(Library):
     """Context derived container object for a shared library"""
     __slots__ = (
         'soname',
         'variant',
         'symbols_file',
-        'output_category',
     )
 
     DICT_ATTRS = {
         'basename',
         'import_name',
         'install_target',
         'lib_name',
         'relobjdir',
@@ -731,17 +728,16 @@ class SharedLibrary(Library):
     MAX_VARIANT = 2
 
     def __init__(self, context, basename, real_name=None,
                  soname=None, variant=None, symbols_file=False):
         assert(variant in range(1, self.MAX_VARIANT) or variant is None)
         Library.__init__(self, context, basename, real_name)
         self.variant = variant
         self.lib_name = real_name or basename
-        self.output_category = context.get('SHARED_LIBRARY_OUTPUT_CATEGORY')
         assert self.lib_name
 
         if variant == self.FRAMEWORK:
             self.import_name = self.lib_name
         else:
             self.import_name = '%s%s%s' % (
                 context.config.import_prefix,
                 self.lib_name,
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -596,22 +596,29 @@ class GTestCommands(MachCommandBase):
         try:
             config = self.config_environment
         except Exception:
             print("Please run |./mach build| before |./mach gtest|.")
             return 1
 
         active_backend = config.substs.get('BUILD_BACKENDS', [None])[0]
         if 'Tup' in active_backend:
-            gtest_build_target = mozpath.join(self.topobjdir, '<gtest>')
+            gtest_build_path = mozpath.join(self.topobjdir, '<gtest>')
         else:
-            gtest_build_target = 'recurse_gtest'
-
+            # This path happens build the necessary parts of the tree in the
+            # Make backend due to the odd nature of partial tree builds.
+            gtest_build_path = mozpath.relpath(mozpath.join(self.topobjdir,
+                                                            'toolkit', 'library',
+                                                            'gtest', 'rust'),
+                                               self.topsrcdir)
+
+        os.environ[b'LINK_GTEST_DURING_COMPILE'] = b'1'
         res = self._mach_context.commands.dispatch('build', self._mach_context,
-                                                   what=[gtest_build_target])
+                                                   what=[gtest_build_path])
+        del os.environ[b'LINK_GTEST_DURING_COMPILE']
         if res:
             print("Could not build xul-gtest")
             return res
 
         if self.substs.get('MOZ_WIDGET_TOOLKIT') == 'cocoa':
             self._run_make(directory='browser/app', target='repackage',
                            ensure_exit_code=True)
 
--- a/toolkit/library/gtest/Makefile.in
+++ b/toolkit/library/gtest/Makefile.in
@@ -1,7 +1,28 @@
 # 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/.
 
+# Enforce that the clean/distclean rules removes everything that needs
+# to be removed from this directory.
+ifneq (,$(filter clean distclean,$(MAKECMDGOALS)))
+LINK_GTEST_DURING_COMPILE = 1
+endif
+
+# Don't link the gtest xul during MOZ_PROFILE_GENERATE, it doesn't get
+# used during profiling anyway.
+ifdef MOZ_PROFILE_GENERATE
+LINK_GTEST_DURING_COMPILE =
+endif
+
+ifndef LINK_GTEST_DURING_COMPILE
+# Force to not include backend.mk unless LINK_GTEST_DURING_COMPILE is set.
+# Not including backend.mk makes traversing this directory do nothing.
+STANDALONE_MAKEFILE = 1
+
+else
+
 include $(topsrcdir)/toolkit/library/libxul.mk
 
 include $(topsrcdir)/config/config.mk
+
+endif
--- a/toolkit/library/gtest/moz.build
+++ b/toolkit/library/gtest/moz.build
@@ -27,14 +27,13 @@ if CONFIG['OS_ARCH'] == 'Linux' and CONF
     GENERATED_FILES['symverscript'].inputs = ['../symverscript.in']
     GENERATED_FILES['symverscript'].flags = [
         'xul%s' % CONFIG['MOZILLA_SYMBOLVERSION']
     ]
     SYMBOLS_FILE = '!symverscript'
 
 # This needs to come after static:xul to avoid things like libfallible coming
 # before StaticXULComponentStart.
-Libxul('xul-gtest-real',
-       output_category=None if CONFIG['LINK_GTEST_DURING_COMPILE'] else 'gtest')
+Libxul('xul-gtest-real')
 
 DIRS += [
     'static',
 ]
new file mode 100644
--- /dev/null
+++ b/toolkit/library/gtest/rust/Makefile.in
@@ -0,0 +1,29 @@
+# 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/.
+
+# This file looks quite similar to toolkit/library/gtest/Makefile.in.
+# We only want to build gkrust-gtest when we are building libxul-gtest.
+
+# Enforce that the clean/distclean rules removes everything that needs
+# to be removed from this directory.
+ifneq (,$(filter clean distclean,$(MAKECMDGOALS)))
+LINK_GTEST_DURING_COMPILE = 1
+endif
+
+# Don't build gkrust-gtest during MOZ_PROFILE_GENERATE, it doesn't get
+# used during profiling anyway.
+ifdef MOZ_PROFILE_GENERATE
+LINK_GTEST_DURING_COMPILE =
+endif
+
+ifndef LINK_GTEST_DURING_COMPILE
+# Force to not include backend.mk unless LINK_GTEST_DURING_COMPILE is set.
+# Not including backend.mk makes traversing this directory do nothing.
+STANDALONE_MAKEFILE = 1
+
+else
+
+include $(topsrcdir)/config/config.mk
+
+endif
--- a/toolkit/library/gtest/rust/moz.build
+++ b/toolkit/library/gtest/rust/moz.build
@@ -1,10 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 include('../../rust/gkrust-features.mozbuild')
 
-RustLibrary('gkrust-gtest', gkrust_features, '../..',
-            output_category=None if CONFIG['LINK_GTEST_DURING_COMPILE'] else 'gtest')
+RustLibrary('gkrust-gtest', gkrust_features, '../..')
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -7,24 +7,24 @@
 @template
 def Libxul_defines():
     LIBRARY_DEFINES['MOZILLA_INTERNAL_API'] = True
     LIBRARY_DEFINES['IMPL_LIBXUL'] = True
     if not CONFIG['JS_SHARED_LIBRARY']:
         LIBRARY_DEFINES['STATIC_EXPORTABLE_JS_API'] = True
 
 @template
-def Libxul(name, output_category=None):
+def Libxul(name):
     if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):
         # This is going to be a framework named "XUL", not an ordinary library named
         # "libxul.dylib"
-        GeckoFramework(name, output_category=output_category, linkage=None)
+        GeckoFramework(name, linkage=None)
         SHARED_LIBRARY_NAME = 'XUL'
     else:
-        GeckoSharedLibrary(name, output_category=output_category, linkage=None)
+        GeckoSharedLibrary(name, linkage=None)
         SHARED_LIBRARY_NAME = 'xul'
 
     DELAYLOAD_DLLS += [
         'comdlg32.dll',
         'hid.dll',
         'msimg32.dll',
         'netapi32.dll',
         'secur32.dll',