Cannot open included file

Hello,

I have VS Code and Modern Fortran with fortls set up, on Windows.

I have a main source dir with some Fortran .f files, and a few subfolders (say lib) with some Fortran files as well, both .f and .inc.

Say a.f is in the main source dir.
Say b.f and c.inc are in the lib subdir.

My issue is with the linting process in the editor only, I have no issue with compilation. (Note that in all the following cases, everything compiles fine on my side with a good makefile. This is really only a problem in the linting process)

An include 'c.inc' statement in b.f : everything is fine, fortls is fine, the linter raises no error.
(An include 'lib/c.inc' statement in b.f : everything is also fine).

An include 'c.inc' statement in a.f, then the linter raises an error, stating Cannot open included file 'c.inc'. <= this is the one I would like to find out how to make the linter work with
An include 'lib/c.inc' statement in a.f: everything is fine, fortls is fine, the linter raises no error.

I am unsure on how to make fortls correctly find c.inc when it is in a project subdirectory as the .f with include statement (and have all / any other such statement simply work). What is especially strange to me is that both include 'c.inc' and include 'lib/c.inc' are fine when stated from b.finside lib.

Here are what I believe might be the relevant Modern Fortran / fortls options I have :

    "fortran.linter.extraArgs": [
      "-Wunused-variable",
      "-Wunused-dummy-argument",
      "-Wall",
      "-Wno-align-commons",
      "-Wmaybe-uninitialized",
      "-flto",
      "-I${workspaceFolder}/.vscode/linter",
      "-I${workspaceFolder}/**",
      "-I${workspaceFolder}\\**",
      "-I./**",
      "-I.\\**",
    ],

    "fortran.linter.includePaths": [
        "./**",
        ".\\**",
        "${workspaceFolder}/**",
        "${workspaceFolder}\\**"
    ],
    "fortran.linter.modOutput": "${workspaceFolder}/.vscode/linter",
    "fortran.fortls.suffixes": [
      "f",
      "inc",
      ".inc",
      ".INC"
    ],
    "fortran.fortls.directories": [
      "./**",
      ".\\**",
      "${workspaceFolder}/**",
      "${workspaceFolder}\\**"
    ],

It seems to me I have instructed fortls to always look everywhere. Have I missed something ? How can I have fortls / the linting process reliably find any .inc in the whole source tree no matter where it is and where the .f with the include statement is ?

Thanks for your help

You’ve instructed make where to look, but not the Fortran compiler. There may be a compile option for that. In my code, in a DOS environment, I just worked directly:

a.f: include ‘c.inc’
b.f: include ‘…\c.inc’

Thanks for your input. You’re suggesting I should add something to the first set of options, fortran.linter.extraArgs ? What could I be missing ? I already have

      "-I${workspaceFolder}/.vscode/linter",
      "-I${workspaceFolder}/**",
      "-I${workspaceFolder}\\**",
      "-I./**",
      "-I.\\**",

Ideed, adding "-I./lib" makes the whole thing work, but I’m unsure why

      "-I${workspaceFolder}/**",
      "-I${workspaceFolder}\\**",
      "-I./**",
      "-I.\\**",

is not enough already ? Does anyone have any idea ?

