Available Languages: | Deutsch | English | Français | 日本語 (Nihongo) | 中文 (简) (Simplified Chinese) |

Unix ソフトウェアの Darwin と Mac OS X への移植

この文書は Unix アプリケーションを Darwin や Mac OS X へ移植する際に有用な情報を集めています. ここでの情報の多くは, Mac OS X バージョン 10.0.0 と Darwin 1.3.x に適用されます. どちらも Mac OS X は Darwin のスーパーセットなので,両者を Darwin という言葉で示します.

Contents

1 基本

1.1 Darwin はどこから来たのか

Darwin は Unix ライクなオペレーティングシステムとして, NeXTStep / OpenStep から派生してきました. これはまた, 4.4BSD Lite から分岐してきたとも言われています. BSD の遺産もあり,実際 Darwin は近年 FreeBSD と NetBSD のコードによって近代化されてきました.

Darwin のカーネルは,Mach 3.0 ,BSD,オブジェクト指向ドライバレイヤ IOKit などの商用機能などの混合です. Mac は元々マイクロカーネルとして設計されていましたが,この上にある BSD カーネルはモノリシックであり,両者は今では相互に依存し,一つのカーネルとして見ることができます.

Darwin にあるユーザー空間のツールやライブラリはほとんど BSD 由来のもので,Linux のような GNU ツールではありません. Apple は他の BSD のように厳密ではなく,有益な妥協もしています. たとえば, Apple は BSD make と GNU make の両方を付けて, GNU make をデフォルトとしています.

1.2 コンパイラとツール

短い説明: コンパイラは gcc の派生物ですが, cc としてインストールされます. Makefile にパッチを当てる必要があるでしょう. ほとんどのパッケージは共有ライブラリ をビルドしません. マクロに関係するエラーが出た時は,-no-cpp-precomp オプションを使用してください.

長い説明: Mac OS X Developer Tools にあるコンパイラツールチェーンは不思議な生き物です. コンパイラは gcc 2.95.2 スイートをもとに, Objective C 言語やいくつかの Darwin 特有なことをサポートする変更がなされています. プリプロセサー (cpp) は二つのバージョンがあります. ひとつは通常の(gcc 2.95.2 からの) プリコンパイラで,もう一つは Apple による,コンパイル済みヘッダをサポートする特別なプリコンパイラです. こちらの方が高速で,デフォルトになっています. しかし,コードによっては Apple のプリコンパイラではコンパイルできません. この場合,-no-cpp-precomp オプションを使い,通常のプリコンパイラでコンパイルします. (注記: 以前は -traditional-cpp オプションを勧めていました. このオプションの意味が GCC 3 で少し変わったため,これを使うパッケージのほとんどを破壊してしまいました. -no-cpp-precomp は現在の Developer Tools と 将来の GCC 3 ベースのコンパイラの双方に要求通りのことをしてくれます.)

アッセンブラは gas 1.38 ベースだと言いますが,リンカは GNU ツールではありません. これは 共有ライブラリ をビルドする際に問題となります. GNU libtool とこれが生成する configure スクリプトは Apple のリンカの扱い方を知らないためです.

1.3 ホスト種別

短い説明: configure が 'Can't determine host type' と言って異常終了した場合,config.guess と config.sub を /usr/share/libtool (OS バージョン 10.2 以前では /usr/libexec) から現在のディレクトリにコピーしてください.

長い説明: GNU の世界では,システムの種類を特定するために基準形式を採用しています. これには3つのパートがあります: CPU 種別,メーカー,オペレーティングシステム. 4つ目のパートがつくこともあります. 全て小文字で表記され,ダッシュでつながれます. 例: i586-pc-linux-gnu, hppa1.1-hp-hpux10.20, sparc-sun-solaris2.6. Mac OS X 10.0 のホスト種別は powerpc-apple-darwin1.3 です.

autoconf を使うパッケージは多くの場合,コンパイル環境のシステム種別を知りたがります. (注記: クロスコンパイルと移植のサポートのため,3つの種別 - ホスト種別,ビルド種別,ターゲット種別があります. 通常は全て同一です.) ホスト種別は configure スクリプトに渡すことも,自動推測してもらうこともできます.

