Repository: mesonbuild/meson

Issue:
meson can't figure out the correct linker for flang
**Describe the bug**
When building the SciPy package with msvc and flang (installed using conda) meson can't detect which linker should be used for flang. @eli-schwartz 

**To Reproduce**
This reproducer assumes that the [scipy repo](https://github.com/scipy/scipy.git) is already cloned.
```
conda create -n test python=3.10
conda activate test
mamba install clangdev flang lld
set cc=clang-cl
set cxx=clang-cl
pip install meson ninja cython numpy pybind11 pythran
meson build
```

Output Error message:
```
(test) H:\programming\scipy>meson build
The Meson build system
Version: 0.63.2
Source dir: \\filer\home\anz\programming\scipy
Build dir: \\filer\home\anz\programming\scipy\build
Build type: native build
Project name: SciPy
Project version: 1.10.0.dev0
C compiler for the host machine: clang-cl (clang-cl 11.0.1)
C linker for the host machine: lld-link lld-link 11.1.0
C++ compiler for the host machine: clang-cl (clang-cl 11.0.1)
C++ linker for the host machine: lld-link lld-link 11.1.0
Host machine cpu family: x86_64
Host machine cpu: x86_64
Compiler for C supports arguments -Wno-unused-but-set-variable: NO
Compiler for C supports arguments -Wno-unused-function: YES
Compiler for C supports arguments -Wno-conversion: YES
Compiler for C supports arguments -Wno-misleading-indentation: YES
Compiler for C supports arguments -Wno-incompatible-pointer-types: YES
Library m found: NO

\\filer\home\anz\programming\scipy\meson.build:55:0: ERROR: Unable to detect linker for compiler `flang -Wl,--version`
stdout:
stderr: flang: error: no input files
```

It seems that `flang -Wl,--version` does not furnish the details that meson would like.

If `cl` is used as the c-compiler then the problem still occurs:
```
(test) set cc=
(test) set cxx=
(test) H:\programming\scipy>meson build
The Meson build system
Version: 0.63.2
Source dir: \\filer\home\anz\programming\scipy
Build dir: \\filer\home\anz\programming\scipy\build
Build type: native build
Project name: SciPy
Project version: 1.10.0.dev0
C compiler for the host machine: cl (msvc 19.29.30145 "Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30145 for x64")
C linker for the host machine: link link 14.29.30145.0
C++ compiler for the host machine: cl (msvc 19.29.30145 "Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30145 for x64")
C++ linker for the host machine: link link 14.29.30145.0
Host machine cpu family: x86_64
Host machine cpu: x86_64
Compiler for C supports arguments -Wno-unused-but-set-variable: NO
Compiler for C supports arguments -Wno-unused-function: NO
Compiler for C supports arguments -Wno-conversion: NO
Compiler for C supports arguments -Wno-misleading-indentation: NO
Compiler for C supports arguments -Wno-incompatible-pointer-types: NO
Library m found: NO

\\filer\home\anz\programming\scipy\meson.build:55:0: ERROR: Unable to detect linker for compiler `flang -Wl,--version`
stdout:
stderr: flang: error: no input files
```

**Expected behavior**
meson should detect which linker is being used by flang.

**system parameters**
*This is a native build
* Windows 10
* Python 3.10 installed by conda
* meson version `0.63.2`
* ninja version `1.10.2.git.kitware.jobserver-1`



Discussion:
Some more context, from https://github.com/scipy/scipy/pull/16956#issuecomment-1236357252:


> [@eli-schwartz] Some linkers, like Windows link.exe, are run directly -- and Meson handles that in `guess_win_linker()`.

[@rgommers] In the compiler detection logic, it seems like `flang` only occurs once, and it uses `guess_nix_linker`: https://github.com/mesonbuild/meson/blob/d285be763f193606b078f218fdedc58679dfe037/mesonbuild/compilers/detect.py#L815-L818

Perhaps the MSVC + Flang combo is unexpected there.

Resolving patch:
diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py
--- a/mesonbuild/compilers/detect.py
+++ b/mesonbuild/compilers/detect.py
@@ -781,8 +781,20 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C
 
             if 'flang' in out or 'clang' in out:
                 cls = fortran.FlangFortranCompiler
-                linker = guess_nix_linker(env,
-                                          compiler, cls, version, for_machine)
+                if 'windows' in out or env.machines[for_machine].is_windows():
+                    # If we're in a MINGW context this actually will use a gnu
+                    # style ld, but for flang on "real" windows we'll use
+                    # either link.exe or lld-link.exe
+                    try:
+                        linker = guess_win_linker(
+                            env, compiler, cls, version,
+                            for_machine, invoked_directly=False
+                        )
+                    except MesonException:
+                        pass
+                if linker is None:
+                    linker = guess_nix_linker(env, compiler, cls,
+                                              version, for_machine)
                 return cls(
                     compiler, version, for_machine, is_cross, info,
                     exe_wrap, full_version=full_version, linker=linker)


Test patch: