Using fpm on both Windows and WSL on the same code
The Windows directory c:\foo is mapped to /mnt/c/foo on Windows Subsystem for Linux. If I run fpm build and fpm test for some code in c:\foo, and I then go to WSL and run the same commands in /mnt/c/foo, I get errors, I think because the WSL object files *.o are not the same as those on Windows. I resolve the error by manually deleting old .o and .mod files.
Is there a way to tell fpm to recompile all source files, even if it looks like the object file is more recent than the source file? Alternatively, could fpm have a command to get rid of object files and .mod files from previous compilations?
Well, there is not much we can do, if you have two different operation systems sharing the same filesystem. A similar issue will apply for using MSYS2 under Windows, which has different environments, like msys2, mingw64, or ucrt64, depending on the MSYS2 terminal you are using, but the identical name for the Fortran compiler.
One option which is useful when working with cross and native compilers on the same system is to use the exact name of the compiler rather than the general name, on Linux/x86_64 this would be x86_64-pc-linux-gnu-gfortran instead of gfortran. In case of MSYS2 this might still be insufficient to distinguish the different compilers.
There is no clear solution here in my opinion, we could expand the build hash and try to get as much information as possible from the environment to create unique hashes and allow switching from one compiler version to another. But keep in mind that this kind of detection must be fast because fpm is supposed to run it on every invocation.
That has been nagging me for a while, and the solution I would like to see is that the build directory include a platform name as well, which has worked for me for a long time. In my own case my build scripts create a directory combining the system type with the compiler. The first issue is there is no purely "fortranic" way to get a system type, as even the C uname(3c) function is not available on all platforms. It was very common for me where my build scripts grew up to have my code in a directory that was NFS mounted to a number of different platforms and I wanted to be able to build on all of them simultaneously but I had not seen people complaining about that, and git(1) lets you easily create a separate copy for each build if you want, so it had not come up till now. The info returned by COMPILER_VERSION(3f) and/or COMPILER_OPTIONS(3f) contains some system type info with some compilers and not with others so it is not a good choice.
For the problem you show I have using a kluge where I add "--flag -D Solaris" so you get a unique build. I was making a wrapper script for the compiler so I got unique build directory names that way too but that did not seem like a good way to go.
In my scripts by default the system type is determined by a command called "system_type" on each platform (that just calls uname(1) on the machines I run on now), but it does allow you to specify an environment variable instead. Don't want to overuse environment variables but maybe that is justified in this case.
We could try to harden up the routine that determines system type as well in fpm(1) now and use that as well. An environment variable like FPM_SYSTEM_TYPE might the way to go, but by default use what fpm(1) does now and improve on it as time passes. I would probably suggest both be used; the default being to add what the routine calculates, but since it is guessing have a failsafe in that the variable can be used when that fails.
I have been doing something similiar when on nodes that are the same type but have different versions of a compiler installed, or are allowing different versions to be used via the modules(1) command as well.
And of course deleting the build directory, or making a clone via "git clone" for a build work now; and another long-term option might be to allow you to specify the name of the build directory which also solves a problem where I might be another user who has read permission to a package but not write permission. So if I am the other user I have to make a complete copy of the package to build it because I do not have write permission to the build directory. git(1) is not required for fpm use, so doing a clone that way is not always possible either, and takes time and filespace.
Note since fpm(1) already determines system type every time it runs, albeit a bit simplistically, that speed is probably not a major issue. Maybe a compromise needs made to use an extension or conditional code, as calling uname(3c) would work on most platforms.
Do we not have the same issue if we use a cross compiler ? I am currently trying to create a cross compile environment to the Raspberry PI (I know, far away of the supercomputer you guys are used to :- ) . Ideally I would like to be able to compile the same source for the local machine (during most of the development) and sometime for the target (for test or release). I did not yet try it. Anyhow, this is a case where detecting the current OS is not good enough to select the proper tools and rules: On the one hand we have to use the rules of the current OS (for file path for example), on the other hand we have to use the rules of the target environment (for library names and extension) and finally the rule of the specific tool (name and options of the cross compiler and linker). I wonder if a concept of build environment (separate from the specification of the project and local to the builder) is not needed to support these cases.