Previous: C++ Compiler, Up: Compilers and Preprocessors


5.10.5 Fortranコンパイラの特徴

AutoconfのFortranサポートは,二つのカテゴリに分けられました.これまでの Fortran 77マクロ(F77)と,現在のFortramマクロ(FC)です.前者 は伝統的なFortram 77コードを想定していて,F77FFLAGS,そ してFLIBSといった出力変数があります.後者は,より新しいFortranの 標準の元でコンパイル可能(または必須)である,より新しいプログラムを想定し ていて,FCFCFLAGS,そしてFCLIBSといった出力変数が あります.

二つの新しいマクロAC_FC_SRCEXTAC_FC_FREEFORM(以下を参照) 以外では,FCF77のマクロの動作はほとんど同じなので,この セクションでまとめて説明しています.

— Macro: AC_PROG_F77 ([compiler-search-list])

使用するFortran 77コンパイラを決定します.F77が環境変数でまだ設定 されていない場合,g77f77,そしてその他の名前を調査します. 見つかったコンパイラ名を,出力変数F77に設定します.

しかし,このマクロはオプション引数を用いて呼び出すことが可能で,指定する 場合は,検索するFortran 77コンパイラをスペースで区切ったリストにする必要 があります.これで,ユーザがFortran 77コンパイラに対する代わりの検索リス トを指定する機会が与えられます.例えば,デフォルトの順序がいやな場合は, 以下のようにしてAC_PROG_F77を呼び出すことが可能です.

          AC_PROG_F77(fl32 f77 fort77 xlf g77 f90 xlf90)

g77(GNU Fortran 77コンパイラ)を使用している場合, AC_PROG_F77はシェル変数G77を‘yes’に設定します.出力変 数FFLAGSが環境変数で設定されていない場合,g77に対して ‘-g -O2’(‘-g’を受け入れないg77では‘-O2’)を設定し, 他のFortran 77コンパイラでは‘-g’を設定します.

— Macro: AC_PROG_FC ([compiler-search-list], [dialect])

使用するFortranコンパイラを決定します.FCが環境変数でまだ設定され ていない場合,dialectが検索しているFortran dialect何かを示すヒン トになります.デフォルトとして,利用可能なdialectの最も新しいものを検索 します.見つかったコンパイラ名を出力変数FCに設定します.

デフォルトで,より新しいdialectがより古いdialectに代わって選択されますが, dialectが指定されている場合,指定されているdialectで始まる,より 古いdialectが選択されます.dialectは,現在Fortran 77,Fortran 90, またはFortran 95が可能です.しかし,これは選択されるコンパイラの名 前のヒント(例えば,f90またはf95)になるだけで,特定の言語 の標準を実際にサポートしていることへの保証は試みません.このため, dialectオプションを避け,AC_PROG_FCだけを最も新しいFortran 標準に互換性のあるコード対して使用した方が良いでしょう.

また,このマクロは,最初のオプション引数を指定して呼び出される場合,それ は,AC_PROG_F77と同様に,検索するFortranコンパイラをスペースで分 離したリストにする必要があります.

出力変数FCFLAGSが環境変数で設定されていない場合,GNU g77に 対してはそれを-g -02に(または,g77-gを受け入 れないところでは-O2に)設定します.それ以外では,すべてのFortran コンパイラに対し,FCFLAGS-gに設定します.

— Macro: AC_PROG_F77_C_O
— Macro: AC_PROG_FC_C_O

Fortranコンパイラが,オプション‘-c’と‘-o’を同時にを受け入れる かどうかテストし,そうでない場合は,それぞれ F77_NO_MINUS_C_MINUS_OまたはFC_NO_MINUS_C_MINUS_Oを定義し ます.

以下のマクロは,Fortranコンパイラの特徴を調査します.ここでリストアップ されていない特徴を調査するために,現在の言語(see Language Choice)が Fortran 77またはFortranに設定されていることをAC_LANG(Fortran 77)AC_LANG(Fortran)で最初に確認し,AC_COMPILE_IFELSE (see Running the Compiler)やAC_RUN_IFELSE (see Run Time) を使用してください.

