Repository: mesonbuild/meson

Issue:
Dependency resolution fails for source with F90 extension

**Describe the bug**

Dependency resolution fails for Fortran source with F90 file extension.

```
ninja: Entering directory `_build_571'
[1/4] Compiling Fortran object libmain.so.p/src_library.F90.o
FAILED: libmain.so.p/src_library.F90.o 
gfortran -Ilibmain.so.p -I. -I.. -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -g -fPIC -Jlibmain.so.p -o libmain.so.p/src_library.F90.o -c ../src/library.F90
../src/library.F90:2:8:

    2 |    use accuracy, only : sp, dp
      |        1
Fatal Error: Cannot open module file ‘accuracy.mod’ for reading at (1): No such file or directory
compilation terminated.
[2/4] Module scanner.
ninja: build stopped: dyndep file 'libmain.so.p/depscan.dd' mentions output 'libmain.so.p/src_library.F90.o' whose build statement does not have a dyndep binding for the file.
```

**To Reproduce**

Example project reproducing the behaviour:
[mwe.tar.gz](https://github.com/mesonbuild/meson/files/6017593/mwe.tar.gz)

Meson log file:
[meson-log.txt](https://github.com/mesonbuild/meson/files/6017586/meson-log.txt)


**Expected behavior**

Resolve dependencies independently of file extensions.

**system parameters**
* Is this a [cross build](https://mesonbuild.com/Cross-compilation.html) or just a plain native build (for the same computer)?
  *native build*
* what operating system (e.g. MacOS Catalina, Windows 10, CentOS 8.0, Ubuntu 18.04, etc.)
```
> conda info

     active environment : mesonbuild
    active env location : /home/awvwgk/miniforge3/envs/mesonbuild
            shell level : 2
       user config file : /home/awvwgk/.condarc
 populated config files : /home/awvwgk/miniforge3/.condarc
          conda version : 4.9.2
    conda-build version : not installed
         python version : 3.7.8.final.0
       virtual packages : __glibc=2.33=0
                          __unix=0=0
                          __archspec=1=x86_64
       base environment : /home/awvwgk/miniforge3  (writable)
           channel URLs : https://conda.anaconda.org/conda-forge/linux-64
                          https://conda.anaconda.org/conda-forge/noarch
          package cache : /home/awvwgk/miniforge3/pkgs
                          /home/awvwgk/.conda/pkgs
       envs directories : /home/awvwgk/miniforge3/envs
                          /home/awvwgk/.conda/envs
               platform : linux-64
             user-agent : conda/4.9.2 requests/2.24.0 CPython/3.7.8 Linux/5.9.16-1-MANJARO manjaro/20.2.1 glibc/2.33
                UID:GID : 1000:1000
             netrc file : None
           offline mode : False

> uname -a
Linux saw8203 5.9.16-1-MANJARO #1 SMP PREEMPT Mon Dec 21 22:00:46 UTC 2020 x86_64 GNU/Linux
```
* what Python version are you using e.g. 3.8.0
* what `meson --version`
* what `ninja --version` if it's a Ninja build
```
conda list
# packages in environment at /home/awvwgk/miniforge3/envs/mesonbuild:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       1_gnu    conda-forge
ca-certificates           2020.12.5            ha878542_0    conda-forge
certifi                   2020.12.5        py37h89c1867_1    conda-forge
ld_impl_linux-64          2.35.1               hea4e1c9_2    conda-forge
libffi                    3.2.1             he1b5a44_1007    conda-forge
libgcc-ng                 9.3.0               h2828fa1_18    conda-forge
libgomp                   9.3.0               h2828fa1_18    conda-forge
libstdcxx-ng              9.3.0               h6de172a_18    conda-forge
meson                     0.57.1             pyhd8ed1ab_0    conda-forge
ncurses                   6.2                  h58526e2_4    conda-forge
ninja                     1.10.2               h4bd325d_0    conda-forge
openssl                   1.1.1j               h7f98852_0    conda-forge
pip                       21.0.1             pyhd8ed1ab_0    conda-forge
python                    3.7.8           h6f2ec95_0_cpython    conda-forge
python_abi                3.7                     1_cp37m    conda-forge
readline                  8.0                  he28a2e2_2    conda-forge
setuptools                49.6.0           py37h89c1867_3    conda-forge
sqlite                    3.34.0               h74cdb3f_0    conda-forge
tk                        8.6.10               hed695b0_1    conda-forge
wheel                     0.36.2             pyhd3deb0d_0    conda-forge
xz                        5.2.5                h516909a_1    conda-forge
zlib                      1.2.11            h516909a_1010    conda-forge
> meson --version
0.57.1
> python --version
Python 3.7.8
> ninja --version
1.10.2
```



Discussion:
Is there any way I can assist with fixing this issue? I have some interest in seeing this issue fixed since it blocks adaption of meson 0.57.1 for almost all my projects.
A first step would be to write a test case that reproduce the bug, and bisect to know which commit exactly broke it. Check what is different in the command line between a build that works and one that fails.
@xclaesse The bug was introduced with the module scanner and only partly fixed after I first reported it, see https://github.com/mesonbuild/meson/issues/8377#issuecomment-781916962.
Bisect says the bug was introduced with 2f836e3accd112a52bb8d3ef5d44b7e0fb692fcf
For a quick hack it seems like adding the F90 file extension in mesonbuild/compiler/compilers.py resolves the issue:

```diff
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index af76ea460..df286e25d 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -55,7 +55,7 @@ lang_suffixes = {
     'cuda': ('cu',),
     # f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
     # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
-    'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'),
+    'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp', 'F90'),
     'd': ('d', 'di'),
     'objc': ('m',),
     'objcpp': ('mm',),
```

I wonder if adding F90, F95, F03, F08, F, FOR, FTN and FPP would work as fix or if the file extension should be considered in a case-insensitive way for Fortran instead.

Edit: See https://github.com/fortran-lang/fpm/issues/250 for the complete list of Fortran file extensions.

Resolving patch:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2537,7 +2537,7 @@ def add_dependency_scanner_entries_to_element(self, target, compiler, element, s
         if not self.should_use_dyndeps_for_target(target):
             return
         extension = os.path.splitext(src.fname)[1][1:]
-        if not (extension in compilers.lang_suffixes['fortran'] or extension in compilers.lang_suffixes['cpp']):
+        if not (extension.lower() in compilers.lang_suffixes['fortran'] or extension in compilers.lang_suffixes['cpp']):
             return
         dep_scan_file = self.get_dep_scan_file_for(target)
         element.add_item('dyndep', dep_scan_file)


Test patch:
diff --git a/test cases/fortran/2 modules/meson.build b/test cases/fortran/2 modules/meson.build
--- a/test cases/fortran/2 modules/meson.build	
+++ b/test cases/fortran/2 modules/meson.build	
@@ -3,6 +3,7 @@ project('modules', 'fortran',
 
 commented = library('commented', 'comment_mod.f90')
 
-e = executable('modprog', 'mymod.f90', 'prog.f90',
+# Have one file with an upper case file extension.
+e = executable('modprog', 'mymod.F90', 'prog.f90',
   link_with: commented)
 test('moduletest', e)
diff --git a/test cases/fortran/2 modules/mymod.f90 b/test cases/fortran/2 modules/mymod.F90
similarity index 100%
rename from test cases/fortran/2 modules/mymod.f90
rename to test cases/fortran/2 modules/mymod.F90