gfortran compiler directive to add/remove compiler option - fortran

I would like to temporarily disable a gfortran compiler option for a piece of Fortran code. I am looking for something like:
!GFORTRAN$ PUSH_OPTION(-fcheck=bounds)
SUBROUTINE FOO(BAR)
INTEGER BAR(*)
! ...
END SUBROUTINE FOO
!GFORTRAN$ POP_OPTION
It looks like gcc/g++ do not have such compiler directive. Is that possible to achieve that with gfortran?

Related

What does # before IF and ENDIF mean

I know how to use IF and ENDIF in Fortran, but in many codes I have from others, there is a # sign before the IF, what does that mean?
!USES:
#if ( defined X )
use Y
#endif
These are pre-compiler macros, and not Fortran statements. They do the same as regular if statements, only at compile time and with a slightly different syntax.
Note that pre-processor directives are not part of any Fortran Standard, and that they are not supported by every compiler. Generally, they are identical to C pre-processor directives, but not always.
#ifdef and #endif are preprocessor directives.
suppose you had a file:
! test.F:
program A
x=1
#ifdef NEW
x=0
#endif
write(*,*) x
end
if you compile it using a preprocessor:
ifort -DNEW test.F -o a.out
you should get x =0
otherwise if you compile without -DNEW like
ifort test.F -o a.out
in that case you get x=1. The code inside the ifdef is not compiled. Here are compile time options for gfortran.. A useful situation for example is this question.

Can CPP preprocessing statement in Fortran be indented?

I am fairly new to use Fortran preprocessing statement and have a question which is probably pretty native. Can Fortran preprocessing statement be indented? I tested using Gfortran 4.8.1 on Linux (openSUSE Leap) and it turned out I it can not be indented at all.
The following code main.f90 works with gfortran -cpp main.f90 -o main:
program main
implicit none
#ifdef DEBUG
print *, "I am in debug mode"
#endif
print *, "hello world!"
end program main
But the following throws an error:
program main
implicit none
#ifdef DEBUG
print *, "I am in debug mode"
#endif
print *, "hello world!"
end program main
The error message is Error: Invalid character in name at (1).
Does this mean that we should always write the preprocessing statement from the first beginning of the line or it is just a compiler specific rule? Any help would be greatly appreciated and thanks in advance!
No, they cannot be indented because gfortran runs CPP in traditional mode which does not allow indentation. They must always start in the first column.
You could run CPP manually, but be very very careful about that.
If you use the // string concatenation operator somewhere the preprocessor would treat it as a comment. You must use the -C flag as shown by #ewcz in his/her answer which disables discarding of comments.
Some compilers supply their own FPP preprocessor which behaves differently.
you could use the C preprocessor to do the processing and then compile the processed file, i.e., assuming that your program is in main.f90, then something like:
cpp -nostdinc -C -P -w main.f90 > _main.f90
gfortran -o main _main.f90
In this connection, this question is quite useful: Indenting #defines

Stringify macro with GNU gfortran

