Repository: mesonbuild/meson

Issue:
[possible regression in 0.55] New rpath must not be longer than the old one
Several projects fail to build with meson with the error from the subject.
For example devel/gnome-builder: http://package22.nyi.freebsd.org/data/113amd64-default-PR244008/2020-07-15_21h37m37s/logs/errors/gnome-builder-3.28.4_4.log
See the list here: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=247935#c2

Could you please comment on this? Why did these build before and not with 0.55?

FreeBSD 12.1

Thanks,
Yuri

Discussion:

Patch:
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index 32919e42a..a74dc957e 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -19,6 +19,7 @@ from ..mesonlib import (
     EnvironmentException, MachineChoice, version_compare,
 )
 
+from ..arglist import CompilerArgs
 from .compilers import (
     d_dmd_buildtype_args,
     d_gdc_buildtype_args,
@@ -426,6 +427,9 @@ class DmdLikeCompilerMixin:
             args = [a.replace('-L=', '-Xcc=-Wl,') for a in args]
         return args
 
+class DCompilerArgs(CompilerArgs):
+    prepend_prefixes = ('-I', '-L')
+    dedup2_prefixes = ('-I')
 
 class DCompiler(Compiler):
     mscrt_args = {
@@ -599,6 +603,9 @@ class DCompiler(Compiler):
         args += extra_args
         return args
 
+    def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> DCompilerArgs:
+        return DCompilerArgs(self, args)
+
     def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'):
         args = self._get_compiler_check_args(env, extra_args, dependencies, mode)
 
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index 4176b9a03..f92769303 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -307,17 +307,20 @@ class Elf(DataSizes):
         self.bf.seek(rp_off)
 
         old_rpath = self.read_str()
-        new_rpaths = []
+        # Some rpath entries may come from multiple sources.
+        # Only add each one once.
+        new_rpaths = OrderedSet()
         if new_rpath:
-            new_rpaths.append(new_rpath)
+            new_rpaths.add(new_rpath)
         if old_rpath:
             # Filter out build-only rpath entries
             # added by get_link_dep_subdirs() or
             # specified by user with build_rpath.
-            for dir in old_rpath.split(b':'):
-                if not (dir in rpath_dirs_to_remove or
-                        dir == (b'X' * len(dir))):
-                    new_rpaths.append(dir)
+            for rpath_dir in old_rpath.split(b':'):
+                if not (rpath_dir in rpath_dirs_to_remove or
+                        rpath_dir == (b'X' * len(rpath_dir))):
+                    if rpath_dir:
+                        new_rpaths.add(rpath_dir)
 
         # Prepend user-specified new entries while preserving the ones that came from pkgconfig etc.
         new_rpath = b':'.join(new_rpaths)


Test patch:
diff --git a/run_unittests.py b/run_unittests.py
index 9cd95f0b5..0ff80356a 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -376,6 +376,12 @@ class InternalTests(unittest.TestCase):
         a += ['-I.', '-I./tests2/']
         self.assertEqual(a, ['-I.', '-I./tests2/', '-I./tests/', '-I..'])
 
+    def test_compiler_args_class_d(self):
+        d = mesonbuild.compilers.DCompiler([], 'fake', MachineChoice.HOST, 'info', 'arch', False, None)
+        # check include order is kept when deduplicating
+        a = d.compiler_args(['-Ifirst', '-Isecond', '-Ithird'])
+        a += ['-Ifirst']
+        self.assertEqual(a, ['-Ifirst', '-Isecond', '-Ithird'])
 
     def test_compiler_args_class(self):
         cc = mesonbuild.compilers.CCompiler([], 'fake', False, MachineChoice.HOST, mock.Mock())