configure スクリプトは二つの付属スクリプトでホスト種別を決定します. config.guess がホスト種別の推測を試み,config.sub で検証・正規化をします. 両スクリプトは別々にメンテナンスされていますが,全てのパッケージに含まれます. 最近までこのスクリプトは Darwin も Mac OS X も知りませんでした. もし Darwin を認識しないパッケージがあった場合, configu.guess と config.sub を置き換える必要があります. 功にも, Apple が動作するバージョンのものを /usr/share/libtool (10.2 以前の OS では /usr/libexec) に置いていますので,そこからコピーしてください.

1.4 ライブラリ

短い説明: -lm を削除しても問題ありませんが,する必要もありません.

長い説明: Mac OS X は libc, libm, libcurses, libpthread などのライブラリを分割して持っていません. 代わりに,これらは全てシステムライブラリ libSystem の一部となっています. (以前のバージョンではこれは System のフレームワークでした.) しかし, Apple は適切にシンボリックリンクを /usr/lib に置いていますので,-lm でリンクすれば動作します. 唯一の例外は -lutil です. 他のシステムでは,libutil は疑似ターミナルや,ログイン監査などの関数を含んでいます. これらの関数は libSystem にはなく, libutil.dylib へのシンボリックリンクもありません.

1.5 他の情報源

ポーティングに関する他の情報源としては,MetaPkg Wiki があります.

Apple Technical Note TN2071: "Porting Command Line Unix Tools to Mac OS X" も読むとよいでしょう.

2 共有コード

2.1 共有ライブラリ vs ローダブル・モジュール

Mach-0 の仕様の一つで,多くの人を驚かせるものとして, 共有ライブラリ と 動的ローダブル・モジュールを厳密に区別する点があります. ELF システムでは両者は同質で,共有コードのどの部分でも,ライブラリとしても動的ローディングにも使うことができます.

Mach-O 共有ライブラリ のファイルタイプは MH_DYLIB で,拡張子は .dylib となります. これは通常の静的リンカフラグ,例えば libfoo.dylib の場合は -lfoo でリンクすることができます. しかし,モジュールとしてロードすることはできません. (注記: 共有ライブラリ は API を通して動的にロードすることができます. しかし API はバンドルの場合と異なり,dlopen() エミュレーションの意味を無くします. 特筆すべきこととして, 共有ライブラリ はアンロードできません.)

ローダブル・モジュールは Mach-O の用語では"バンドル"と言われ,ファイルタイプは MH_BUNDLE です. これを用いるコンポーネントは拡張子を気にしないので,拡張子は何でも構いません. .bundle という拡張子が Apple の推奨ですが,移植されたソフトウェアのほとんどは,互換性のため .so を使っています. バンドルは dyld API を用いて動的にロード/アンロードされることができますし,この API の上に dlopen() をエミュレートするラッパもあります. バンドルを 共有ライブラリ のようにリンクすることはできませんが,バンドルを 共有ライブラリ にリンクさせることは可能です. この場合,バンドルがロードされた際に両者ともロードされます.

2.2 バージョン番号

ELF システムでは通常, libqt.so.2.3.0 のようにバージョン番号はファイル名に後置されます. Darwin では,libqt.2.3.0.dylib にようにバージョン番号はライブラリ名と拡張子の間に置かれます. これにより, -lqt.2.3.0 のように,特定バージョンのライブラリをリンク時に指定することができます.

共有ライブラリを作成する場合,実行時に検索するライブラリの名前を指定することができます. これはよく行われることで,これによって,ライブラリのいくつかのメジャーバージョンをインストールすることが可能になります. ELF システムでは,これは soname と言われています. Darwin の場合,ファイル名の他にフルパスを指定することができ(またする必要があり)ます. これにより,"rpath" オプションと ldconfig/ld.so.cache システムが不要になります. まだインストールされていないライブラリを使うには, DYLD_LIBRARY_PATH 環境変数を設定することもできます. 詳細は dyld の man ページをご覧ください.

Mach-O 形式は,ELF システムの関知しないマイナーバージョンの確認を行います. Mach-O ライブラリは二つのバージョン番号: "current" バージョンと "compatibility" バージョンがあります. 両方のバージョン番号は3つの番号を 1.4.2 のようにドットでつなげます. 最初の番号は 0 ではいけません. 2つ目と3つ目の番号は省略可能で,この場合 0 と扱われます. バージョン番号を指定しなかった場合, 0.0.0 と扱われ,ある種のワイルドカード値となります.

"current" バージョンは情報提供のためのみ存在します. "compatibility" バージョンは以下のように確認目的に使用されます. 実行可能ファイルをリンクする際,ライブラリからの情報がファイルにコピーされます. ファイルが実行される際に使用するライブラリに対して情報を確認します. 使用するライブラリのバージョンが,リンク時のものと同一か新しいものでない限り,実行時エラーを生成してプログラムを終了させます.

2.3 コンパイラフラグ

位置独立コード (PIC: Position Independent Code) の生成は Darwin ではデフォルトです. 実際, PowerPC コードは設計上 position-independent となり,パフォーマンスや空間上の損失はありません. このため,共有ライブラリやモジュールへコードをコンパイルする際も,PIC を指定する必要はありません. しかし,リンカは「共通」のシンボルを共有ライブラリ内に持つことは認めないので, -fno-common コンパイラオプションが必要になります.

2.4 共有ライブラリ をビルド

共有ライブラリをビルドするには, -dynamiclib 付きでコンパイラドライバを呼び出します. 以下の一連の例を見るとわかりやすいでしょう. ここでは source.c と code.c というソースからなる libfoo というライブラリビルドするとします. バージョン番号は 2.4.5 ,2 が主リビジョン (非互換の API 変更), 4 が副リビジョン (後方互換な API の変更),5 がバグ修正リビジョンかうんと (人によっては"teeny" リビジョンといい,完全に互換性のある変更です)です. このライブラリは他の共有ライブラリには依存せず, /usr/local/lib にインストールされます.

cc -fno-common -c source.c
cc -fno-common -c code.c
cc -dynamiclib -install_name /usr/local/lib/libfoo.2.dylib \
 -compatibility_version 2.4 -current_version 2.4.5 \
 -o libfoo.2.4.5.dylib source.o code.o
rm -f libfoo.2.dylib libfoo.dylib
ln -s libfoo.2.4.5.dylib libfoo.2.dylib
ln -s libfoo.2.4.5.dylib libfoo.dylib

この例で,バージョンのどの部分がどこで使われたかわかりましたでしょうか. また,静的リンカが libfoo.dylib シンボリックリンクを使い,動的リンカは libfoo.2.dylib シンボリックリンクを使うことに注意してください. それぞれのシンボリックリンクをライブラリの異なるリビジョンへつなげることも可能です.

2.5 モジュールをビルド

ローダブル・モジュールをビルドするためには,-bundle オプション付きでコンパイラドライバを呼び出します. モジュールがホストプログラムのシンボルを使う場合, -undefined suppress を指定して未定義のシンボルを使い, -flat_namespace を指定して新しいリンカが Mac OS X 10.1 でも使えるようにします. 一連の例:

cc -fno-common -c source.c
cc -fno-common -c code.c
cc -bundle -flat_namespace -undefined suppress \
 -o mymodule.so source.o code.o

バージョン番号は使用していません. 理論的には使うことも可能ですが,実際あまり意味がありません. また,バンドルには名称上の制限が無いことに注意してください. パッケージによっては,他のシステムが要求するため "lib" を前置しますが, プログラムがモジュールをロードする際には完全なファイル名を使用するので,無害です.

3 GNU libtool

ライブラリをビルドする GNU パッケージは,ライブラリをビルド・インストールする際のプラットフォーム依存の手続きを隠すため GNU libtool を使います.

3.1 状況

粗く言って,4つの libtool の流派があります:

