Search code examples
fortranpreprocessorintel-fortrannag-fortran

Relative include paths of different Fortran preprocessors


Consider the following directory tree:

test.F90
test/
├─ a.inc
└─ b.inc

With the following file contents:

  • test.F90:
#include "test/a.inc"
end
  • a.inc:
#if defined(__GFORTRAN__) | defined(__PGI) | defined(__NVCOMPILER)
#  include "b.inc"
#else
#  include "test/b.inc"
#endif

#include "b.inc"
#include "b.inc"
  • b.inc:
print*,'!'

The GNU (gfortran 11.1.0) and Nvidia (nvfortran 22.9) compiler preprocessors search for the file to be included in the directory relative to the current file. E.g. b.inc should be included inside of a.inc with #include "b.inc".

The Intel (ifort 2021.8.0, ifx 2023.0.0) and NAG (nagfor 7.1) compiler preprocessors search for the file to be included in the directory relative to the first file to invoke #include. E.g. b.inc should be included inside of a.inc with #include "test/b.inc" because a.inc is included in test.F90. However, it only applies for the first #include command. In all consequent #include commands, the directory is "changed" to test and #include "b.inc" can be used. While multiple #include "test/b.inc" commands also work in the Intel compiler, the code doesn't compile with the NAG compiler if the consequent paths are changed to test/b.inc.

Is this the intended behavior of the Intel and NAG compiler preprocessors? Is there a way to make the behavior of the #include command independent of the used compiler (and avoid the first 5 lines in a.inc)?


Solution

  • Intel and NAG have replied and agreed that this behavior is a bug of their preprocessors (fpp and fdfpp, respectively). This bug will be fixed in future releases. (The bug report for the Intel compiler is CMPLRLLVM-45307.)

    A somewhat not very elegant solution to make this preprocessor behavior compiler-independent is to change the directory tree: distribute the files in different folders on the same level, and, in the path of #include, always go up one level in the directory tree first and then to the desired file.

    Example

    • Directory tree:
    d1/
    ├─ test.F90
    └─ b.inc
    d2/
    ├─ a.inc
    └─ b.inc
    
    • d1/test.F90:
    #include "../d2/a.inc"
    end
    
    • d2/a.inc:
    ! Even though "d2/b.inc" is in the same directory as "d2/a.inc", go up one level first
    #include "../d2/b.inc"
    #include "../d2/b.inc"
    
    #include "../d1/b.inc"
    
    • d2/b.inc:
    print*,'Hello from d2/b.inc'
    
    • d1/b.inc:
    print*,'Hello from d1/b.inc'
    

    All compilers will print the expected output:

     Hello from d2/b.inc
     Hello from d2/b.inc
     Hello from d1/b.inc