How can I stringify a preprocessor macro with GNU gfortran? I would like to pass a macro definition to GNU gfortran which will then be used as a string in the code.
Effectively I would like to do this:
program test
implicit none
character (len=:), allocatable :: astring
astring = MYMACRO
write (*, *) astring
end program test
and then build with:
gfortran -DMYMACRO=hello test.F90
I tried creating various macro, for example:
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
...
astring = STRINGIFY(MYMACRO)
but this doesn't work with the gfortran preprocessor.
I also tried using a different style of macro:
#define STRINGIFY(x) "x"
...
astring = STRINGIFY(MYMACRO)
but this just creates a string containing the text 'MYMACRO'.
I then tried changing the macro definition to:
-DMYMACRO=\"hello\"
but this caused unrelated problem in the build process.
Thank you for your help
Your attempt to use the well-known stringification recipe of the C preprocessor,
viz:
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
fails for two reasons, each sufficient by itself.
First and simplest, the source file in which you attempt to employ it apparently
has the extension .f90. What this extension signifies to gfortran (and to
the GCC compiler driver, by any other name) is: Free form Fortran source code that should not be preprocessed.
Similarly .f95, .f03 and .f08. If you want gfortran to infer that a source
file contains free form Fortran code that must be preprocessed, give it one of
the extensions .F90, .F95, .F03 or .F08. See the GCC documentation of
these points
Even if you do that simple thing, however, the second reason bites.
The use of the C preprocessor to preprocess Fortran source is as old as C
(which though old, is much younger than Fortran). gfortran is obliged not
to break ancient working code; so, when it invokes the C preprocessor,
it invokes it in traditional mode. The traditional mode of the C preprocessor
is the way in which the preprocessor behaved prior to the first standardization
of the C language (1989), insofar as that unstandardized behaviour can be pinned down. In traditional
mode, the preprocessor does not recognize the stringizing operator '#', which was
introduced by the first C Standard. You can verify this by invoking the preprocessor
directly like:
cpp -traditional test.c
where test.c contains some attempt to employ the stringification recipe. The
attempt fails.
You cannot coax gfortran on its own to work the the stringification recipe.
But there is a workaround. You can invoke cpp directly, unencumbered by traditional mode,
to preprocess the Fortran source in which you want the stringification done and relay its
output to gfortran. If you already know this and were looking for a gfortran-alone
solution you need read no further.
Doing the stringification in your test source this way would look like:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' '-DMYMACRO=STRINGIFY(hello)' test.f90
The output of that is:
# 1 "test.f90"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.f90"
program test
implicit none
character (len=:), allocatable :: astring
astring = "hello"
write (*, *) astring
end program test
And that output is what you want to to compile. You could accomplish that as well by:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' test.f90 > /tmp/test.f90 \
&& gfortran -o test /tmp/test.f90
Then you will find that ./test exists and that executing it outputs hello.
You can eliminate the intermediate temporary file with further refinement. Your F90 source
code will compile as F95, as the latter is conservative of the former. So you can take
advantage of the fact that GCC will compile source piped to its standard input if
you tell it what language you are piping, using its -x language option. The
Fortran dialects that you may specify in this way are f77, f77-cpp-input, f95
and f95-cpp-input, where the -cpp-input prefix denotes that
the source is to be preprocessed and its absence denotes that it is not. Thus
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' test.f90 | gfortran -x f95 -o test -
works as well as the previous solution, minus the temporary file, and emits
the innocuous warning:
Warning: Reading file '<stdin>' as free form
(Note and retain the final - on the commandline. That is what tells gfortran to
compile the standard input.). The meaning of -x f95 brings the additional
economy that the source, which is preprocessed by cpp, is not preprocessed
again by the compiler.
The use of the option -std=c89 when invoking cpp calls for a cautionary
explanation. It has the effect of making cpp conform to the earliest C Standard.
That is as close to -traditional as we can get while still availing of the
#-operator, on which the stringification recipe depends, But with it you embrace
the possibility of breaking some Fortran code if you preprocess it this way;
otherwise gfortran itself would not enforce -traditional. In the case of
your test program, you could safely omit -std=c89, allowing cpp to conform
to the default C standard when it was built. But if you permit it or direct it
to conform to -std=c99 or later, then the standard will mandate recognition
of // as the beginning of a one-line comment (as per C++), by which any line
of Fortran that contains the concatenation operator will be truncated at the
first occurrence.
Naturally, if you use are using make or another build system to build the
code in which you want the stringified macros, you will have a way of telling
the build system what actions constitute compiling a given class of compilable
files. For any Fortran source file fsrc you wanted to compile with
a stringification preamble, the actions to specify would be in the vein:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' fsrc.f90 | gfortran -x f95 -c -o fsrc.o -
Although this is an old and answered question, I wanted to achieve macro stringification in gfortran without changing the default preprocessor or build process. I found that the preprocessor would do what I want, as long as there was no initial quotation mark on the line, therefore the desired stringification can be achieved by breaking lines with ampersands:
astring = "&
&MYMACRO"
A caveat is that this really only works with the traditional preprocessor, and for examples breaks with intel ifort compiler, which is too smart to fall for this trick. My current solution is to define separate stringification macros for gfortran as:
#ifdef __GFORTRAN__
# define STRINGIFY_START(X) "&
# define STRINGIFY_END(X) &X"
#else /* default stringification */
# define STRINGIFY_(X) #X
# define STRINGIFY_START(X) &
# define STRINGIFY_END(X) STRINGIFY_(X)
#endif
program test
implicit none
character (len=:), allocatable :: astring
astring = STRINGIFY_START(MYMACRO)
STRINGIFY_END(MYMACRO)
write (*, *) astring
end program test
It looks really ugly, but it does get the job done.
Removing the quotes around x in STRINGIFY solved the problem for me:
#define STRINGIFY(x) x ! No quotes here
program test
implicit none
character (len=:), allocatable :: astring
astring = STRINGIFY(MYMACRO)
write(*,*), astring
end program test
Compiled with
gfortran -cpp -DMYMACRO=\"hello\" test.f90
The -cpp option enables the preprocessor for all extensions.

two fortran questions

Is there any way for gfortran to compile a f90 program but with a non-f90 extension, or even no file extension at all?
How to suppress pause statement warning used in a f90 program when compiled with gforTRan?
Many thanks.
gfortran -c sourfile.xyz does not work. I know the manpage explains these options, but I did not find one working.
I mean in my f90 program, I have a pause statement. If I compile it, I got a warning saying the use of pause is obsolete. I want to suppress this warning during compilation.
Suppress all warnings with -w option?

Pre-processing !DEC$ directives in gfortran

I've got a large Fortran codebase that originally targeted Intel's compiler. I'm now gearing up to compile with gfortran. Unfortunately, the code is littered with Intel-style pre-processing directives like:
!DEC$ IF DEFINED (MYDIRECTIVE)
REAL, DIMENSION(:,:,:), ALLOCATABLE :: my_real_var
!DEC$ ENDIF
From what I can tell via googling and the gfortran docs, there is no internal gfortran support for anything besides C-style pre-processing, like:
#if defined MYDIRECTIVE
REAL, DIMENSION(:,:,:), ALLOCATABLE :: my_real_var
#endif
Has anyone else encountered this problem and come up with an elegant solution? Obviously, I could write a shell script which calls an external pre-processor before passing code to gfortran for compile, but this just doesn't seem like a terrific solution to me.
Any thoughts? Thanks SO gurus!
Intel ifort understands the C-style preprocessor directives, so it might be easiest to convert your files to that style. Then you would have a single code base that would work with both compilers. There would be some work regression testing the converted code with ifort.