Reputation: 1889
I'm trying to emulate C asserts in Fortran in order to enforce pre- and post-conditions of all my procedures. This way, I get to provide the user with more detailed information about run-time errors than I could reasonably be expected to maintain otherwise.
In order to implement this, I used the preprocessor directives __FILE__
and __LINE__
, and defining an assert
macro which expands to a Fortran subroutine call. Rather than try to describe it here, I made a git repo with a little bit of example code in it. If you build it with
make test
./test
the function hangs, because you called a function that expects a positive argument with a negative one. However, if you build with
make test DEBUG=1
./test
the error is caught by an assertion.
This works with both gfortran and the Intel Fortran compiler. I don't have access to other Fortran compilers. Can I reasonably expect other compilers to do the necessary source pre-processing if the file extension is .F90
? Or should I be relying on the -cpp
flag? What's the most portable way to do this? Should I even do this at all?
Upvotes: 1
Views: 421
Reputation: 21431
It is reasonable to expect that a suitable "C-like" preprocessor is available, though undoubtedly there will be exceptions for some compilers or tools.
The definition of portability can depend on your perspective, but given that a large number of systems run with a case insensitive file system, it is not reasonable to solely rely on case alone to specify that the preprocessor needs to be run. Most Fortran related build systems will have some way of making that specification explicit.
Whether this is a good idea is a bit more subjective. Perhaps it is only nominal in terms of impact, but requiring the preprocessor still represents a reduction in portability and an increase in build complexity. Depending on compiler, use of the preprocessor may hinder use of things like standard conformance diagnostics.
Consequently, my preference for relatively simple use cases like this is to have the assertion coded as normal Fortran source - an if statement testing a named constant from a debug module or similar, invoking [ERROR] STOP (not exit
) with a descriptive message if the assertion expression fails.
USE DebuggingFlags
IF (debug_flag) THEN
IF (x <= 0) ERROR STOP 'negative or zero x in sqrrt!'
END IF
This won't give you file and line information, but as long as you are somewhat selective with the STOP message the relevant source shouldn't be too hard to locate.
"Release" builds are made with the debugging flag constant defined as false (or your chosen equivalent) and with any sort of reasonable compiler optimisation active the object code associated with the assertion should be identified and eliminated as dead.
But there are pros and cons.
Upvotes: 5
Reputation: 2518
Adding to the answer of @LeleDumbo:
As far as I can tell, the Fortran 2008 Standard does not specify any form of preprocessing. This does also mean, that there is no standard way of specifying, how to invoke the preprocessor. However, it is common practice to use .F90
to specify the need for preprocessing.
Concerning COCO: The third part of the Fortran Standard ISO 1539-3, which should specify conditional compilation, was withdrawn.
Upvotes: 0
Reputation: 9340
Fortran 95+ has conditional compilation (coco) defined in standard, but only few compilers support it. The de facto standard (since Fortran 90 I believe) is still cpp and fpp, which most compilers support. Both are highly compatible but not 100%. Using these facts, relying on cpp/fpp style preprocessor should be safe for most cases.
Upvotes: 0