結論として,libtool 1.3.x とこれを使うパッケージ (libtool を使うパッケージの主流) は, Darwin で共有ライブラリをビルドするにはパッチが必要になります. Apple は libtool 1.3.5 のパッチが当たったバージョンを Mac OS X に組み込んでいますが,ほとんどの場合うまく行きません. Christoph Pfisterer がこのパッチを改良し,正しいパスのハードコーディングと完全なバージョニングを行うようになりました. この変更は上流の libtool リリースと 1.4 で始まる開発バージョンに統合されました. Fink チームのメンバーはこれからも改良を続け, libtool メンテナに送っていきます. バージョン番号のスキームは全ての libtool バージョンで一致しています.

注記: 全てのバージョンの libtool に関して,付属の libltdl ライブラリは dlcompat がインストールされている場合に限り Darwin 上で動作します. 10.3以降の OSX には付属されています. これ以前のバージョンでは,"dlcompat" 関連のパッケージをインストールします.

3.2 1.3.5 パッチ

libtool 1.3.5 を自分でビルドする場合, このパッチ [updated 2002-06-09] をソースにあて,ltconfig と ltmain.sh というファイルを削除します. (これらのファイルは,configure と make をすることで .in ファイルにより再生成されます.) Fink パッケージの libtool 1.3.5 では自動的に行われます.

ここまででやっと半分です - libtool を使うパッケージはそれぞれ独自の ltconfig と ltmain.sh を持っています. 共有ライブラリとしてビルドする全てのパッケージについて,これらのファイルを置き換える必要があります. これは configure スクリプトを実行する前に行う必要があります. 両ファイルは以下から取得することができます: ltconfig (98K) と ltmain.sh (110K) [both updated 2002-06-09].

3.3 1.4.x を修正

現在,よく使われている libtool 1.4.x には3つのバージョンがあります (1.4.1, 1.4.2, 最新開発スナップショット). いずれも Darwin ではいくつかの問題があり,修正方法も異なります. Fink で提供している libtool14 は全てのパッチを含んでいます. しかし,これによって影響されるパッケージの ltmain.sh/configure ファイルを修正する必要があります.

  1. flat_namespace バグ: この問題は, Mac OS X 10.1 上で libtool を使用する際に発生します. 何が起こるかというと,libtool は未定義シンボルを許可するために -undefined suppress を使おうとするが,これに伴う -flat_namespace を指定しません. 10.1 からは,これでは動作しません. パッチは以下のようになります:
    diff -Naur gdk-pixbuf-0.16.0.old/configure gdk-pixbuf-0.16.0.new/configure
    --- gdk-pixbuf-0.16.0.old/configure	Wed Jan 23 10:11:48 2002
    +++ gdk-pixbuf-0.16.0.new/configure	Thu Jan 31 03:19:54 2002
    @@ -3334,7 +3334,7 @@
         ;;
     
       darwin* | rhapsody*)
    -    allow_undefined_flag='-undefined suppress'
    +    allow_undefined_flag='-flat_namespace -undefined suppress'
         # FIXME: Relying on posixy $() will cause problems for
         #        cross-compilation, but unfortunately the echo tests do not
         #        yet detect zsh echo's removal of \ escapes.
    
  2. ローダブル・モジュールのバグ: このバグは,zsh (10.0 と 10.1 のデフォルトシェル; 10.2 では bash に変更される見込み) の非標準的な挙動によります. zsh の非標準的なクォートの挙動により,ローダブル・モジュールが正しくビルドされず,(Linux と異なり,Darwin では本質的に別ものな) 共有ライブラリになります. 修正方法の例 (の一部なので,そのままでは使えません):
    diff -Naur gnome-core-1.4.0.6.old/configure gnome-core-1.4.0.6.new/configure
    --- gnome-core-1.4.0.6.old/configure	Sun Jan 27 08:19:48 2002
    +++ gnome-core-1.4.0.6.new/configure	Fri Feb  8 01:10:21 2002
    @@ -4020,7 +4020,7 @@
         # FIXME: Relying on posixy $() will cause problems for
         #        cross-compilation, but unfortunately the echo tests do not
         #        yet detect zsh echo's removal of \ escapes.
    -    archive_cmds='$nonopt $(test "x$module" = xyes && echo -bundle || echo -dynamiclib) ...'
    +    archive_cmds='$nonopt $(test x$module = xyes && echo -bundle || echo -dynamiclib) ...'
         # We need to add '_' to the symbols in $export_symbols first
         #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
         hardcode_direct=yes
    

    この問題は 1.4.2 以降のバージョンでは修正されました.

  3. convenience ライブラリのバグ: 条件によっては,libtool は convinience ライブラリをリンクすることができず, "multiple definitions" エラーを出します. これは libtool の本質的な問題によるようです. 現在のところ回避策として (原因ではなく症状を治すだけでですが,成功します),この修正を行います (Dave Vasilevsky に感謝):
    --- ltmain.sh.old       2002-04-27 00:01:23.000000000 -0400
    +++ ltmain.sh   2002-04-27 00:01:45.000000000 -0400
    @@ -2894,7 +2894,18 @@
            if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
              eval cmds=\"$archive_expsym_cmds\"
            else
    +         save_deplibs="$deplibs"
    +         for conv in $convenience; do
    +       tmp_deplibs=
    +       for test_deplib in $deplibs; do
    +         if test "$test_deplib" != "$conv"; then
    +           tmp_deplibs="$tmp_deplibs $test_deplib"
    +         fi
    +       done
    +       deplibs="$tmp_deplibs"
    +         done
              eval cmds=\"$archive_cmds\"
    +         deplibs="$save_deplibs"
            fi
            save_ifs="$IFS"; IFS='~'
            for cmd in $cmds; do
    
  4. DESTDIR バグ: DESTDIR を設定し, libtool 1.4.2 を使用するパッケージのなかで,再リンクに問題がある場合があります. この問題は,以下のメールで議論されました:

    http://mail.gnu.org/archive/html/libtool/2002-04/msg00019.html

    http://mail.gnu.org/archive/html/libtool/2002-04/msg00021.html

    http://mail.gnu.org/archive/html/libtool/2002-04/msg00025.html,

    パッチに関する議論は:

    http://mail.gnu.org/archive/html/libtool/2002-04/msg00043.html.

3.4 さらなる注記

libtool 自体と,libtool が何をするかについての詳細は libtool ホームページを参照.

注記: Apple の Developer Tools には libtool というプログラムがはいっていて,コンパイラドライバが共有ライブラリをビルドする際に使われます. しかし,これは GNU の libtool とは全く関係がありません. Apple の提供する GNU libtool は glibtool としてインストールされています. これは, GNU libtool を--program-transform-name=s/libtool/glibtool/ と configure することで得られます.

4 10.2 に向けて

4.1 bash シェル

OS X 10.2 は /bin/sh 機能を提供するため zsh ではなく bash を使用すると理解しています. これにより fink にとっては3つのことが実現されます.

4.2 gcc3 コンパイラ

gcc3 コンパイラを使用する Mac OS X 10.2

ローダブル・モジュールを含み, libtool を使用するパッケージで, install_name エラーで失敗するものは, libtool が -install_name フラグと(特に必要なり) -bundle フラグを送るためです . gcc2 コンパイラは受け付けていましたが, gcc3 コンパイラでは受け付けません. 修正はここにあります. libtool-1.3.5 を使うパッケージ (UpdateLibtool: True を使用している場合を含む) はこのパッチは必要ないことに注意してください. 既に fink の ltconfig ファイル (fink のプレリリース版にある) に統合されているためです.

他の gcc3 コンパイラの問題は, gcc2 と gcc3 での C++ ABI の非互換性によります. gcc2 でコンパイルされたライブラリに gcc3 でコンパイルされた C++ プログラムからリンクできないことを意味します.

5 10.3 に向けて

5.1 Perl

OS X 10.2 では, /usr/bin/perl は perl 5.6.0 であり, architecture 文字列は "darwin" でした. OS X 10.3 では, /usr/bin/perl は perl 5.8.1 にアップグレードされ, architecture 文字列が "darwin-thread-multi-2level" に変更されました. この変更は, それぞれの perl 実行ファイルはモジュールを探す場所を知っているので,パッケージ作成時に perl 実行ファイルを使用する分にはおそらく影響がないでしょう. perl モジュール ("-pm") パッケージのメンテナは,Perl モジュールのパッケージ化ポリシーに従い,CompileScriptInstallScript が適切に作成されるようにしてください。

