aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2018-12-06 00:44:47 +0200
committerJussi Pakkanen <jpakkane@gmail.com>2018-12-06 16:20:54 +0200
commitc44a5a1aeca638f46b4a2d8d4a9fcb0a554037df (patch)
tree71c4fd88e2fdd98dfd61d8c3f539999ea22a658b
parent4db1b3a09f8e1f9faf7747beca2bc77ae0e5a6a5 (diff)
downloadmeson-c44a5a1aeca638f46b4a2d8d4a9fcb0a554037df.zip
meson-c44a5a1aeca638f46b4a2d8d4a9fcb0a554037df.tar.gz
meson-c44a5a1aeca638f46b4a2d8d4a9fcb0a554037df.tar.bz2
Deduplicate export-dynamic and pthread. Closes #4567.
-rw-r--r--mesonbuild/backend/ninjabackend.py4
-rw-r--r--mesonbuild/compilers/compilers.py16
-rwxr-xr-xrun_unittests.py28
-rw-r--r--test cases/unit/49 ldflagdedup/bob.c5
-rw-r--r--test cases/unit/49 ldflagdedup/meson.build12
-rw-r--r--test cases/unit/49 ldflagdedup/prog.c7
6 files changed, 69 insertions, 3 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 5606c41..f49649b 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2442,7 +2442,7 @@ rule FORTRAN_DEP_HACK%s
for dep in target.get_external_deps():
# Extend without reordering or de-dup to preserve `-L -l` sets
# https://github.com/mesonbuild/meson/issues/1718
- commands.extend_direct(dep.get_link_args())
+ commands.extend_preserving_lflags(dep.get_link_args())
need_threads |= dep.need_threads()
need_openmp |= dep.need_openmp()
for d in target.get_dependencies():
@@ -2450,7 +2450,7 @@ rule FORTRAN_DEP_HACK%s
for dep in d.get_external_deps():
need_threads |= dep.need_threads()
need_openmp |= dep.need_openmp()
- commands.extend_direct(dep.get_link_args())
+ commands.extend_preserving_lflags(dep.get_link_args())
if need_openmp:
commands += linker.openmp_flags()
if need_threads:
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 3761433..bdc90da 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -612,7 +612,10 @@ class CompilerArgs(list):
dedup2_suffixes = ()
dedup2_args = ()
# Arg prefixes and args that must be de-duped by returning 1
- dedup1_prefixes = ('-l', '-Wl,-l')
+ #
+ # NOTE: not thorough. A list of potential corner cases can be found in
+ # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038
+ dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic')
dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a')
# Match a .so of the form path/to/libfoo.so.0.1.0
# Only UNIX shared libraries require this. Others have a fixed extension.
@@ -748,6 +751,17 @@ class CompilerArgs(list):
for elem in iterable:
self.append_direct(elem)
+ def extend_preserving_lflags(self, iterable):
+ normal_flags = []
+ lflags = []
+ for i in iterable:
+ if i.startswith('-l') or i.startswith('-L'):
+ lflags.append(i)
+ else:
+ normal_flags.append(i)
+ self.extend(normal_flags)
+ self.extend_direct(lflags)
+
def __add__(self, args):
new = CompilerArgs(self, self.compiler)
new += args
diff --git a/run_unittests.py b/run_unittests.py
index cbd031a..4810264 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -118,6 +118,21 @@ def skipIfNoPkgconfig(f):
return f(*args, **kwargs)
return wrapped
+def skipIfNoPkgconfigDep(depname):
+ '''
+ Skip this test if the given pkg-config dep is not found, unless we're on CI.
+ '''
+ def wrapper(func):
+ @functools.wraps(func)
+ def wrapped(*args, **kwargs):
+ if not is_ci() and shutil.which('pkg-config') is None:
+ raise unittest.SkipTest('pkg-config not found')
+ if not is_ci() and subprocess.call(['pkg-config', '--exists', depname]) != 0:
+ raise unittest.SkipTest('pkg-config dependency {} not found.'.format(depname))
+ return func(*args, **kwargs)
+ return wrapped
+ return wrapper
+
def skip_if_not_language(lang):
def wrapper(func):
@functools.wraps(func)
@@ -4393,6 +4408,19 @@ endian = 'little'
def test_install_subdir_symlinks_with_default_umask_and_mode(self):
self.install_subdir_invalid_symlinks('196 install_mode', 'sub1')
+ @skipIfNoPkgconfigDep('gmodule-2.0')
+ def test_ldflag_dedup(self):
+ testdir = os.path.join(self.unit_test_dir, '49 ldflagdedup')
+ if is_cygwin() or is_osx():
+ raise unittest.SkipTest('Not applicable on Cygwin or OSX.')
+ self.init(testdir)
+ build_ninja = os.path.join(self.builddir, 'build.ninja')
+ max_count = 0
+ search_term = '-Wl,--export-dynamic'
+ with open(build_ninja, 'r', encoding='utf-8') as f:
+ for line in f:
+ max_count = max(max_count, line.count(search_term))
+ self.assertEqual(max_count, 1, 'Export dynamic incorrectly deduplicated.')
class LinuxCrossArmTests(BasePlatformTests):
'''
diff --git a/test cases/unit/49 ldflagdedup/bob.c b/test cases/unit/49 ldflagdedup/bob.c
new file mode 100644
index 0000000..a68d4b1
--- /dev/null
+++ b/test cases/unit/49 ldflagdedup/bob.c
@@ -0,0 +1,5 @@
+#include<gmodule.h>
+
+int func() {
+ return 0;
+}
diff --git a/test cases/unit/49 ldflagdedup/meson.build b/test cases/unit/49 ldflagdedup/meson.build
new file mode 100644
index 0000000..0bbcc50
--- /dev/null
+++ b/test cases/unit/49 ldflagdedup/meson.build
@@ -0,0 +1,12 @@
+project('lddedup', 'c')
+
+# Chosen because its ldflags contains -Wl,--export-dynamic,
+# which must be deduplicated.
+gm = dependency('gmodule-2.0')
+
+lib = static_library('bob', 'bob.c',
+ dependencies: gm)
+
+executable('prog', 'prog.c',
+ link_with: lib,
+ dependencies: gm)
diff --git a/test cases/unit/49 ldflagdedup/prog.c b/test cases/unit/49 ldflagdedup/prog.c
new file mode 100644
index 0000000..02c599d
--- /dev/null
+++ b/test cases/unit/49 ldflagdedup/prog.c
@@ -0,0 +1,7 @@
+#include<gmodule.h>
+
+int func();
+
+int main(int argc, char **argv) {
+ return func();
+}