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

Use #ifdef to skip call statements in Debug mode

frenchnq
Beginner
1,350 Views

All,

 

I have some call statements that I would like to be skipped over when I am in debug mode and used when in compiling a release.  I have turned FPP on.

 

I am trying to structure something as follows:

#ifdef DEBUG
#else
    call abcd...

#endif

 

Is there a better way to achieve this or can it be done this way?

 

Thanks

0 Kudos
4 Replies
jimdempseyatthecove
Honored Contributor III
1,329 Views

The use of #ifdef implies (requires) the use of the Fortran PreProcessor (-fpp)

If using fpp, then use fpp in Release build as well and:

#ifdef DEBUG

#define DEBUG_abcd(argX, argY) call abcd(argX, argY)

...

#else

#define DEBUG_abcd(argX, argY)

,,,

#endif

 

then

... ! your code

DEBUG_abcd(a, b)

''' ! more code

 

IOW you can define an assert and trace.

 

Jim Dempsey

0 Kudos
Ron_Green
Moderator
1,325 Views

It sounds like you are in Visual Studio on WIndows.  IF NOT, if you are on linux or macOS, if your filenames use upper case F, like .F90 or .F then fpp is invoked by default before the compilation. 

0 Kudos
IanH
Honored Contributor II
1,295 Views

When you conditionally compile chunks of source based on preprocessor conditionals, you accept that your program source has slightly different logic between release and debug builds.  Continuing to accept that, my preference is to not use the preprocessor (which may come with a set of subjective evils) and instead make the equivalent changes directly in normal, boring, Fortran source ... IF (debug) CALL abcd(..)

This means you need some way of changing that `debug` named constant or similar between release and debug builds.  One way to do this is by varying the source file for a module that contains the definition of that module between release and debug builds.  For example:

 

! In DebugMod_debug.f90
MODULE DebugMod
  IMPLICIT NONE
  
  LOGICAL, PARAMETER :: DebugFlag = .TRUE.
  INTEGER, PRIVATE :: log_unit = 0
CONTAINS
  SUBROUTINE DebugLog(text, value)
    CHARACTER(*), INTENT(IN) :: text
    INTEGER, INTENT(IN) :: value
    
    IF (log_unit == 0) THEN
      OPEN(  &
          NEWUNIT=log_unit,  &
          FILE='MyLoggingFile.txt',  &
          ACTION='WRITE',  &
          STATUS='REPLACE' )
    END IF
    WRITE (log_unit, "(A,T60,I0)") text, value
  END SUBROUTINE DebugLog
END MODULE DebugMod



! In DebugMod_release.f90
MODULE DebugMod
  IMPLICIT NONE
  
  LOGICAL, PARAMETER :: DebugFlag = .FALSE.
CONTAINS
  SUBROUTINE DebugLog(text, value)
    CHARACTER(*), INTENT(IN) :: text
    INTEGER, INTENT(IN) :: value
    
    ! Do nothing
  END SUBROUTINE DebugLog
END MODULE DebugMod

 

perhaps used in an example program...

 

PROGRAM MainProgram
  USE DebugMod
  IMPLICIT NONE
  
  INTEGER :: value
  
  value = 10
  
  ! Useful program logic elided...
  
  IF (DebugFlag) THEN
    IF (value == 10) PRINT *, 'All good'
  END IF
  
  ! Useful program logic elided...
  
  CALL DebugLog('The value of value ended up being ', value)
  
END PROGRAM MainProgram

 

Within Visual Studio you can use the "Exclude File From Build" file specific property to determine which source file ends up contributing the DebugMod module.  In the following I am doing a Debug build, so the DebugMod_release.f90 file is excluded from the build.

IanH_0-1651786009731.png

 

Compile optimisers have been smart enough for several decades now, that they will compile time eliminate execution of IF on a constant logical value.  Compilers with inter-procedural optimisation are also likely to knock out calls to a subroutine that has no effect.

The Fortran module dependency determination step of the build within Visual Studio may issue a warning about multiple files contributing the same module, but this appears to be cosmetic.

Other sane build systems will have similar mechanisms for selecting source files based on the nature of a build.

0 Kudos
FortranFan
Honored Contributor III
1,285 Views

@frenchnq ,

 

Re: "Is there a better way to achieve this or can it be done this way?," can you please explain what would constitute a "better way" for you?

 

If by a "better way" you mean to not needing to use a preprocessor but you do intend to stick to Intel Fortran on Windows, you can consider predefined processor symbols along with Intel's directive-enhanced compilation option. 

See this link.

And consider this example that is usable from Visual Studio as well:

 

module m
   !dir$ if defined (_DEBUG)
   logical, parameter :: DEBUG = .true.
   !dir$ else
   logical, parameter :: DEBUG = .false.
   !dir$ end if
contains
   subroutine sub()
      if ( DEBUG ) then
         print *, "In debug mode"
      end if
      print *, "Hello World!" 
   end subroutine 
end module
   use m
   call sub()
end 

 

  • So when DEBUG mode is not in effect, the program works as below

 

C:\Temp>ifort p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.3.0 Build 20210609_000000
Copyright (C) 1985-2021 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.29.30038.1
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:p.exe
-subsystem:console
p.obj

C:\Temp>p.exe
 Hello World!

 

 

  • But with DEBUG mode, it will be like so: note no explicit prepreprocessing on your part is required.

 

C:\Temp>ifort /dbglibs p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.3.0 Build 20210609_000000
Copyright (C) 1985-2021 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.29.30038.1
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:p.exe
-nodefaultlib:libcpmt
-subsystem:console
p.obj

C:\Temp>p.exe
 In debug mode
 Hello World!

 

 

0 Kudos
Reply