Repository: mesonbuild/meson

Issue:
Do not use --no-undefined and --as-needed with lld cross-compiling for windows
When cross-compiling and linking with lld + mingw for Windows, meson links with  `--no-undefined` and `--as-needed`, both of these are not supported.

Meson should either try if those flags are accepted by the linker before trying to use those or the defaults need adjustment for the case of lld when cross compiling for windows.

(This can be easily worked around by disabling the flags, so this is not a urgent issue but should eventually be solved.)


Discussion:
This is specified in the constructors of the respective compiler classes. The fix is to check if the compiler is of the `GCC_MINGW` type and not add those options to the list of supported base options.
The code that enables --no-undefined and --as-needed with gcc is at [mesonbuild/compilers/compilers.py line 1066](https://github.com/mesonbuild/meson/blob/7fbab2c6e93af182703b813d5a1f962757743f26/mesonbuild/compilers/compilers.py#L1066):

```py
class GnuCompiler:
    # Functionality that is common to all GNU family compilers.
    def __init__(self, gcc_type, defines):
        self.id = 'gcc'
        self.gcc_type = gcc_type
        self.defines = defines or {}
        self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
                             'b_colorout', 'b_ndebug', 'b_staticpic']
        if self.gcc_type != GCC_OSX:
            self.base_options.append('b_lundef')
        self.base_options.append('b_asneeded')
        # All GCC backends can do assembly
        self.can_compile_suffixes.add('s')
```

The option b_lundef adds -Wl,--no-undefined, and b_asneeded does -Wl,--as-needed. The fix that jpakkane suggested might look like

```py
        if gcc_type not in (GCC_OSX, GCC_MINGW)
            self.base_options.append('b_lundef')
        if gcc_type != GCC_MINGW:
            self.base_options.append('b_asneeded')

```

Right now, Meson can't tell the difference between GNU ld and lld. From [mesonbuild/compilers/compilers.py line 1000](https://github.com/mesonbuild/meson/blob/7fbab2c6e93af182703b813d5a1f962757743f26/mesonbuild/compilers/compilers.py#L1000):

```py
def get_compiler_uses_gnuld(c):
    # FIXME: Perhaps we should detect the linker in the environment?
    # FIXME: Assumes that *BSD use GNU ld, but they might start using lld soon
    if (getattr(c, 'gcc_type', None) in (GCC_STANDARD, GCC_MINGW, GCC_CYGWIN)) or \
       (getattr(c, 'clang_type', None) in (CLANG_STANDARD, CLANG_WIN)) or \
       (getattr(c, 'icc_type', None) in (ICC_STANDARD, ICC_WIN)):
        return True
    return False
```

So if you want to enable b_lundef and b_asneeded on GNU ld but not lld, you can't call get_compiler_uses_gnuld() to decide. I wonder if we should delete GCC_MINGW from this function, or if we should teach mesonbuild/environment.py to detect GNU ld: `$CC -Wl,--version` might work.
I think it makes sense to detect the linker type because many platforms are transitioning to `lld`. We can no longer deduce the linker from the compiler, or assume that the default linker used by the compiler is what everyone wants to use.
I came across this when investigating #4105.

If I'm understanding correctly, llvm does something truly strange here:  The `clang` driver supports `gcc`-style options, but the linker used is `lld-link`, which supports `LINK`-style options, (which can be passed to it from the driver with `-Wl,`).

See http://lists.llvm.org/pipermail/llvm-dev/2017-March/111569.html

> The `clang` driver supports `gcc`-style options, but the linker used is `lld-link`, which supports `LINK`-style options

Poking at this a bit more, on Windows, by default, it seems to use MSVC's `link`, although I'm not sure how it found it:

```
C:\Program Files\LLVM\bin>where link
INFO: Could not find files for the given pattern(s).

C:\Program Files\LLVM\bin>clang -Wl,/? -v
clang version 6.0.1 (tags/RELEASE_601/final)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin
 "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe" -out:a.exe -defaultlib:libcmt "-libpath:C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\amd64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.14393.0\\ucrt\\x64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.14393.0\\um\\x64" -nologo /?
 usage: LINK [options] [files] [@commandfile]
[...]
```



I think you misunderstood what this issue is about. It is not about gcc-style vs LINK-style options. (I suggest you open a separate issue if you wncountered problems with that)

What this issue is about is that meson by default tried to use unsupported args with llvm-mingw when cross-compiling.

This issue is not about compiling on Windows.

> Am 20.09.2018 um 15:00 schrieb Jon Turney <notifications@github.com>:
> 
> The clang driver supports gcc-style options, but the linker used is lld-link, which supports LINK-style options
> 
> Poking at this a bit more, on Windows, by default, it seems to use MSVC's link, although I'm not sure how it found it:
> 
> C:\Program Files\LLVM\bin>where link
> INFO: Could not find files for the given pattern(s).
> 
> C:\Program Files\LLVM\bin>clang -Wl,/? -v
> clang version 6.0.1 (tags/RELEASE_601/final)
> Target: x86_64-pc-windows-msvc
> Thread model: posix
> InstalledDir: C:\Program Files\LLVM\bin
>  "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe" -out:a.exe -defaultlib:libcmt "-libpath:C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\amd64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.14393.0\\ucrt\\x64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.14393.0\\um\\x64" -nologo /?
>  usage: LINK [options] [files] [@commandfile]
> [...]
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub, or mute the thread.

Same here: I use meson to compile native targets for UEFI systems. This uses clang for compilation and lld-link for linking. This works perfectly fine on linux, except that meson passes the mentioned options to lld-link.

It is not a crucial issue, as the warnings can be easily ignored. But it who knows which other possibly conflicting options might be added later.

Resolving patch:
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -1298,9 +1298,11 @@ class GnuLikeCompiler(abc.ABC):
     def __init__(self, compiler_type):
         self.compiler_type = compiler_type
         self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
-                             'b_ndebug', 'b_staticpic', 'b_asneeded']
-        if not self.compiler_type.is_osx_compiler:
+                             'b_ndebug', 'b_staticpic']
+        if not self.compiler_type.is_osx_compiler and not self.compiler_type.is_windows_compiler:
             self.base_options.append('b_lundef')
+        if not self.compiler_type.is_windows_compiler:
+            self.base_options.append('b_asneeded')
         # All GCC-like backends can do assembly
         self.can_compile_suffixes.add('s')
 


Test patch: