1

我如何在“编译时”(例如使用预处理器)查明编译器是否支持特定的语言特性?我正在考虑的具体示例是NEWUNITFortran 2008 的说明符。我想做这样的事情:

#ifdef HAVE_NEWUNIT
! go ahead and use that
#else
! activate workaround
#endif

我标记了这个问题fortran,因为这是我目前关心的问题,尽管我怀疑一般答案可能必须超出 Fortran ( autoconf??)。当然,该解决方案应该与尽可能多的编译器一起使用,但大多数情况下,我关心的是gfortranand ifort(这两个都是NEWUNIT最近才引入的)。

澄清:

  1. 我正在寻找一种自动处理这种情况的方法。(其中可能不仅仅包括 Fortran 源文件——Makefiles ……)
  2. 我不太关心它是否是“标准的”,只要它能在大多数 Unix 类型的系统上工作。
4

2 回答 2

4

如果您打算使用 using 的路线autotools,具体而言autoconf,以下是我将其全部编码的方式。

创建configure.ac

dnl                                               -*- Autoconf -*-
dnl Process this file with autoconf to produce a configure script.
dnl

AC_PREREQ(2.61)
AC_INIT([test], [0.0.1], [me@example.com])

# Define our M4 macro directory
AC_CONFIG_MACRO_DIR([m4])

# Put our generated config header in the source directory
AC_CONFIG_HEADERS([src/config.h])

# Make sure we have a fortran compiler
AC_PROG_FC([ifort xlf pgfortran gfortran])
AC_LANG([Fortran])
AC_FC_FREEFORM

# Check for newunit option to open()
AX_F08_NEWUNIT

AC_OUTPUT

在子目录中创建ax_f08_newunit.m4宏。m4/因为这是我指定宏所在的位置configure.ac

AC_DEFUN([AX_F08_NEWUNIT], [

AC_REQUIRE([AC_PROG_FC])
AC_LANG_PUSH([Fortran])

AC_MSG_CHECKING([for NEWUNIT support])
AC_COMPILE_IFELSE([
       program conftest
       integer :: i
       open(newunit=i,file='test')
       end program conftest],
[ax_f08_newunit=yes], [ax_f08_newunit=no])

AC_LANG_POP([Fortran])

if test "x$ax_f08_newunit" = "xyes"; then
    AC_MSG_RESULT([yes])
    AC_DEFINE([HAVE_NEWUNIT], [1], [NEWUNIT support])
else
    AC_MSG_RESULT([no])
fi

])

然后遵循所有常规autotools程序:

aclocal -I m4
autoheader
autoconf

然后你可以运行./configure,这是我的输出:

checking for Fortran compiler default output file name... a.out
checking whether the Fortran compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU Fortran compiler... no
checking whether ifort accepts -g... yes
checking for Fortran flag needed to allow free-form source... -FR
checking for NEWUNIT support... yes
configure: creating ./config.status
config.status: creating src/config.h

最后在你的src/config.h文件中你应该有:

/* src/config.h.  Generated from config.h.in by configure.  */
/* src/config.h.in.  Generated from configure.ac by autoheader.  */

/* NEWUNIT support */
#define HAVE_NEWUNIT 1

/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "me@example.com"

/* Define to the full name of this package. */
#define PACKAGE_NAME "test"

/* Define to the full name and version of this package. */
#define PACKAGE_STRING "test 0.0.1"

/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "test"

/* Define to the version of this package. */
#define PACKAGE_VERSION "0.0.1"

当然,您的源代码现在也必须通过预处理器运行。例如src/test.F90

program test
#include "config.h"

integer :: i

#ifdef HAVE_NEWUNIT
  open(newunit=i,file='data')
#else
  i = 7
  open(unit=i,file='data')
#endif

end program test

编译测试程序的时候ifort明白大写的F表示需要对文件进行预处理。

于 2013-09-06T21:49:26.173 回答
1

(标准)Fortran 没有能力做你想做的事。我们中的大多数(?)(Fortran 程序员)会通过编译使用它的代码并研究编译器消息来测试新功能的可用性。我们还可以查阅编译器文档。

Fortran 预处理器不是由 Fortran 标准定义的,根据我的经验,通常是 C 预处理器,它们已经对 Fortran 进行了足够多的培训,几乎可以使用;想想教一只狗用两条腿走路,它永远不会是真正的双足动物,它非常擅长四足运动,那有什么意义呢?

暂时搁置我自己的偏见,除了尝试编译使用它的代码之外,没有标准的方法可以在编译时检查新功能的可用性。

早在 90 年代就有一份关于 Fortran 条件编译的技术报告(我认为),但它提出的语言扩展并没有在 Fortran 的最新版本中找到。

回应OP的澄清:

一种方法是效仿许多 Linux 软件并使用工具,例如automakeautoconf首先确定(在这种情况下)Fortran 编译器的功能,然后再编写(可能使用宏处理器)或选择必要的代码片段,从而构建一个可编译的程序。换句话说configuremakeinstall

由于在编译时确定在运行时需要一个新的单元号时可能正在使用哪些单元号绝非易事,我想您必须退回到从 pre 中选择新单元号的老式方法-您知道的定义范围(或者,如果代码足够大和复杂,只是希望)尚未使用。

于 2013-09-06T08:37:35.367 回答