んで次は D のゲームのコンパイルしてたわけですな。
D のコンパイラは gdcmac がすばらしいのでありがたく使う。
http://gdcmac.sourceforge.net/
まずは普通に D の非互換によるエラーを潰す。そんなにたいした量なかった。
リンクは大変。まず昔も書いたような話。
要は Ruby/SDL と同じで、 libphobos.a も main を奪いたがるのでここでも競合する。しゃーないなーということで main の無い libgphobos.a を作ることにする。めんどくさいから shell script をはる。
#!/bin/sh -x rm -fr t mkdir t cd t cp /usr/lib/libgphobos.a . for i in i386 ppc ; do mkdir $i cd $i lipo ../libgphobos.a -extract $i -output libgphobos.a libtool -static libgphobos.a -o gp.a ruby ../../arext.rb gp.a rm cmain.o || exit ar crus libgphobosnm.a *.o cd .. done lipo -create -arch i386 i386/libgphobosnm.a -arch ppc ppc/libgphobosnm.a -output ../libgphobosnm.a
何してるかっていうと libgphobos.a が Universal Binary なので、 i386 と ppc でそれぞれ libgphobos.a を取り出して、 .a を展開してから cmain.o を削除、そんでから .a にまとめて、もう一度 Universal Binary にしている。 lipo は Universal Binary を操作するツールで、 i386 だけを取り出したりできる。この段階ではまだ新しいフォーマットなので、古き良き ar アーカイブにするために libtool -static を使い、そんでから展開している。展開は ar でできるのだけど、うっといことに同じ名前オブジェクトファイルが入ってたので ar 展開ツールをサクっと作った。こんなの:
if ARGF.read(8) != "!<arch>\n" abort 'it is not ar' end m=[] while x=ARGF.gets x = x.split abort 'wrong format?' if x[6] != '`' x = [x[0], Time.at(x[1].to_i), x[2], x[3], x[4], x[5].to_i, x[6]] if /\#(\d+)\/(\d+)/ =~ fn=x[0] fn = ARGF.read(s=$2.to_i)[/[^\0]+/] x[5] -= s end c = ARGF.read(x[5]) on = fn while m.include?(fn) en = File.extname(fn) bn = File.basename(fn, '.*') fn = bn + '_' + en end if on != fn puts "filename changed: #{on} => #{fn}" end m << fn File.open(fn, 'w') do |o| o.print(c) end end
これで libgphobos からは main を消せた。後は D の初期化をする SDL_main 相当を書いてやればいい。以下 boot.d
import std.c.stdio; extern (C) int chdir(char* s); private extern (C) char* rindex(char* s, int c); private extern (C) int _d_run_main(int argc, char **argv, void * p); int main(); extern (C) int SDL_main(int argc, char** argv) { char buf[256]; char* p = rindex(argv[0], '/')+1; sprintf(buf.ptr, "%s.app/Contents/Resources", p); if (0 != chdir(buf.ptr)) { printf("cannot change dir\n"); } return _d_run_main(argc, argv, & main); }
こんなのを一緒にリンクしてやると、
- libSDLmain.a の main から起動
- boot.d の SDL_main
- ユーザーコード
という流れになる。
で、 Universal Binary を作る話だけど、基本的には gdc -arch i386 -arch ppc などとすればよろしくやってくれる。ところがリンクは、 libgphobos.a を変えちゃってる都合で自前でやることになった。 gcc のオプションに -v をつけて ld のオプションを調べて、それを適当に編集して -lgphobos を自作のに変えればいい。それぞれリンクできたら lipo でひっつける。うちだとリンクオプションはこんな感じになった。 crt が微妙に違うんだなーと思った。
LIBS=../libgphobosnm.a -lstdc++ ../bulletml/libbulletml_d.a -F$(FPATH) -framework Cocoa $(FOPTS) -framework OpenGL ../SDLMain.o LD_386=/usr/libexec/gcc/i686-apple-darwin8/4.0.1/collect2 -dynamic -arch i386 -arch_multiple -macosx_version_min 10.3 -multiply_defined suppress -weak_reference_mismatches non-weak -lcrt1.o /usr/lib/gcc/i686-apple-darwin8/4.0.1/crt3.o -L/usr/lib/gcc/i686-apple-darwin8/4.0.1 -L/usr/lib/gcc/i686-apple-darwin8/4.0.1 -L/usr/lib/gcc/i686-apple-darwin8/4.0.1/../../.. -lgcc_s.10.4 -lgcc -lm -lSystem LD_PPC=/usr/libexec/gcc/powerpc-apple-darwin8/4.0.1/collect2 -dynamic -arch ppc -arch_multiple -macosx_version_min 10.3 -multiply_defined suppress -weak_reference_mismatches non-weak -lcrt1.o /usr/lib/gcc/powerpc-apple-darwin8/4.0.1/crt2.o -L/usr/lib/gcc/powerpc-apple-darwin8/4.0.1 -L/usr/lib/gcc/powerpc-apple-darwin8/4.0.1 -L/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/../../.. -lgcc_s.10.4 -lgcc -lm -lSystemStubs -lSystem
あとはここに昔書いたような方法でパッケージを作りました。要は hdiutils ってコマンドを使うと良い。
http://zinnia.dyndns.org/~hiki/SDLKB/?MacOSX%2BSDL%A4%C7%A4%CE%C7%DB%C9%DB%CA%AA%BA%EE%C0%AE%CB%A1