2

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)?

V T
  • 103
  • 7
  • I'll comment that the Intel compiler has an option `-assume [no]source_include` that affects this behavior. I believe it is honored by the Intel fpp as well. I agree with @francescalus that #include is not part of the Fortran language. – Steve Lionel Feb 22 '23 at 20:48
  • @francescalus I meant only the `#include` command. I know that the behavior of `#include` is not part of the Fortran standard. But my question is, if there is a way to achieve the same results without writing cumbersome `#if` statements for each compiler (preferably without something like CMake). And if I understand it correctly, `include` cannot replace `#include`. – V T Feb 22 '23 at 21:40
  • @SteveLionel yes, I know. But I find the default behavior of the Intel compiler strange. Like described above, only the first `#include` statement should have the "full" path. – V T Feb 22 '23 at 21:43
  • My comment was about Fortran's include lines, not any particular preprocessor's `#include`. As you've clarified that part of the text, I've deleted my comment. – francescalus Feb 22 '23 at 21:46
  • @SteveLionel I tested it: `-assume [no]source_include` doesn't seem to affect anything in this example. – V T Mar 01 '23 at 10:42

1 Answers1

2

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
V T
  • 103
  • 7