— Macro: AC_F77_LIBRARY_LDFLAGS
— Macro: AC_FC_LIBRARY_LDFLAGS

Fortranプログラムや共有ライブラリをうまくリンクするために必要な Fortranのイントリンシックとランタイムライブラリ(Fortran intrinsic and run-time libraries)に対して,リンカフラグ(例えば‘-L’ と ‘-l’)を決定します.出力変数 FLIBSFCLIBSには,これら のフラグが設定されます(それらはリンク時にLIBSの後に含めるべきです).

このマクロは,単一のプログラムや共有ライブラリに,例えば,C++とFortranの ソースコードを混在させる必要があるとき利用されます(see Mixing Fortran 77 With C and C++).

例えば,C++とFortranコンパイラで生成されるオブジェクトファイルを,お互い にリンクする必要があるとき,リンクにはC++コンパイラ/リンカが使用されるは ずです(C++特有のものは,リンク時にグローバルコンストラクタ,インスタンス テンプレート,例外処理等を呼び出す必要が生じるためです).

しかし,Fortranのイントリンシックとランタイムライブラリもリンクする必要 がありますが,C++コンパイラ/リンカは,これらのFortranライブラリを追加す る方法をデフォルトでは知っていません.そのため,これらのFortranライブラ リを決定するマクロが作成されました.

マクロAC_F77_DUMMY_MAIN/AC_FC_DUMMY_MAINAC_F77_MAIN/AC_FC_MAINは,FortranでC/C++にリンクする必要が あるときもおそらく必要です.以下を参照してください.

— Macro: AC_F77_DUMMY_MAIN ([action-if-found], [action-if-not-found])
— Macro: AC_FC_DUMMY_MAIN ([action-if-found], [action-if-not-found])

多くのコンパイラでは,AC_F77_LIBRARY_LDFLAGSAC_FC_LIBRARY_LDFLAGSで見つかるFortranライブラリは,Fortran I/Oの ようなものを初期化したり,ユーザプログラムを実行するために,(いわゆる) MAIN__のような名前を持つユーザ提供のエントリー関数を呼び出す,独 自のmainエントリー関数を提供しています. AC_F77_DUMMY_MAIN/AC_FC_DUMMY_MAINAC_F77_MAIN/AC_FC_MAINマクロは,この相互作用を扱う方法を理 解します.

(I/Oなどではない)純粋な数値関数のためにFortranを使用しているとき,独自の mainを提供し,Fortranライブラリの初期化を停止したいこともよくあり ます.しかしこの場合は,いくつかのシステムでのリンクエラーを避けるため, ダミーのMAIN__ルーチンを提供する必要があるかもしれません. AC_F77_DUMMY_MAINAC_FC_DUMMY_MAINは,そのようなルーチン がリンク時に要求されているかどうか,そしてその名前が何かを検出し ます.シェル変数F77_DUMMY_MAINF77_DUMMY_MAINは,解決方法 が見つからないときはunknown,そのようなダミーのmainが不要 なときはnoneという値を保持します.

デフォルトで,必要な場合は,action-if-foundF77_DUMMY_MAINFC_DUMMY_MAINをこのルーチン名(例えば MAIN__)に定義します.[action-if-not-found]はデフォルトでエラー で終了します.

Fortranとリンクするために,必要な場合はダミーのmainを定義するため に,userのC/C++プログラムで以下のようなコードをインクルードすべきです.

          #ifdef F77_DUMMY_MAIN
          #  ifdef __cplusplus
               extern "C"
          #  endif
             int F77_DUMMY_MAIN() { return 1; }
          #endif

(Fortran 77ではなくFortranに対しては,F77FCで置換して下 さい.)

