预处理器和使用关联

4
总之,通过使用关联,可以访问在Fortran模块中定义的预处理器指令吗?
背景:我使用预处理器语句来定义打印警告和错误消息的子程序。例如,我使用以下模块/子例程,在文件“errors.f”中打印警告消息。
module errors
  use, intrinsic :: iso_fortran_env, only : error_unit=>stderr
  implicit none
  contains

    !> Print formatted warning message.
    subroutine warn_print( file, line, mesg )
      implicit none
      character(len=*), intent(in) :: file
      integer,          intent(in) :: line
      character(len=*), intent(in) :: mesg

      write(stderr,'(a,a,a,i4,a,a)') "WARNING::", file, ":", line, ": ", mesg

  end subroutine warn_print

end module errors

而且,在一个单独的文件errors.h中,我使用上述模块并定义了一个预处理器宏。

use errors

#define warn( text )warn_print(__FILE__,__LINE__,text)

我会在需要使用警告打印程序的任何文件/模块中,#include文件errors.h,这样我就可以简单地编写:

call warn("Some warning message")

编译器将自动包含调用警告消息的文件和行号。

问题

在Fortran代码中,使用 #include 'errors.h' 是相当个性化的,它隐藏了 errors 模块的使用。理想情况下,我更喜欢在 errors 模块本身中定义上述预处理器。然而,在使用该模块时,这个预处理器指令对于 use 该模块的程序/模块不可用。

有没有一种方法可以通过 use 关联使预处理器指令可访问?

我能想到的唯一另一种方法是只有 errors 模块并在调用编译器时定义预处理器指令(例如使用 ifort 的 -D 标志)。如何实现以上目标的任何替代方案都将不胜感激。

2个回答

2
不,这是不可能的,因为预处理和编译阶段完全独立于彼此,而C预处理器不知道Fortran USE语句的任何信息。
我通常在大多数.F90源文件中使用#include 'config.h' (来自autoconf),没有问题。

我也是这么想的,这就是为什么我使用我在问题中描述的设置。我希望能够得到其他人对于实现一个函数以打印调用它的文件和行号的不同方案的建议。欢迎来到So! - Chris

1

这可能不是您正在寻找的内容,但如果您正在使用ifort,则可以使用回溯功能来实现类似的功能(更强大但也更丑陋),例如:

program tracetest
  call sub(5)
  write(*,*) '=== DONE ==='
end program tracetest

subroutine sub(n)
  use ifcore
  integer :: n
  character(len=60) :: str
  write(str,*) '=== TROUBLE DETECTED: n =',n  ! code -1 means "do not abort"      
  call tracebackqq(str,-1)    
end subroutine sub

然后,使用-traceback编译以查看源文件、行和堆栈跟踪。由于内联可能会导致堆栈跟踪和行被遮蔽,为了避免这种情况,您可以指定-traceback -O0来获取类似以下的内容:

=== TROUBLE DETECTED: n =           5                      
Image              PC                Routine            Line        Source             
a.out              0000000000473D0D  Unknown               Unknown  Unknown
a.out              0000000000472815  Unknown               Unknown  Unknown
a.out              0000000000423260  Unknown               Unknown  Unknown
a.out              0000000000404BD6  Unknown               Unknown  Unknown
a.out              0000000000402C14  sub_                       12  tracetest.f90
a.out              0000000000402B18  MAIN__                      2  tracetest.f90
a.out              0000000000402ADC  Unknown               Unknown  Unknown
libc.so.6          000000323201EC5D  Unknown               Unknown  Unknown
a.out              00000000004029D9  Unknown               Unknown  Unknown
=== DONE ===

或者,如果想保留优化,并且还想看到正确的行(12),可以使用(例如)-fast -traceback -debug all,inline_debug_info进行编译。其他编译器可能也有类似的选项,但我不确定。


谢谢@laxxy - 我之前不知道这个。这是一个好答案,但不幸的是它不具备可移植性。如果有人有类似的可移植功能版本,那将会很有趣。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接