Repository: mesonbuild/meson

Issue:
Linking with Clang 3.9 using LTO is broken by Meson 0.57
**Describe the bug**
Clang 3.9 does not support `-flto-jobs` (added by #7820 / #8087).

**To Reproduce**
Use `clang-3.9` as the compiler for a build and enable LTO.

The build fails when linking and clang is called with `-flto-jobs=0`, e.g.:

```
$ clang-3.9 -flto-jobs=0
clang: error: unknown argument: '-flto-jobs=0'
clang: error: no input files
```
```
$ clang-4.0 -flto-jobs=0
clang: error: no input files
```

**Expected behavior**
Meson should not try to use `-flto-jobs` with Clang 3.9

**system parameters**
* Ubuntu 18.04/20.04
* Python 3.8.10
* Meson 0.60.1
* Ninja 1.10.2.2




Discussion:
This code is not consistent with the comment:
```
        # In clang -flto=0 means auto
        if threads >= 0:
```

The comment states a meaning for 0 but then doesn't do anything different for 0. If "0 means auto" then the expression should probably be `threads > 0` and the argument would not be used unless a non-default value was supplied.
The comment is informational and is there to inform readers that `>=` is deliberate and not an accident. Meson itself uses 0 to mean auto, too.

This is a separate matter from the fact that -flto-jobs=0 is passed as the default. It's not necessarily the case that the clang default is auto, merely because the meson default is auto... however, in this case it is true, the clang documentation says that -flto-jobs=0 is the default.

So, it could be safely removed, yes. Not because of the comment, but because it is a default option and doesn't need to be manually encoded into the command line.

...

As you have pointed out yourself, this functionality actually works flawlessly on clang 4.0 and later, so... upgrading clang to a version that is not from the dark ages would thus solve your problem. Why do you need a compiler that is 5 years old and 10 major versions behind (my system clang is 13.0.0, for comparison)? :p

However, patches to detect clang 3.9 and handle this better will be welcome. :) I think you'd want to:
- refrain from adding any explicit flags for the `=0` case
- detect the >=1 case by raising a MesonException during configure if clang is too old, because it would still be a build-time error in that case
> Why do you need a compiler that is 5 years old and 10 major versions behind (my system clang is 13.0.0, for comparison)? :p

Because unlike the "it works on my computer" approach I have a documented list of minimum requirements for dependencies and so I'm testing them. Ubuntu 18.04 provides Clang 3.9 and it doesn't go EOL until 2023.

> Ubuntu 18.04 provides Clang 3.9

Always Ubuntu. :(

What's the first version of clang with support for -flto (not -flto-jobs)? I think 3.9?

Resolving patch:
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -156,7 +156,9 @@ def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.
 
     def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]:
         args = self.get_lto_compile_args(threads=threads, mode=mode)
-        # In clang -flto=0 means auto
-        if threads >= 0:
+        # In clang -flto-jobs=0 means auto, and is the default if unspecified, just like in meson
+        if threads > 0:
+            if not mesonlib.version_compare(self.version, '>=4.0.0'):
+                raise mesonlib.MesonException('clang support for LTO threads requires clang >=4.0')
             args.append(f'-flto-jobs={threads}')
         return args


Test patch: