# HG changeset patch
# User Chris Manchester <cmanchester@mozilla.com>
# Date 1524613176 25200
# Node ID b0e196352e1727b1df0ad2318a5587f62c9131ef
# Parent  9b49f68440cb50dc807fc54280f5960281ea17f4
Bug 1455504 - Normalize library paths to work around windows incremental linking bug. r=ted

MozReview-Commit-ID: DuZaGMKVZrn

diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -1282,18 +1282,19 @@ class RecursiveMakeBackend(CommonBackend
     def _process_host_library(self, libdef, backend_file):
         backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)
 
     def _build_target_for_obj(self, obj):
         return '%s/%s' % (mozpath.relpath(obj.objdir,
             self.environment.topobjdir), obj.KIND)
 
     def _process_linked_libraries(self, obj, backend_file):
-        def pretty_relpath(lib):
-            return '$(DEPTH)/%s' % mozpath.relpath(lib.objdir, topobjdir)
+        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.
         build_target = self._build_target_for_obj(obj)
         self._compile_graph[build_target]
 
         objs, no_pgo_objs, shared_libs, os_libs, static_libs = self._expand_libs(obj)
 
@@ -1354,34 +1355,35 @@ class RecursiveMakeBackend(CommonBackend
                                                              pgo_list_file_path)
                     backend_file.write_once('%s_PGO_OBJS := %s\n' %
                                             (obj.name, pgo_list_file_ref))
                     backend_file.write_once('%s: %s\n' % (obj_target,
                                                           pgo_list_file_path))
                 write_obj_deps(obj_target, objs_ref, pgo_objs_ref)
 
         for lib in shared_libs:
-            backend_file.write_once('SHARED_LIBS += %s/%s\n' %
-                                    (pretty_relpath(lib), lib.import_name))
+            backend_file.write_once('SHARED_LIBS += %s\n' %
+                                    pretty_relpath(lib, lib.import_name))
         for lib in static_libs:
-            backend_file.write_once('STATIC_LIBS += %s/%s\n' %
-                                    (pretty_relpath(lib), lib.import_name))
+            backend_file.write_once('STATIC_LIBS += %s\n' %
+                                    pretty_relpath(lib, lib.import_name))
         for lib in os_libs:
             if obj.KIND == 'target':
                 backend_file.write_once('OS_LIBS += %s\n' % lib)
             else:
                 backend_file.write_once('HOST_EXTRA_LIBS += %s\n' % lib)
 
         for lib in obj.linked_libraries:
             if not isinstance(lib, ExternalLibrary):
                 self._compile_graph[build_target].add(
                     self._build_target_for_obj(lib))
-            if isinstance(lib, (HostLibrary, HostRustLibrary)):
-                backend_file.write_once('HOST_LIBS += %s/%s\n' %
-                                        (pretty_relpath(lib), lib.import_name))
+            if isinstance(lib, (HostRustLibrary)):
+                backend_file.write_once('HOST_LIBS += %s\n' %
+                                        pretty_relpath(lib, lib.import_name))
+
 
         # We have to link any Rust libraries after all intermediate static
         # libraries have been listed to ensure that the Rust libraries are
         # searched after the C/C++ objects that might reference Rust symbols.
         if isinstance(obj, SharedLibrary):
             self._process_rust_libraries(obj, backend_file, pretty_relpath)
 
         # Process library-based defines
