Fpm if statements or preprocessing

My Fortran project builds often need “if” build logic based on operating system and compiler, selecting source files that contain Fortran submodules. An alternative way to do this would be to build all the source files, enclosing the entire code with #ifdef __GFORTRAN__ or #ifdef __WIN32 etc.

Suppose pathlib.f90 with module “pathlib”, and then submodule functions where in CMake I use if(UNIX) to select “unix.f90” or “win.f90” and also “intel.f90” and “gcc.f90”. I changed these file extensions to .F90 and put #ifdef but it failed with fpm. Example: intel.f90 enclosed all contents with #ifdef __INTEL_COMPILER and fpm build errored when using GCC:

<ERROR>*cmd_build*:target error:Unable to find source for module dependency: "ifport" used by ".\src\intel.F90"
STOP 1

If I were able to in fpm.toml have statements like if: unix or if: gcc and include source files based on that, it would enable several of my projects to use fpm.

1 Like

I think having conditional logic in the fpm.toml could have several uses; but in your case where you want to select a specific file instead of ending your files with the suffix for .f90 or .F90 end them in .inc so fpm will not automatically include them in the build, and then make a simple file like OS.F90 and compiler.F90 that use cpp/fpp directives (or whatever your compilers support) to do an include on the file you want, and that will work if I understand what you want; although
currently I think fpm will not automatically rebuild if the *.inc files are changed but that might work (have not checked recently). Also note that include files can be placed in a special directory at the top of the project named include/, which is not emphasized in the documentation.

Features like this have been discussed, but were not pushed at the time as it is not straight-forward to pick up system information like a uname(1) command accesses portably from Fortran, and the assumption is routines like the POSIX routines (which exist in almost every compiler but under different names) would emerge in stdlib. That would make it almost trivial to add some conditional processing.

#ifdef __unix__
INCLUDE "unix.inc"
#else
INCLUDE "win.inc"
#endif

That might need refined but the general concept should work. There are other approaches that might work too; depends exactly what is in those files and whether the contents contain duplicate names and such.

OK and CMake could still recognize changes in those files with CMAKE_CONFIGURE_DEPENDS property. Meson likewise knows to handle Fortran include statements.

This technique worked for fortran-pathlib which can now build independently with FPM or CMake