Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28789 Discussions

Incosistent #include paths of ifort and ifx

V-T
New Contributor I
3,849 Views
Consider the following directory tree:
test.F90
b.inc
test/
├─ a.inc
└─ b.inc

With the following contents:

  • `test.F90`:
#include "test/a.inc"
end
  • `test/a.inc`:
#include "test/b.inc"
#include "b.inc"
#include "b.inc"
  • `test/b.inc`:
print*,"Hello from test/b.inc"
  • `b.inc`:
print*,"Hello from b.inc"

A similar example was already discussed hereRunning the compiled code with the Intel compiler (ifort 2021.8.0 and ifx 2023.0.0 on Ubuntu 18.04.2 LTS) without any flags leads to the following output:

 Hello from test/b.inc
 Hello from test/b.inc
 Hello from test/b.inc

After the first `#include "test/b.inc"` in `a.inc` the directory is "changed" to `test` for some reason and only `test/b.inc` is included in all consequent `#include` statements.

Is it the intended behavior of the preprocessor? Or is it a bug?

Labels (1)
0 Kudos
1 Solution
Barbara_P_Intel
Employee
2,842 Views

This fpp issue is fixed in the compiler versions released this week as part of 2024.0.

@V-T, please try the new compiler.



View solution in original post

0 Kudos
21 Replies
jimdempseyatthecove
Honored Contributor III
3,458 Views

Does this mean that there are two different fpp's? (or that ifx internally processes #include?)

FWIW, this looks like a file caching issue whereby the file name.type alone is the key as opposed to the complete path.

Thanks for posting this, I will keep this in mind.

Jim Dempsey

0 Kudos
V-T
New Contributor I
3,453 Views

@jimdempseyatthecove 

I didn't invoke fpp separately. It is the result of internal preprocessing by ifort and ifx.

I also don't think it is a file caching issue: the directory is literally "changed" to `test`. You can check it by adding a `test/c.inc` file and changing the last `#include "b.inc"` to `#include "c.inc"`.

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,448 Views

fpp isn't invoked seperately.

There is an option to the compiler to invoke fpp....

however, on Linux:

foo.F90 (uppercase F) implicitly adds the -fpp, whereas

foo.f90 does not.

 

On Windows, you must supply the fpp option.

In either case, ifort/ifx command will invoke fpp.

 

Jim Dempsey

 

0 Kudos
V-T
New Contributor I
3,446 Views

Sorry, I didn't formulate the sentence correctly. I meant that I didn't use fpp on `test.F90` in the first step and use ifx on the resulting preprocessed code in the second step (which, I think, should lead to the same result as the `ifx -fpp test.F90` command).

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,392 Views

>>Sorry, I didn't formulate the sentence correctly. I meant that I didn't use fpp on `test.F90` in the first step 

Maybe I did not state the clearly before.

With the upper case F on .F90, the compiler front end called fpp. So in a sense, by using .F90 (on Linux/Mac) as opposed to .f90, you told the compiler to preprocess the file with fpp.

 

Jim Dempsey

0 Kudos
V-T
New Contributor I
3,355 Views

No, everything is alright with your reply. I did understand you. I know that `ifx test.F90` and `ifx -fpp test.F90` is the same command (on Linux/Mac) due to uppercase `F` in the extension. I just wanted to clarify that I only used `ifx test.F90` instead of `fpp test.F90 > test.f90 && ifx test.f90`. I differentiated between this two commands because, in the case of the GNU compiler, the analogous commands `gfortran test.F90` and `cpp test.F90 > test.f90 && gfortran test.f90` can sometimes lead to different results. But it is not the case with the Intel compiler.

0 Kudos
Steve_Lionel
Honored Contributor III
3,418 Views

I tested this on Windows, with /fpp, and I reproduced the strange behavior.

0 Kudos
V-T
New Contributor I
3,353 Views
0 Kudos
andrew_4619
Honored Contributor III
3,376 Views

Jim the manual seems to disagree with you, I know not what is true however....

 

To quote:

By default, the preprocessor is not run on files before compilation. However, the Intel® Fortran Compiler automatically calls 
fpp when compiling source files that have file extension .fpp or .FPP, .f or .F, .f90 or .F90, .for or .FOR, .ftn or .FTN, and .fpp or .FPP.
For example, the following command preprocesses a source file that contains fpp preprocessor directives, then passes the preprocessed file to the compiler and linker:

 