このマクロははAC_F77_WRAPPERSAC_FC_WRAPPERSから自動的に 呼び出されることに注意してください.一般的にデフォルトの動作を変更したく ない限り,明示的にに呼び出す必要はありません.

— Macro: AC_F77_MAIN
— Macro: AC_FC_MAIN

上で議論したように,Fortranライブラリには,通常のmainの代わりに, (いわゆる)MAIN__と呼ばれるエントリーポイントを提供することが可能 なものも多く,それは,Fortran I/Oのようなものを初期化するために,Fortran ライブラリのmain関数で呼び出されます. AC_F77_MAIN/AC_FC_MAINマクロは,そのような代理の main関数の利用が可能かどうかを検出し, F77_MAIN/AC_FC_MAINを関数の名前に定義します.(代理の main関数の名前が見つからない場合, F77_MAIN/AC_FC_MAINは単純にmainに定義します.)

このため,Fortranルーチンが,I/Oのようなものを実行するためにCから呼び出 されるとき,このマクロを使用し,"main"関数をmainではなく F77_MAIN/FC_MAINの名前にすべきです.

— Macro: AC_F77_WRAPPERS
— Macro: AC_FC_WRAPPERS

名前がmangleされる方法をFortranコンパイラで使用されているものに一致させ るため,mangleされているC/C++の識別子とアンダースコアが付いた識別子の名 前が正しくなるように,Cマクロの F77_FUNC(name,NAME)/FC_FUNC(name,NAME)F77_FUNC_(name,NAME)/FC_FUNC_(name,NAME)をそれぞれ定義しま す.

Fortranは大文字小文字の区別が無く,このために,Fortranコンパイラは全ての 識別子を標準的な文字と書式に変換します.CからFortranのサブルーチンを呼び 出したり,Fortranから呼び出し可能なC関数を書いたりするために,Cプログラ ムではFortranコンパイラが期待する書式で,識別子を明示的に使用する必要が あります.こうするために,全てのC識別子をAC_F77_WRAPPERSAC_FC_WRAPPERSで提供されるマクロの一つで,単純にラッパー関数にし ます.例えば,以下のようなFortranのサブルーチンがあるとします.

                subroutine foobar(x,y)
                double precision x, y
                y = 3.14159 * x
                return
                end

CやC++のプロトタイプで,以下のように宣言します.

          #define FOOBAR_F77 F77_FUNC(foobar,FOOBAR)
          #ifdef __cplusplus
          extern "C"  /* prevent C++ name mangling */
          #endif
          void FOOBAR_F77(double *x, double *y);

正しいものが選択できるように,関数名の大文字と小文字の両方のバージョンを F77_FUNCに渡していることに注意してください.また,Fortran 77 のルー チンへの全てのパラメータを,ポインタとして渡していることにも注意してくだ さい(see Mixing Fortran 77 With C and C++).

(Fortran 77の代わりに,Fortranに対してはF77FCで置換して 下さい.)

AutoconfはFortranコンパイラが名前をmangleする手法を検出するために知的な 手法で試みていますが,Fortranコンパイラはそれをまだサポートしていないか もしれません.この場合,上記のコードはコンパイル時にエラーとなりますが, それ以外の動作(例えば,Fortranに関連する機能の停止)は, F77_FUNC/FC_FUNCマクロが定義されているかどうかを調査するこ とで引き起こされます.

さて,そのようなルーチンをCプログラムから呼び出すために,以下のようにし てみます.

          {
              double x = 2.7183, y;
              FOOBAR_F77(&x, &y);
          }

Fortran 77の識別子がアンダースコアを含んでいる(例えばfoo_barの) 場合,F77_FUNC/FC_FUNCの代わりに F77_FUNC_/FC_FUNC_を(同じ引数で)使用すべきです.これは,ア ンダースコアを含んでいる場合,Fortranコンパイラによっては異なる名前に mangleするものもあるからです.

— Macro: AC_F77_FUNC (name, [shellvar])
— Macro: AC_FC_FUNC (name, [shellvar])