5.2 新しいシンボル定義

Mac OS X 10.3 より,常に socklen_t タイプの完全な定義があります. この typpedef 定義を知るには,プログラムに以下を追加する必要があるかもしれません:

#include <sys/types.h>
#include <sys/socket.h>
  

5.3 新しいシステムのライブラリ

Mac OS X 10.3 には,これまでのシステムでは提供していないために fink パッケージとして提供していたものがあります:

FieldValue
libpoll

/usr/lib/libpoll.dylib/usr/include/poll.h というファイルが含まれています.しかし,OS X によるライブラリは不完全です. もしこれで十分であれば, Fink "libpoll" への依存性を削除することもできます. ライブラリのコードは,実際は libSystem に統合されているため,自動的にリンクされます. つまり, OS X のものを使用する際には -lpoll も不要となります. OS X は libpoll.dylib も提供しているため, -lpoll をすると Fink "libpoll" パッケージがインストールされているかいないかで結果が変わることには注意をしてください.

libdl

/usr/lib/libdl.dylib/usr/include/dlfcn.h というファイルが含まれています.このため,Fink の "dlcompat", "dlcompat-dev", "dlcompat-shlibs" パッケージは不要となります. ライブラリのコードは,実際は libSystem に統合されているため,自動的にリンクされます. つまり, OS X のものを使用する際には -ldl も不要となります (あっても影響はありません).

GNU getopt

このライブラリは, getopt_long() 関数を含めて, libSystem と /usr/include/getopt.h に統合されました. このため, Fink の"libgnugetopt" と "libgnugetopt-shlibs" を使用する必要はありません. libSystem は自動的にリンクされ, /usr/include も自動的に検索されるため, Fink の "libgnugetopt" へアクセスするために手動で追加していた -lgnugetopt-I/opt/sw/include/gnugetopt を削除することができます.

OS X 10.3 へパッケージを投入する際には,これらのパッケージは将来的に削除されるので,上述の不要となった依存性を削除してください. このため,それぞれのツリー用に別々のパッケージ記述ファイルを用意する必要があります. Revision は通常通りあげる必要があります. この方法で,OS X 10.2 から 10.3 へアップグレードするユーザーは,10.2 用のパッケージより 10.3 用のパッケージの方が"より新しい"と認識することができます. 低い方のツリーでの変更があるかもしれないので,その時にリビジョンをあげられるよう Revision は 10 あげてください.

10.3 へ統合されるパッケージをテストする際は, BuildDepends から削除したパッケージをアンインストールしてください. そうでないと Fink が提供するライブラリにリンクする可能性があります.

6 10.4 に向けて

6.1 Perl

/usr/bin/perl は perl 5.8.6 です. architecture string は未だに "darwin-thread-multi-2level" です.

6.2 新しいシンボル定義

Mac OS X 10.4 は,多くのシンボルの型を変更しました. 今までに明示的に型を指定したもの、例えば socklen_tint と定義したようなもの, この定義は正しくありません.

6.3 新しいシステムライブラリ

Mac OS X 10.3 の poll() 関数は、実際は select() を利用したエミュレーションでした。 Mac OS X 10.4 では、 poll() はカーネルで実装されている実際の関数です。 しかし、ソケットと使用する際には壊れています。 システムの poll() を完全に無視することも検討してください。 Fink の glib2 パッケージは、完全に機能するエミュレーションを使うようパッチされていますので、 poll のような機能のライブラリを安全に使うことができます。


Copyright Notice

Copyright (c) 2001 Christoph Pfisterer, Copyright (c) 2001-2020 The Fink Project. You may distribute this document in print for private purposes, provided the document and this copyright notice remain complete and unmodified. Any commercial reproduction and any online publication requires the explicit consent of the author.


Generated from $Fink: porting.ja.xml,v 1.12 2023/08/04 5:08:13 nieder Exp $