ifort source.fpp

If you want to preprocess files that have other Fortran extensions than those listed, you have to explicitly specify the preprocessor by using compiler option 
fpp
.
0 Kudos
andrew_4619
Honored Contributor III
3,374 Views

additionally the fpp manual discusses search folder rules but only refers to "filename" or <filename> it gives no clue about adding path to the name which in any case is going to be operating system dependant. 

 

The standard Fortran  include statement e.g.

include 'filename' 

also does not discuss  the use of path within filename but for me 'filename' should be any string that is a valid absolute or relative URL for the OS being used.  Does this option have the same problem BTW?

0 Kudos
V-T
New Contributor I
3,352 Views

No, the Fortran `include` command (without `#`) doesn't have this problem. But all paths should be made relative to `test.F90` , i.e. changed to `include "test/b.inc"`, and no preprocessor lines are allowed in the included files.

0 Kudos
andrew_4619
Honored Contributor III
3,335 Views

I would agree it would make sense to have the relative paths anchored to the source directory but I was just commenting that the manual is silent on this matter so the "correct" behaviour is not defined. I personally would say it is a bug but it is really down to Intel to comment.

 

0 Kudos
Barbara_P_Intel
Employee
3,264 Views

gfortran won't even compile it!

$ gfortran test.F90
test/a.inc:2:2:
  2 | #include "b.inc"
    |  1~~~~~~~~~~~
Fatal Error: test/b.inc: No such file or directory
compilation terminated.

 

 

0 Kudos
V-T
New Contributor I
3,230 Views

Yes, of course, because the traditional cpp (which is used by gfortran) in contrast to fpp searches for the following files relatively to the file from which `#inlcude` is invoked (here: relatively to `test/a.inc`, not to `test.F90`). That's why `#include "test/b.inc"` is wrong because there is no `test/test/b.inc` file and only `#include "b.inc"` can be used. It was already discussed on Stack Overflow (the link is in the question). Personally, I find the approach of cpp more preferable than that of fpp, because it allows more flexible structures of chained `#include` statements. But this behavior can be affected in the Intel compiler with the flag `-assume [no]source_include` (like Steve Lionel said).

0 Kudos
V-T
New Contributor I
3,230 Views

No, I just tested it: `-assume [no]source_include` doesn't seem to affect anything in this example.

0 Kudos
Barbara_P_Intel
Employee
3,259 Views

I filed a bug report, CMPLRLLVM-45307. I'll let you know when a fix is available.



0 Kudos
Barbara_P_Intel
Employee
2,809 Views

After discussion with the compiler team, we determined that the reproducer is working as expected. Preprocessor behavior is defined by the implementer; there is no standard at this time.

According to the Fortran Developer Guide and Reference, the compiler searches for include files in this order:

  1. In the directory of the source file that contains the include
  2. In the current working directory
  3. In the directories specified by compiler option I
  4. In the directory specified by compiler option -isystem (Linux* and macOS only)
  5. In the directories specified with environment variables CPATH (Linux* and macOS) or INCLUDE (Windows*)
  6. In the standard system directories

ifort/ifx will always include test/b.inc since we first search the directory of the source file that contains include and a.inc's directory is "/test".

 

0 Kudos
V-T
New Contributor I
2,800 Views

If I understand you correctly, the preprocessor should search for a `b.inc` file in the `test` directory first, because the `a.inc` file is in this directory. However, replacing the contents of the `a.inc` file with:

#include "b.inc"
#include "b.inc"
#include "b.inc"

 will lead to the following output:

 Hello from b.inc
 Hello from test/b.inc
 Hello from test/b.inc

But according to your reply, all printed messages should have been `Hello from test/b.inc`. After the first `#include` statement, the directory is changed to `test` for some reason, and I find this behavior inconsistent.

0 Kudos
Barbara_P_Intel
Employee
2,777 Views

The compiler team is reevaluating with your new reproducer.



0 Kudos
Barbara_P_Intel
Employee
2,843 Views

This fpp issue is fixed in the compiler versions released this week as part of 2024.0.

@V-T, please try the new compiler.



0 Kudos
Reply