The last 4 sets of includes are equivalent. You should only keep one (${workspaceFolder}/**). You should also omit the -I when specifying includes since you are using fortran.linter.includePaths

Update to pre-release of the extension and set fortran.logging.level to DEBUG. Then post the output from the OUTPUT pane > Modern Fortran.

I will have a more detailed look in your settings later, but here is a link to the fortls docs for source file parsing which you might find useful

https://fortls.fortran-lang.org/options.html#sources-file-parsing

Compilers will only consider files in their current working directory for inclusion.
Since you don’t use a relative path to c.inc in a.f, the compiler has no way of locating that file unless you also include ./lib. Obviously that should be caught under the ${workspaceFolder}/** glob but I suspect that the multiple ways that you added it in the includePaths made either gfortran or Modern Fortran choke. We can investigate further once you upload the logs.

I read this as you have instructed the linter where to find additional includes.

I think that you may want to use

fortran.includePaths

so that the same information is used for the compiler.

Ok.

Switching to Pre-Release fixes the issue.

I have tried going back and forth between Release and Pre-Release, and the issue pops back again in Release and disappears in Pre-Release.

Here is the debug output from the Release version :slightly_smiling_face:

["INFO" - 12:28:38 PM] Extension Name: Modern Fortran
["INFO" - 12:28:38 PM] Extension Version: 3.2.0
["INFO" - 12:28:38 PM] Linter set to: gfortran
["INFO" - 12:28:38 PM] Formatter set to: Disabled
["INFO" - 12:28:38 PM] Autocomplete set to: fortls
["INFO" - 12:28:38 PM] Hover set to: fortls
["INFO" - 12:28:38 PM] Symbols set to: fortls
["INFO" - 12:28:38 PM] using linter: gfortran located in: D:\Logiciels\GCC\bin\gfortran.EXE
["INFO" - 12:28:38 PM] Linter.arguments:
-fno-automatic
-fdefault-real-8
-fdefault-double-8
-Wunused-variable
-Wunused-dummy-argument
-Wall
-Wno-align-commons
-Wmaybe-uninitialized
-flto
-I${workspaceFolder}/.vscode/linter
-I${workspaceFolder}/**/*
-I${workspaceFolder}\**\*
-I./**/*
-I.\**\*
-ffree-line-length-none
-ffixed-line-length-none
["INFO" - 12:28:38 PM] Linter.moduleOutput: -J d:\Work\PROJECTNAME\sources/.vscode/linter
["INFO" - 12:28:38 PM] Linter.include:
./**/*
.\**\*
${workspaceFolder}/**/*
${workspaceFolder}\**\*
["INFO" - 12:28:38 PM] using linter: gfortran located in: D:\Logiciels\GCC\bin\gfortran.EXE
["INFO" - 12:28:38 PM] Linter.arguments:
-fno-automatic
-fdefault-real-8
-fdefault-double-8
-Wunused-variable
-Wunused-dummy-argument
-Wall
-Wno-align-commons
-Wmaybe-uninitialized
-flto
-I${workspaceFolder}/.vscode/linter
-I${workspaceFolder}/**/*
-I${workspaceFolder}\**\*
-I./**/*
-I.\**\*
-ffree-line-length-none
-ffixed-line-length-none
["INFO" - 12:28:38 PM] Linter.moduleOutput: -J d:\Work\PROJECTNAME\sources/.vscode/linter
["INFO" - 12:28:38 PM] Fortran Language Server
["INFO" - 12:28:39 PM] Initialising Language Server for workspace: d:\Work\PROJECTNAME\sources\algos\somefile.f with command-line options: --enable_code_actions, --hover_signature, --use_signature_help, --lowercase_intrinsics, --nthreads=4, --incremental_sync, --disable_autoupdate, --incl_suffixes, f, inc, .inc, .INC, --source_dirs, ./**/*, .\**\*, ${workspaceFolder}/**/*, ${workspaceFolder}\**\*
[INFO - 12:28:40] fortls - Fortran Language Server 3.1.1 Initialized

And with the Pre-Release :

[INFO - 12:31:55 PM] Extension Name: Modern Fortran
[INFO - 12:31:55 PM] Extension Version: 3.4.0
[INFO - 12:31:55 PM] Linter set to: "gfortran"
[INFO - 12:31:55 PM] Formatter set to: "Disabled"
[INFO - 12:31:55 PM] Autocomplete set to: "fortls"
[INFO - 12:31:55 PM] Hover set to: "fortls"
[INFO - 12:31:55 PM] Symbols set to: "fortls"
[INFO - 12:31:56 PM] [lint] Found GNU Fortran version 13.2.0
[DEBUG - 12:31:56 PM] [lint] Using Modern GNU Fortran diagnostics: true
[DEBUG - 12:31:56 PM] [lint] arguments:
[
  "-ffree-line-length-none",
  "-ffixed-line-length-none",
  "-fno-automatic",
  "-fdefault-real-8",
  "-fdefault-double-8",
  "-Wunused-variable",
  "-Wunused-dummy-argument",
  "-Wall",
  "-Wno-align-commons",
  "-Wmaybe-uninitialized",
  "-flto",
  "-I${workspaceFolder}/.vscode/linter",
  "-I${workspaceFolder}/**/*",
  "-I${workspaceFolder}\\**\\*",
  "-I./**/*",
  "-I.\\**\\*"
]
[DEBUG - 12:31:56 PM] [lint] moduleOutput: -J d:\Work\PROJECTNAME\sources\.vscode\linter
[DEBUG - 12:31:56 PM] [lint] Initialising cache for linter.includePaths
[DEBUG - 12:31:56 PM] [lint] glob paths:
[
  "./**/*",
  ".\\**\\*",
  "${workspaceFolder}/**/*",
  "${workspaceFolder}\\**\\*"
]
]
[DEBUG - 12:31:56 PM] [lint] resolved paths:
[
  "tools",
  "resources",
  "resources\\app",
  "resources\\app\\resources",
  "resources\\app\\resources\\win32",
  "resources\\app\\out",
  "resources\\app\\out\\vscode-dts",
  "resources\\app\\out\\vs",
  "resources\\app\\out\\vs\\workbench",
  "resources\\app\\out\\vs\\workbench\\services",
(...)

(…) I have cut the rest as it is monstrous.

So :slightly_smiling_face:

  • good news, the pre-release version fixes the issue :slight_smile:
  • could you explicitly suggest to me what to set fortran.linter.extraArgs, fortran.linter.includePaths, and fortran.fortls.directories to regarding this specific subject ?
  • in particular, I will at least definitely remove the ./**/. and .\**\* that are not prefixed with {workspaceFolder}, as they apparently are pointing to the VS Code install folder !

These are the settings I am now using. They seem to work fine with the Pre-Release version, but any comment is welcome :slight_smile:

    "fortran.linter.extraArgs": [
(some other options before these two :)
      "-I${workspaceFolder}/.vscode/linter",
      "-I${workspaceFolder}/**/*",
    ],

    "fortran.linter.includePaths": [
        "${workspaceFolder}/**/*",
    ],
    "fortran.linter.modOutput": "${workspaceFolder}/.vscode/linter",
    "fortran.fortls.suffixes": [
      "f",
      "inc",
      ".inc",
      ".INC"
    ],
    "fortran.fortls.directories": [
      "${workspaceFolder}/**/*",
    ],