Search path for `INCLUDE` line (and the unexpected behavior of `nagfor`)

When using nagfor 7.0, I notice that the search path for the INCLUDE line is not relative to the directory where the source file is located, but relative to where the compiler is invoked. For example,
the following file cannot be compiled unless I invoke the compiler from its parent directory:

! test.f90
program test
include "test.inc"  ! test.inc is in the same directory as the current file, i.e., test.f90
end program test

What is the intuition/motivation behind this particular design? How should I write test.f90 and place test.inc so that nagfor can compile test.f90 no matter where it is invoked? I hope not to use the -I option for such a simple program.

Fortran 2003 standard does not specify the searc path for the INCLUDE line (WHY?), but all other Fortran compilers I can find (gfortran, ifort, ifx, Absoft af95, flang, AOCC flang, nvfortran, sunf95, g95, Lahey lf95) include the parent directory of the source file by default (which seems quite intuitive and natural). That said, they can all compile the above file no matter where we invoke the compiler.

Just an observation: The Fortran standard does not prescribe a lot of things, such as the extension of source files or what compiler options should be available. All that sort of things are to the discretion of the compiler builder. And OSes may differ greatly in how their file system works. The now ubiquitous Linux or Windows system of directories and subdirectories and files is only one possibility.

1 Like

I agree, that the choice NAG made is probably less intuitive then how it works for other compilers. But you can simply add the -I . option, and it should work with all of them.

2 Likes

ifort lets you do it either way, with an option -assume source_include .

2 Likes

The NAG documentation states:

If the #include file name is enclosed in double-quotes ( "..." ), it is searched for first in the directory of the file with the #include line"

The compiler behavior, as reported in the OP, does not agree with this statement.

1 Like

Note the difference between include (standard Fortran) and #include non-standard preprocessor macro. The OP uses the first one. Apparently, the search rules differ for the two.

1 Like

Apparently the statement:

“Non-intrinsic modules, INCLUDE files and #include files are expected to exist in the current working directory or in a directory named by an -I option.”

found in

https://www.nag.com/nagware/np/r70_doc/nagfor.html#OPTIONS

must not be correct then; but that means that the many compilers that support a “#include” preprocessor directive would be a work-around. That is, change the INCLUDE to a #include and the filename suffix from .f90 to .F90. I would suspect everyone would prefer to use the standard Fortran directive but in this case I think the NAG approach would really be confusing with nested includes, especially if relative pathnames were used. The INCLUDE directive is very loosely defined so it does not have to permit relative path names either, of course. We used to get the source file for the OS and Fortran compiler and make local mods, and one of the changes we used to make was to allow and INCLUDE to read command output and URLs and pathnames with a hostname prefix that was like an scp(1) pathname. It was very useful as that could include a command that pulled the file from our local platform-independent file manager and archiving utility; and technically that did not make the compiler non-standard conforming

8 The interpretation of char-literal-constant is processor dependent. An
example of a possible valid interpretation is that char-literal-constant
is the name of a file that contains the source text to be included.

Since it could include command output it let you generate the code with a script or program or anything else, which made for REALLY flexible “pre-processing” where it was trivial to include build times, build platform information, and just about anything else you could think of; albeit not portably unless you were careful.

Seems like the -I solution is the easiest for single-depth includes, but the behavior described so far make me think nested INCLUDEs would still behave differently if there were relative pathnames used.

1 Like