@@ -1396,18 +1398,18 @@ class RecursiveMakeBackend(CommonBackend
             return
 
         # We should have already checked this in Linkable.link_library.
         assert len(direct_linked) == 1
 
         # TODO: see bug 1310063 for checking dependencies are set up correctly.
 
         direct_linked = direct_linked[0]
-        backend_file.write('RUST_STATIC_LIB_FOR_SHARED_LIB := %s/%s\n' %
-                           (pretty_relpath(direct_linked), direct_linked.import_name))
+        backend_file.write('RUST_STATIC_LIB_FOR_SHARED_LIB := %s\n' %
+                           pretty_relpath(direct_linked, direct_linked.import_name))
 
     def _process_final_target_files(self, obj, files, backend_file):
         target = obj.install_target
         path = mozpath.basedir(target, (
             'dist/bin',
             'dist/xpi-stage',
             '_tests',
             'dist/include',
diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -992,44 +992,45 @@ class TestRecursiveMakeBackend(BackendTe
 
             for line in lines:
                 self.assertNotIn('LIB_IS_C_ONLY', line)
 
     def test_linkage(self):
         env = self._consume('linkage', RecursiveMakeBackend)
         expected_linkage = {
             'prog': {
-                'SHARED_LIBS': ['$(DEPTH)/prog/qux/qux.so',
-                                '$(DEPTH)/shared/baz.so'],
-                'STATIC_LIBS': ['$(DEPTH)/real/foo.a'],
+                'SHARED_LIBS': ['qux/qux.so',
+                                '../shared/baz.so'],
+                'STATIC_LIBS': ['../real/foo.a'],
                 'OS_LIBS': ['-lfoo', '-lbaz', '-lbar'],
             },
             'shared': {
                 'OS_LIBS': ['-lfoo'],
-                'SHARED_LIBS': ['$(DEPTH)/prog/qux/qux.so'],
+                'SHARED_LIBS': ['../prog/qux/qux.so'],
                 'STATIC_LIBS': [],
             },
             'static': {
-                'STATIC_LIBS': ['$(DEPTH)/real/foo.a'],
+                'STATIC_LIBS': ['../real/foo.a'],
                 'OS_LIBS': ['-lbar'],
-                'SHARED_LIBS': ['$(DEPTH)/prog/qux/qux.so'],
+                'SHARED_LIBS': ['../prog/qux/qux.so'],
             },
             'real': {
                 'STATIC_LIBS': [],
-                'SHARED_LIBS': ['$(DEPTH)/prog/qux/qux.so'],
+                'SHARED_LIBS': ['../prog/qux/qux.so'],
                 'OS_LIBS': ['-lbaz'],
             }
         }
         actual_linkage = {}
         for name in expected_linkage.keys():
             with open(os.path.join(env.topobjdir, name, 'backend.mk'), 'rb') as fh:
                 actual_linkage[name] = [line.rstrip() for line in fh.readlines()]
         for name in expected_linkage:
             for var in expected_linkage[name]:
                 for val in expected_linkage[name][var]:
+                    val = os.path.normpath(val)
                     line = '%s += %s' % (var, val)
                     self.assertIn(line,
                                   actual_linkage[name])
                     actual_linkage[name].remove(line)
                 for line in actual_linkage[name]:
                     self.assertNotIn('%s +=' % var, line)
 
     def test_list_files(self):
@@ -1042,21 +1043,21 @@ class TestRecursiveMakeBackend(BackendTe
             ],
             'shared/baz_so.list': [
                 'baz/baz1.o',
             ],
         }
         actual_list_files = {}
         for name in expected_list_files.keys():
             with open(os.path.join(env.topobjdir, name), 'rb') as fh:
-                actual_list_files[name] = [mozpath.normsep(line.rstrip())
+                actual_list_files[name] = [line.rstrip()
                                            for line in fh.readlines()]
         for name in expected_list_files:
             self.assertEqual(actual_list_files[name],
-                             expected_list_files[name])
+                             [os.path.normpath(f) for f in expected_list_files[name]])
 
         # We don't produce a list file for a shared library composed only of
         # object files in its directory, but instead list them in a variable.
         with open(os.path.join(env.topobjdir, 'prog', 'qux', 'backend.mk'), 'rb') as fh:
             lines = [line.rstrip() for line in fh.readlines()]
 
         self.assertIn('qux.so_OBJS := qux1.o', lines)
 
