Modern Fortran for VS Code creating caches

While adding fypp support to the VS Code Modern Fortran extension we realised that Intel and NAG compilers cannot receive input from stdin. This actually means that we would have to temporarily create the files produced via fypp and then run the linter on the temps. In other words we need to create persistent caches to store .mod, .smod and fypp-generated files.

My question is how do users feel about Modern Fortran doing that?

There are a few different ways that we can cache all coming with pros and cons.

Option 1: default behaviour

By default, the VS Code API offers caching to directories placed somewhere in its config where it can guarantee read/write permissions and are hidden away from the user, outside of the project’s source/build trees.

  • It allows for projects to remain clean (not polluting git, source and build trees with temporary files)
  • but accessing the persistent cache manually can be tricky since it’s always an obscure directory inside VS Code’s config.
  • Will have to give the option for the user to clean the cache and/or clean on exit

Option 2: within source/build trees

Create the persistent cache inside the project e.g. ./build/, ./build-vscode/ or .vscode/fortran/ are some potential names/locations.

  • User has easy access to the cache
  • But git tree is polluted, source and build trees are probably not
  • Potential name conflict issues with existing directories (since we will be reserving the name)
  • Can’t use the VS Code API

Option 3: no cache

Stick to only on-the-fly calculations for diagnostics. This will limit the potential usage combinations of a compiler with external tools like fypp

I am leaning towards Option 1, especially since it is the easiest and most performant to implement. I also think that the option to clear out the cache should always be provided.

GitHub issue: feat: use `Memento`s for persistent cache during linting · Issue #614 · fortran-lang/vscode-fortran-support · GitHub

Feel free to post any recommendations, thoughts or general comments on this.

  • Store cache away from my code (default VS Code behaviour)
  • Store cache somewhere in my project
  • No cache, I’m okay with only using gfortran as my linter
  • Other

0 voters

If you automatically add ./build to the .gitignore file, does that also cause git to ignore everything inside of that directory? I think so. (I’m not on a machine where I can test that right now.)

One of the nice things about having the compiler automatically invoke the preprocessor with source code is that you do not have these extra files sitting around. You have the .F90 file, and you have the resulting .o file, with nothing else sitting around to clutter the directory or confuse svn or git or anything. The debugger knows to point back directly to the .F90 source file rather than to some intermediate file.

When the preprocessor must create intermediate files, all of that becomes more complicated, for the build system (make, or whatever), for the programmer, and for the debugger. Fortran compilers have been doing this correctly for decades, not because of the fortran standard, but rather because everyone knows what works well in practice. That is why including the preprocessing step to the fortran standard should have been done decades ago.

Yes, you are correct. However, cmake (and by extension the vscode cmake extension) very often uses ./build and the out-of-source build directory. So if Modern Fortran starts using ./build to place the .mod, .smod and fypp-generated files. There is no way we can guarantee that we won’t break one’s build by overwriting a .mod generated via the build system with one generated via the linter (which does a mock compilation).

True, and we do do that with the linter’s preprocessor (fpp, cpp depending on the compiler used for linting), but because fypp is a tool external to the compiler piping its output to the compiler can only be done with stdin. Even gfortran does not officially support that, or if it does it’s undocumented. The gfortan -x flag only lists c, c++ and assembler as supported languages.

Microsoft implements Option 1 for a good reason. Option 2 is a potential security minefield if you’re not careful, a quick DuckDuckGo search brings up something along the lines of CWE - CWE-377: Insecure Temporary File (4.8), but there’s certainly others.

Better to offload those concerns onto them.

Best to not store the cache inside the project, but somewhere were it cannot be included by accident in the version control or accidentally manipulated by the user.

Fpm is using ./build for storing its data and it more and more seems like a rather bad choice, as users want to directly use things from this directory because they can see it is there (like executables, which contain a hash in their path), instead of using fpm to do the work to resolve paths.