I’m wondering if there’s any support for using a preprocessor to generate different versions of a file which are all expected to be compiled into a single library. In meson I would use compiler.preprocess.
E.g. I have a file foo.F90 that should be compiled into foo_r32.f90 and foo_r64.f90 and I want to create a single library that allows for using either.
foo.F90
module foo_MYPRECISION
...
end module foo_MYPRECISION
There is a kind of “poor man’s template” pattern I’ve seen people use. Something like
module foo_real32
use iso_fortran_env, only: wp => real32
contains
include "impl.inc"
end module
module foo_real64
use iso_fortran_env, only: wp => real64
contains
include "impl.inc"
end module
! impl.inc
subroutine stuff(x)
real(wp) :: x
...
end subroutine
subroutine other(y)
real(wp) :: y
...
end subroutine
...
Not sure if it’s feasible in your situation, but it does avoid the need for a preprocessor.
I use that method exactly. Sometimes I mix INCLUDE and other preprocessors so I might use something just like what you show but use the fpp/cpp #include with a #define right before that sets something like #define mytype real32 and then have some conditional #if/#else/#endif in the file based on the defined variable(s).
I have not called INCLUDE a “Poor man’s template” but I have called it the most minimalist preprocessor of any computer language.
Funny, I do something almost exactly opposite. I have a module that defines kinds:
module mo_kind
use, intrinsic :: iso_c_binding, only: c_float, c_double, c_long, c_int, c_bool
implicit none
public
integer, parameter :: dp = c_double, sp = c_float, i8 = c_long, i4 = c_int
!
! Floating point working precision
!
#ifdef USE_SP
integer, parameter :: wp = sp
#else
integer, parameter :: wp = dp
#endif
!
! Logical - for use with kernels
!
! Note that c_boolians don't work with PGI compiler currently
!
#ifdef USE_CBOOL
integer, parameter :: wl = c_bool
#else
integer, parameter :: wl = kind(.true.)
#endif
end module mo_kind
which other modules all rely on:
! -------------------------------------------------------------------------------------------------
module mo_foo
use mo_kind, only: wp, wl
contains
function a(x, y)
real(wp), intent(in) :: x, y
logical(wl) :: a
...
end function
end module
This mean I have a default value and need to compile with -DUSE_SP if I want everything to be in single precision
Thanks for the suggestions. In this case, we have something the team is happy with and I was hoping to add fpm support on top of it rather than changing the code.
I think I’ll just look into making the fpm build work with either real64 or real32 rather than both at the same time. Which is a shame because it means it’s not going to be quite as good as the meson build.
Since you are already using the C-like preprocessor, it sounds like you just need to add a macro for use as a suffix for each procedure name. Then define the macro to a value like “r32” or “r64”.
Once done, you can then create a module that USEs the two modules, and associates each of the two specific procedures with a generic name. E.g.,
module foo
use foo_r32
use foo_r64
implicit none
interface foo_sub1
module procedure foo_sub1_r32
module procedure foo_sub1_r64
end interface
end module
Strip all the subroutines and functions into a separate file. Then just #include the file twice in the foo module. Do the appropriate #defines before each #include. (Will have to do #undef between them.)