g77 の build の手順は、まず、Darwin の gcc ソースを展開し
$ cd gcc-2libg2c パッチは例によって、libg2c.a を PIC flag を立ててコンパイルするためのパッチ。macosx patch のポイントは、build_gcc の中で LANGUAGES に f77 を加えることと、gcc/config/apple/apple-specs.h に #include "f/lang-specs.h" を加えること、そして、gcc-2/gcc/f/com.c に 上で述べた undefined symbols を解決するための dummy routines をつけ加えることである。これで取り合えず f771、g77 を build できる。
$ cp -pr <gcc-2.95.2 のソースディレクトリー>/libf2c .
$ cp -pr <gcc-2.95.2 のソースディレクトリー>/gcc/f gcc/.
$ patch -p1 -s < <somewhere>/gcc-2.95.2-libg2c.patch
$ patch -p1 -s < <somewhere>/gcc-2.95.2-macosx.patch$ export RC_ARCHS=ppc
$ export RC_CFLAGS='-arch ppc'
$ export RC_OS='macos'
$ export SRCROOT=/Users/fujiik/sandbox/gcc-2
$ make TARGETS='ppc' HOSTS='ppc' >& make.log &
$ make install TARGETS='ppc' HOSTS='ppc' >& install.log &
次に libg2c.a を build する。
$ cd gcc注意
$ for i in ../obj/cc-ppc-on-ppc/*.h; do ln -s $i .; done
$ cd ..
$ mkdir obj/ppc/libf2c
$ cd obj/ppc/libf2c
$ CFLAGS='-traditional-cpp' $SRCROOT/libf2c/configure --srcdir=/Users/fujiik/sandbox/gcc-2/libf2c --host=ppc --target=ppc
$ make TARGETS='ppc' HOSTS='ppc' >& make.log &
できた g77 で Hello World がコンパイルできたと喜んだのもつかの間、以下の例で早くも失敗。g77 -O0 は リテラル数が関数コールの引数に含まれているとインターナルコンパイラーエラーを起こしてしまう。最適化をすれば(g77 -O)この例の場合問題を回避できるが、多重ループを含む複雑なプログラムでどうしても -O0 でコンパイルしなくてはならない場合が予想されるので、何とか -O0 で動かせないと後々困る。
(例)
$ cat test.F上記の問題の RTL expression は、LinuxPPC が発生するものとレジスターの番号を除き同じであった。RTL (Register Transfer Language) については gcc の info に詳しい解説があるが、簡単に言えば、コンパイラーがマシン依存のアセンブラコードを吐く際のもととなる、マシン非依存の中間言語である。つまり、g77 などの front end は ソースを RTL 表現に変換し、これを back end に渡すのである。RTL で表現された命令(insn)を RTX (RTL EXpression) と呼ぶが、RTX を解釈し、マシン依存のアセンブラを吐くのが back end の仕事である。
a = abs(1.)
end
$ g77 test.F
main2.F: In program `MAIN__':
main2.F:2: internal error--unrecognizable insn:
(insn 10 8 11 (set (reg:SF 115)
(mem/u:SF (lo_sum:SI (reg:SI 116)
(symbol_ref/u:SI ("*LC0"))) 0)) -1 (nil)
(nil))
RTX が LinuxPPC と同じということは RTX を解釈する back end の問題と思われる。この back end のコントロール部分は、gcc/recog.c で、そのマシン依存の実体は insn-recog.c である。insn-recog.c は genrecog.c により自動生成されるが、そのもととなるのが gcc/config/rs6000/rs6000.md などの Machine Description ファイルである。つまり、GNU コンパイラーのポーティングの作業の中心はこの部分になるわけである。
この rs6000.md を LinuxPPC のものと比べてみると、当然であるが、多くの部分は altivec 対応のための変更である。これに加え、少数の PIC (Position Independent Code) 生成の際の分岐に変更があった。そこで PIC Flag を立てれば、上記の問題を回避できることが分かった。正しくは、rs6000.md を修正するべきであろうが、取り合えず -fPIC をつけてコンパイルすれば動くということである。もともと、CERNLIB などでは、共有ライブラリーへの組み込みを可能とするためアーカイブも PIC Flag を立ててコンパイルする必要があったので、格好は悪いが当面はよしとする(時間ができれば altivec のこともあるので、再挑戦することとする)。
(問題の回避法)
$ g77 -fPIC test.F格好悪いが取り合えず動くということで。
$ cd tdr-1.7問題なくコンパイルでき、正常動作した。これで、少しではあるが、大物 CERNLIB に挑戦する元気がでてきた。
$ patch -p1 -s < ../tdr-1.7_linux.patch
$ make compile F77='g77 -O -fPIC'
$ make lib F77='g77 -O -fPIC'
$ make tdr F77='g77 -O -fPIC' MAINDIR=`pwd`
今までにコンパイルしたもののソースおよびパッチは macosx/src
に、またバイナリーの tar ball は macosx/tgz
にそれぞれ置いてある。いつものように使う場合は自己責任で。