Repository: mesonbuild/meson

Issue:
clang's linker doesn't like -pthread
There is already #2118, but I'm not sure if this is the same issue.

When I include `googletest` which requests `pthreads`, the compiler complains:
```
clang: warning: argument unused during compilation: '-pthread' [-Wunused-command-line-argument]
```

The command used to compile is:

```
 c++  -o test/unittest/simpletest 'test/unittest/simpletest@exe/simpletest.cpp.o' 'test/unittest/simpletest@exe/.._.._subprojects_googletest-release-1.8.0_googletest_src_gtest-all.cc.o' 'test/unittest/simpletest@exe/.._.._subprojects_googletest-release-1.8.0_googletest_src_gtest_main.cc.o' src/mylib.a -pthread
```
and there are no duplicate entries of `-pthread`.


Note that this is a super low priority issue (it's just a warning after all).

See https://stackoverflow.com/a/19382663/585897


Discussion:
This only applies to Apple's clang, right? I've seen this working on macOS, but I don't remember seeing it on Linux.
Strange. Now that you mentioned it I tried two compilers, the native `clang` that's shipped by the system, and version 5.0 as compiled by MacPorts. Only the one which comes with the system complains, the other one does not.

But just to confirm once again:
* `clang[++] -pthread hello.c[pp] -o hello` OK
* `clang[++] -pthread hello.o -o hello` complains because this only calls linker
* `clang[++]-mp-5.0 -pthread hello.c[pp] -o hello` OK
* `clang[++]-mp-5.0 -pthread hello.o -o hello` OK
I believe clang is wrong here, according to `man gcc`:

```
-pthread
    Define additional macros required for using the POSIX threads library. 
    You should use this option consistently for both compilation and linking.
    This option is supported on GNU/Linux targets, most other Unix derivatives,
    and also on x86 Cygwin and MinGW targets.
```

However if clang does not require `-pthread` during linking, then we can filter it out.
@jeremyhu, do you perhaps have any idea about why clang is throwing warnings for `-pthread` when used just for linking? But in particular, why only the one shipped by macOS does that, while the one compiled by MacPorts doesn't complain at all? And how this compares to `gcc` and the behaviour of `clang` on FreeBSD or Linux?
clang 7 under Linux similarly complains. Isn't the version that ships with macOS rather old?

@nirbheek I must be missing something, because I don't see how quoting the *gcc* man page could show that *clang* is wrong.
> @nirbheek I must be missing something, because I don't see how quoting the gcc man page could show that clang is wrong.

Well, if clang has decided to stop being compatible with gcc w.r.t. the `-pthread` flag, then we can change things.

If you could figure out which version of clang changed this, the fix is trivial.

Resolving patch:
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -986,12 +986,12 @@ def find_library(self, libname, env, extra_dirs, libtype='default'):
         return self.find_library_impl(libname, env, extra_dirs, code, libtype)
 
     def thread_flags(self, env):
-        if for_haiku(self.is_cross, env):
+        if for_haiku(self.is_cross, env) or for_darwin(self.is_cross, env):
             return []
         return ['-pthread']
 
     def thread_link_flags(self, env):
-        if for_haiku(self.is_cross, env):
+        if for_haiku(self.is_cross, env) or for_darwin(self.is_cross, env):
             return []
         return ['-pthread']
 
@@ -1076,16 +1076,6 @@ def get_options(self):
                                                        'none')})
         return opts
 
-    def thread_flags(self, env):
-        if for_darwin(self.is_cross, env):
-            return []
-        return super().thread_flags()
-
-    def thread_link_flags(self, env):
-        if for_darwin(self.is_cross, env):
-            return []
-        return super().thread_link_flags()
-
     def get_option_compile_args(self, options):
         args = []
         std = options['c_std']
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -37,7 +37,7 @@
 import mesonbuild.modules.gnome
 from mesonbuild.interpreter import Interpreter, ObjectHolder
 from mesonbuild.mesonlib import (
-    is_windows, is_osx, is_cygwin, is_dragonflybsd, is_openbsd,
+    is_windows, is_osx, is_cygwin, is_dragonflybsd, is_openbsd, is_haiku,
     windows_proof_rmtree, python_command, version_compare,
     BuildDirLock, Version
 )
@@ -3270,17 +3270,17 @@ def test_pkgconfig_gen_deps(self):
         self.assertEqual(sorted(out), sorted(['libfoo >= 1.0']))
 
         out = self._run(cmd + ['--cflags-only-other']).strip().split()
-        self.assertEqual(sorted(out), sorted(['-pthread', '-DCUSTOM']))
+        self.check_pkg_flags_are_same(out, ['-pthread', '-DCUSTOM'])
 
         out = self._run(cmd + ['--libs-only-l', '--libs-only-other']).strip().split()
-        self.assertEqual(sorted(out), sorted(['-pthread', '-lcustom',
-                                              '-llibmain', '-llibexposed']))
+        self.check_pkg_flags_are_same(out, ['-pthread', '-lcustom',
+                                            '-llibmain', '-llibexposed'])
 
         out = self._run(cmd + ['--libs-only-l', '--libs-only-other', '--static']).strip().split()
-        self.assertEqual(sorted(out), sorted(['-pthread', '-lcustom',
-                                              '-llibmain', '-llibexposed',
-                                              '-llibinternal', '-lcustom2',
-                                              '-lfoo']))
+        self.check_pkg_flags_are_same(out, ['-pthread', '-lcustom',
+                                            '-llibmain', '-llibexposed',
+                                            '-llibinternal', '-lcustom2',
+                                            '-lfoo'])
 
         cmd = ['pkg-config', 'requires-test']
         out = self._run(cmd + ['--print-requires']).strip().split('\n')
@@ -3290,6 +3290,11 @@ def test_pkgconfig_gen_deps(self):
         out = self._run(cmd + ['--print-requires-private']).strip().split('\n')
         self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello']))
 
+    def check_pkg_flags_are_same(self, output, expected):
+        if is_osx() or is_haiku():
+            expected = [x for x in expected if x != '-pthread']
+        self.assertEqual(sorted(output), sorted(expected))
+
     def test_pkg_unfound(self):
         testdir = os.path.join(self.unit_test_dir, '23 unfound pkgconfig')
         self.init(testdir)


Test patch: