如果编译器支持特定语言功能,如何在“编译时”(例如使用预处理器)找到?我想到的具体例子是Fortran 2008的NEWUNIT
说明符。我想做这样的事情:
#ifdef HAVE_NEWUNIT
! go ahead and use that
#else
! activate workaround
#endif
我正在标记这个问题fortran
因为这是我现在所关注的问题,尽管我怀疑一般答案可能超出Fortran(autoconf
??)。当然,该解决方案应该尽可能多地使用编译器,但大多数情况下,我关心的是gfortran
和ifort
(两者都是半近期引入NEWUNIT
。
澄清:
答案 0 :(得分:4)
如果您打算沿着使用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意味着文件需要预处理。
答案 1 :(得分:1)
(标准)Fortran并没有真正有能力做你想做的事情。我们中的大多数(?)(Fortran程序员)将通过编译使用它并研究编译器消息的代码来测试新功能的可用性。我们也可以参考编译器文档。
根据我的经验,Fortran预处理器没有Fortran标准定义,通常是C预处理器,它们已经足够教授Fortran几乎可用;想到教一条狗走两条腿,它永远不会是真正的双足,它完全擅长四肢运动所以重点是什么?暂时搁置我自己的偏见,没有标准的方法可以在编译时检查新功能的可用性,而不是尝试编译使用它的代码。
早在90年代就有一篇关于Fortran条件编译的技术报告(我认为),但它所提出的语言的扩展还没有进入最近版本的Fortran。
回应OP的澄清:
一种方法是跟随许多Linux软件的领导并使用诸如automake
和autoconf
之类的工具来首先确定(在这种情况下)Fortran编译器的功能,以及之后要么写(可能使用宏处理器),要么选择必要的代码片段,从而构建可编译的程序。换句话说,configure
,make
和install
。
由于在编译时确定在运行时需要新单元号时可能正在使用的单元编号远非微不足道我认为你必须依赖于选择新单元号的传统方法从您所知道的预定义范围(或者,如果代码足够大且复杂,只是希望)尚未使用。