Build fails with Fortran modules nammed with macros

Hello,

I am working on a Fortran project that simulates generic programming (or C++ type templates) with include files and macros. We have decided to replace our home-brew build system with CMake and, up to now, things have went pretty well.

I have made a really small example that shows the issue we are running into. It’s made up of 4 files:

square.inc:

module GEN_NAME(trigo_)
    implicit none
    contains

    DATATYPE function square(num)
        implicit none
        DATATYPE, intent(in) :: num
        square = num * num
    end function
end module

square.F90

#define DATATYPE integer
#define GEN_NAME(name) name/**/integer
#include "square.inc"
#undef GEN_NAME
#undef DATATYPE

#define DATATYPE real
#define GEN_NAME(name) name/**/real
#include "square.inc"
#undef GEN_NAME
#undef DATATYPE

main.F90

program main
    use trigo_real
    implicit none
    real, parameter :: py = 3.1416
    print *, 'I make square pies: ', square(py)
end program

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(test_generic_f90 LANGUAGES Fortran)
file(GLOB PROJECT_F_FILES *.F90)
add_executable(main ${PROJECT_F_FILES})

Building manually work fine:

gfortran -c square.F90
gfortran -o main main.F90 square.o

However, if I try to build this project with CMake, I get the following error:

Error copying Fortran module "gen_name.mod". Tried "GEN_NAME.mod" and "gen_name.mod".

It looks like CMake did not parse the macro to get the actual module name since I still see “GEN_NAME.mod” instead of “trigo_integer.mod” or"trigo_real.mod".

Is there a way I can fix this in my project or does it require changes in CMake?

Cheers!

1 Like

I suspect this is a gap in our Fortran support. I don’t know how much work it’d be to fix it. I suggest filing an issue with this example so we can at least track it.

Cc: @brad.king

With the Ninja generator, I’d expect this to work. It preprocesses using the real compiler before extracting module dependencies.

With the Makefile generators we use approximate preprocessing for dependency scanning, and it doesn’t expand macros. This approach predates the approach used by the Ninja generator. The Makefile generators will need updates to use the newer approach.

1 Like

Please be aware that there are Fortran files out in the wild which do not function correctly if preprocessed (e.g. they use identifiers which clash with common macro names such as DEBUG); this is especially tricky in targets which mix C[++] and Fortran files.

When we switched from Make to Ninja, we had to work around this by adding the compilation flag -Qoption,fpp,-macro=no to such files. When modifying the automatic-Fortran-preprocessing implementation in CMake, please keep such a workaround possible.

There is support for not compiling the preprocessed source now. See this MR which is in 3.18.0. I believe that scanning still requires preprocessing in Ninja though.

That same merge request also taught the Ninja generator to not run preprocessing before scanning when the Fortran_PREPROCESS property is off.

Thanks for the info. I somehow missed this when reading 3.18 release notes. We’re still at 3.14 at work, but I can add this to the pile of “reasons to upgrade.”