識別子nameが与えられている場合,シェル変数shellvarをFortran リンカの規則(AC_F77_WRAPPERSAC_FC_WRAPPERSも参照してくだ さい)によって,mangleされるバージョンのnameを保持するように設定し ます.shellvarはオプションです.提供されていない場合,シェル変数は 単純にnameになります.このマクロの目的は,上記のようにCプリプロセッ サを通じてではなく,呼び出し側に名前のmangleに関する情報にアクセスする方 法を与えることで,例えば,C/C++以外の言語からFortranルーチンを呼び出すた めです.

— Macro: AC_FC_SRCEXT (ext, [action-if-success], [action-if-failure])

デフォルトで,FCマクロは,ソースコードファイルを.fの拡張子 を使用しているテストを実行します.しかし,コンパイラによっては,適切なファ イル名に対してのみ,より新しい言語の機能を利用可能にし,例えば,Fortran 90の機能は.f90ファイルだけになります.一方,すべてのソースファイ ルが.fで終わることを期待していて,他のファイル名の拡張子をサポー トするためには特殊なフラグが必要になります.AC_FC_SRCEXTマクロは 両方の問題を扱います.

AC_FC_SRCEXTは,拡張子ext(すなわち,extにはドットは含 まれません)で終わるファイルを受け入れるFCコンパイラの取得 を試みます.こうするために特定のコンパイラフラグが必要な場合,それを出力 変数FCFLAGS_extに保存します.この拡張子とこのフラグは (AC_FC_SRCEXTが再び呼び出されるまで),それ以降に呼び出されるすべ てのFCで使用されます.

例えば,機能テストで.f90の拡張子を用いるため, AC_FC_SRCEXT(f90)を使用し,そのようなファイルをコンパイルするため に必要な追加フラグがあれば,FCFLAGS_f90出力変数を設定します.

FCFLAGS_extを単純にFCFLAGSに書き込むことは不可 能で,それにはコンパイラの制限に起因する二つの理由があります.最初のも のは,一度に一つのFCFLAGS_extが使用可能なので,ことなる拡張 子を持つファイルは別々にコンパイルする必要があるためです.二番目のものは, FCFLAGS_extはコンパイル時のソースコードのファイル名の 直前に書く必要があるためです.そのため,上記の例を続けると,以下 のコマンドを持つMakefileでfoo.f90ファイルがコンパイルされるでしょ う.

          foo.o: foo.f90
               $(FC) -c $(FCFLAGS) $(FCFLAGS_f90) foo.f90

extの拡張子を持つファイルのコンパイルでAC_FC_SRCEXTが成功す る場合,それは[action-if-success](デフォルトでは何もしません)を呼び 出します.失敗した場合と,FCコンパイラにそのようなファイルを受け 入れさせる方法が見つからない場合,[action-if-failure](デフォルトは エラーメッセージとともに終了します)を呼び出します.

— Macro: AC_FC_FREEFORM ([action-if-success], [action-if-failure])

AC_FC_FREEFORMは,Fortranコンパイラ($FC)でフリーフォーマッ トのソースコードが可能であることの確認を試みます(逆に,Fortran 77はより 古い固定フォーマット形式です).必要な場合,FCFLAGSに追加フラグを 加えてもかまいません.

デフォルトの.f拡張子を使用している場合,追加のフラグが提供されて いない限り,多くのコンパイラがこの拡張子を固定フォーマットのソースコード であると解釈するので,このマクロが最も重要です..f90.f95 のように,異なる拡張子をAC_FC_SRCEXTで指定している場合, AC_FC_FREEFORMは,通常,FCFLAGSを編集することなく成功しま す.

AC_FC_FREEFORMはフリーフォームのソースのコンパイルで成功する場合, それは[action-if-success](デフォルトでは何もしません)を呼び出します. 失敗した場合,[action-if-failure](デフォルトはエラーメッセージとと もに終了します)を呼び出します.