|
|
3 ソース・ツリーこの章では、OpenSolaris のソース・ツリーの取得、管理、および変更について説明します。
3.1 ソースを取得するソースを取得するには、ソースのみが含まれる「tarball」と、公開される読み取り専用の CSV リポジトリの 2 つの方法があります。両方とも同じセットのソースが含まれ、毎日更新されます。
3.1.1 tarball からソースを取得するhttp://opensolaris.org/os/downloads/ から tarball を入手できます。ソースをビルドする計画があり、また完全なインストール・セットを作成したい場合は、同じ場所から入手できるクローズド・バイナリも必要です。必ずプラットフォームに適したバイナリを入手してください。プラットフォームに適したバイナリを入手したら、次のようにワークスペースを作成します。
$ mkdir /path/to/workspace
$ cd /path/to/workspace
$ bzip2 -dc /path/to/tarball/opensolaris-src-<ver>.tar.bz2 | tar xf -
$ bzip2 -dc /path/to/tarball/opensolaris-bins-<ver>.{x86,sparc}.tar.gz | tar xf -
3.2 ワークスペースの概要ワークスペースを作成し、その中にファイルを準備した後、ソース・ツリーの内容の調査を開始することができます。このセクションでは、ON ワークスペースのレイアウトと内容を説明します。
3.2.1 構成最初の時点で、ワークスペースには 1 つのディレクトリ usr のみがあります。ビルドを完了すれば、archives、log、packages、proto などを含む、いくつかの追加ディレクトリを使用できます。このページには、これらのディレクトリとそのサブディレクトリをすべて示す図があります。また、オブジェクト・ファイルを含み、以下のサブセクション ▼2 ~ 4 で詳細が説明されているビルド・サブディレクトリもあります。
すべてのソースは usr/src の下にあります。このディレクトリには、ON 統合のビルドに使用されるソースと、Solaris のビルドには必要ですが Solaris には含まれないツールおよびそのほかの周辺ユーティリティのソースの両方が含まれています。このディレクトリには ON のソースのみが含まれるため、Java、ウィンドウ・システム、パッケージ・ツールおよびインストール・ツールは含まれていません。契約上の義務により、通常、サードパーティ・ハードウェア・ベンダー製のコードも含まれていません。usr/src ディレクトリには、以下で説明する複数のサブディレクトリがあります。
3.2.2 オブジェクト・ディレクトリオブジェクト・ファイルと最終のバイナリ (実行可能ファイルとライブラリ) の作成には、次の 2 つの基本的方法が使用できます。 (a) ソースに対して並列な専用のディレクトリ階層にオブジェクトを配置する (b) ビルド元のソースと同じディレクトリにオブジェクトを配置する OpenSolaris では実際には、ツリーの異なる部分ではそれぞれのアプローチを使っています。方法 (a) はすべてのカーネル・コードと多くのライブラリに使用する必要があり、新しいコードには望ましいもので、ここで詳細を説明します。方法 (b) がまだ使われている場合があるように、方法 (a) にも歴史的にいくつかのバリエーションがあります。多くは cmd 階層にあります。uts の階層全体は、以下で説明するように方法 (a) に移行しています。この同じアプローチは、残りのツリーの多くで使われています。
3.2.2.1 カーネル・オブジェクトの一般的な方法最初に、プラットフォームに依存しない各モジュールには、アーキテクチャごとに 0 または 1 つのビルド・ディレクトリがあります。この場合のアーキテクチャは、マシン (sun4u、i86pc) またはプロセッサ・アーキテクチャ (intel、sparc) のことです。この場所へのパスは常に usr/src/uts/<プラットフォーム>/<モジュール> となります。この場合のモジュール名は、/kernel/drv または同じような場所にあるものを指します。デバイス・ドライバや STREAMS モジュールの場合は、ドライバやモジュールを説明している man ぺージの名前に常に一致する必要があります。 空のツリーでは、通常このディレクトリにあるファイルは makefile だけです。ビルドの後では、これらのディレクトリには obj32、obj64、debug32、debug64 ディレクトリの内の 1 つ以上が含まれます。これらのディレクトリには、オブジェクト・ファイルと、(後でカーネル・ディレクトリやプロトタイプのほかの場所にインストールされる) 最終的にリンクされるモジュールが含まれます。 「実装アーキテクチャ」に依存しないモジュールは、「命令セット・アーキテクチャ」ディレクトリ (sparc など) の下にある個別の (モジュールごとに 1 つの) ディレクトリに生成されます。同様に、「実装アーキテクチャ」に依存するモジュールは、「実装アーキテクチャ」ディレクトリ (sun4、sun4u、i86pc など) の下にある個別のディレクトリに生成されます。 プラットフォームに依存するモジュール (「unix」を含む) は異なる場所に複数回ビルドされることがあります。プラットフォームに依存するモジュールについては、詳細を ▼<section> で説明します。 ソースは、これらのビルド・ディレクトリには含まれていません。
3.2.2.2 コマンド/ライブラリ・オブジェクトの一般的な方法ほとんどのライブラリと一部のコマンドおよびデーモンは、カーネルのビルドに使用されるものとよく似た makefile を使用してビルドされます。したがって、中間オブジェクト、共有オブジェクト、ライブラリ、実行可能ファイルは、makefile の一部分によってビルドされ、専用の ISA 固有のサブディレクトリに配置されます。 そのほかのコマンドのビルド・システムは、ソースと同じディレクトリにオブジェクトを配置します。コマンドのビルド方法の詳細は、セクション 3.2.2.3、3.2.3.2、および 3.2.5 を参照してください。
3.2.2.3 cmd と lib の例外ほとんどの cmd ツリーはオリジナルの System V Release 4 のソースに直接基づいており、上記の方法 (b) を使用します。ほとんどのコマンドとデーモンは、32 ビットと 64 ビット両方のバージョンを作成する必要はなく、異なるアーキテクチャ用にビルドする際に特別な処理をする必要もないため、ほとんどのコマンドについてこの方法は妥当かつ適切なものであり、新しいサブディレクトリにも適用されてきました。アーキテクチャ依存のビルド・オプションが必要であるか、1 つのプログラムについて複数の ISA バージョンを提供しなければならない場合には、この方法は役に立たず、代わりに、ISA オブジェクトごとの複数のディレクトリから成る、より一般的なアプローチを使用する必要があります。後者のアプローチは、カーネル・モジュールに使用されるアプローチに似ています。 lib 階層の場合は多少単純です。ほぼすべてのサブディレクトリは、ISA オブジェクトごとのファイル位置と makefile を使用する必要があります。 cmd/cmd-inet や cmd/agents のように、ルールやパターンに従っていないように思われるディレクトリも少数あります。これらは主に、Sun 内部のプロジェクト編成に起因する歴史的な遺物です。
3.2.3 makefile のレイアウトこのセクションは、どのようなターゲットが存在し、ターゲットがどのように makefile によりビルドされるかを順を追って説明することを目的としています。ハードウェア・サポート・エンジニア以外には重要ではないと考えられるため、プラットフォーム固有のモジュール・アーキテクチャについては省略します。重要な 3 つの主要なサブツリーは、カーネル (uts)、コマンドとデーモン (cmd)、およびライブラリ (lib) です。次の 3 つのサブセクションでは、順に 3 つのサブツリーを扱います。また、すべてのビルドに適用される makefile も少数ながらあります。
3.2.3.1 カーネル makefile のレイアウトどのモジュールにも使用される makefile は、モジュールとそのコンポーネント・オブジェクトがビルドされるリーフ・ディレクトリ (ビルド・ディレクトリ) に置かれます。「make clobber」操作のあと、そのディレクトリには makefile だけがファイルとして残るようにする必要があります。ツリーにはほかに、接尾辞付きと接尾辞なしの 2 つの種類の makefile があります。すべてのリーフ makefile で必要な共通の定義と規則は、接尾辞付き makefile の中に含まれます。これらはリーフ makefile により含められます。接尾辞なしの makefile は、一般的には、1 回の make の呼び出しで多くのモジュールをビルドできるように、同じターゲットがある複数の下位レベルの makefile を 呼び出します。
uts ディレクトリで「make」コマンドを実行すると、すべてのサポートされているモジュール化されたカーネルとモジュールがビルドされます。 (uts/sparc などの) uts/ARCHITECTURE ディレクトリで「make」コマンドを実行すると、すべてのサポートされた「実装アーキテクチャ」に依存しない ARCHITECTURE のモジュールがビルドされます。 (uts/sun4u などの) uts/MACHINE ディレクトリで「make」コマンドを実行すると、そのカーネルと、すべてのサポートされた「実装アーキテクチャ」に依存する MACHINE のモジュールがビルドされます。 makefile については詳細にコメントを記載しましたが、以降も同様に詳細を説明します。
3.2.3.2 コマンド makefile のレイアウトほとんどのコマンドとデーモンのサブディレクトリは、オブジェクト・ファイルが配置される場所に依存して、一般的な 2 つのレイアウト規則のどちらかに従います (セクション 3.2.2.2 および 3.2.2.3 を参照)。ISA 依存のプログラムでは、レイアウトはカーネルにより使用されるものと似ています。ISA 依存のビルドの動作を必要としないプログラムは、単純な makefile のレイアウトを使用します。ここでの説明では、ソースが /usr/src/cmd/foocmd に配置されている「foocmd」という名前の汎用コマンドの例を使用します。foocmd のビルドに関連する makefile は次のとおりです。
3.2.3.3 ライブラリ makefile のレイアウトほとんどのライブラリのサブディレクトリは、同じ一般的なレイアウトに従い、コマンドのレイアウトに似ています。コマンドとは異なり、ほとんどのライブラリは 32 ビットと 64 ビット両方のアーキテクチャの種類に対してビルドされます。そのため、ほとんどの場合 ISA 固有のディレクトリが存在します。したがって、各ライブラリのビルド構造全体は、カーネルのビルド構造と似たものになります。ライブラリ makefile の詳細については、3.3.3.3 新しいライブラリを追加するを参照してください。
3.2.4 makefile の動作このセクションでは、make の依存性と規則がどのように構築され、また各 makefile がビルド・プロセスにどのように貢献するかを詳細に説明します。makefile がどのように動作するかを理解すれば、既存のビルド規則を変更し、新しいビルド規則を作成することが、既存ファイルのコピーと既存ファイルへのわずかな変更を行う際の主な作業になります。まずはカーネルの makefile から始め、続いて非常によく似たコマンドとライブラリの makefile について説明します。
3.2.4.1 カーネル makefile の動作make の依存性には、ターゲットのセットと規則のセットの 2 つがあります。 規則は、uts の下の各ディレクトリにある Makefile.rules ファイルに含まれています。これらは、ある別のディレクトリ (common/io など) にあるソース・ファイルを、前述のビルド・ディレクトリ内のオブジェクト・ファイルにコンパイルする方法を扱います。また、指定のオブジェクト・ファイルのビルドにはどのソースが必要であるかも規定します。同じベース名に一致する複数のソース・ファイルが存在する場合、規則が指定される順序により、どのソース・ファイルが必要であるかが決定されます。すべてにとって重要なことは、すべての規則とターゲットは静的でモジュールに依存しないが、各モジュールのビルド・ディレクトリ (リーフ) の makefile で設定されている変数が、モジュールに固有のビルド情報を定義していることを理解することです。 ターゲットは 2 種類から成ります。第 1 のものは、各ビルド・ディレクトリで実行される「all」または「install」のように make に与えることができる「make targets」汎用指令です。ビルド・ディレクトリの makefile には、オブジェクトとモジュールをビルドするための規則が含まれるそのほかの makefile が含まれます。第 2 の種類のターゲットはより重要で、ビルドする必要がある実際のモジュール名 (実際にはディレクトリ) です。これらの変数は KMODS および XMODS と呼ばれます。 KMODS に、たとえば「aac ata asy」が含まれている場合、aac、ata、および asy の各ビルド・ディレクトリに対して、make システムはそのディレクトリに移動し、指定されているすべてのターゲット (all、install など) を使用して make を再実行します。そのモジュールの規則は、含まれているすべての makefile から派生しています。検索すべき重要な変数は XXX_OBJS の形式です (XXX はモジュール名)。複数の makefile には、これらの各オブジェクト・リストに追加される定義が含まれる場合があります。これは、モジュールのビルドには、各プラットフォーム上で異なるオブジェクトが必要となる場合があるためです。 XMODS は、商用 Solaris 製品のエクスポート・バージョンのビルドにのみ使用されます。OpenSolaris のビルドでは使用されません。 たとえば、次のような例を考えます。
common/Makefile.files:ASY_OBJS += asy.o
これは、ASY モジュールのビルドには asy.o オブジェクトが必要であることを示しています。<プラットフォーム>/asy ディレクトリの makefile は ASY_OBJS を参照するため、何をビルドするかを認識しています。そのため、intel/asy/Makefile には次の行があります。
MODULE = asy
OBJECTS = $(ASY_OBJS:%=$(OBJS_DIR)/%)
これには多くの優れた点もあります。ALL_TARGET も定義されているためです。
ALL_TARGET = $(BINARY) $(SRC_CONFILE)
Makefile.uts は BINARY を次のように定義します。
BINARY = $(OBJS_DIR)/$(MODULE)
OBJS_DIR は、最初に説明した独立したモジュール・ビルド・ディレクトリです。そのため、make は usr/src/uts/intel/asy/obj32/asy をビルドする必要があることを認識しています。また、Makefile.targ もこのための規則を定義しています。
$(BINARY): $(OBJECTS)
$(LD) -r $(LDFLAGS) -o $@ $(OBJECTS)
$(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX)
$(POST_PROCESS)
$(ELFSIGN_MOD)
必要な作業はあと少しです。ある場所から OBJECTS を指定する必要があります。これは intel/asy/Makefile で定義されていることが分かります。
OBJECTS = $(ASY_OBJS:%=$(OBJS_DIR)/%)
以上ですべて終わりです。ASY_OBJS から作成された OBJECTS に依存する BINARY (obj32/asy) を持つモジュール (asy) を得ました。ASY_OBJS 内の各エントリの規則は、Makefile.rules ファイルのいずれか 1 つの中にあります。規則は次のようになります。
$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
各オブジェクトはこれらの規則に従ってビルドされます。続いて、$(BINARY) の規則がそれらの規則をモジュールにリンクします。 これで、すべてをまとめることができます。マクロと、ローカルのモジュールごとの定義を多用すると柔軟性が高まりますが、以下の例にある同等の makefile の一部が一般的であると考えられます。
KMODS += asy
all: $(KMODS)
asy: obj32/asy.o
$(LD) -r $(LDFLAGS) -o $@ obj32/asy.o
...
obj32/asy.o: ../../common/io/asy.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
...
3.2.4.2 コマンド makefile の動作前述したように、コマンドの makefile は非常に多様です。そのため、コマンドの makefile の「代表例」を示すことは不可能です。ただし、セクション 3.2.4.1 および 3.3.3.3 の内容を理解すれば、コマンドの makefile を使用した作業に必要な知識が得られます。このケースだけでなく、特定のコマンドに関する情報を探す場合、通常はメーリング・リストなどのコミュニティ・リソースを使用するのが最善です。
3.2.4.3 ライブラリ makefile の動作セクション 3.3.3.3 では、ライブラリ makefile の動作が詳細に説明されています。
3.2.5 ISA の依存性OpenSolaris のコードの大部分は汎用的で、プラットフォームと ISA に依存しません。つまり、適切なコンパイラが使用できる任意のシステム上でコンパイルと実行が可能な、移植性が高いコードです。ただし、移植性が高いコードであっても、実行されるシステムの特定の属性に対処しなければならない場合があり、またユーザが選択したアーキテクチャ固有のバージョンを実行し、アーキテクチャ固有のバージョンとリンクできるように、複数のサポート対象アーキテクチャ用にコンパイルして提供する必要があります。 複数のアーキテクチャ固有のビルドを用意する必要がある、2 つの明確な状況があります。性質上システムのハードウェア特性に対する可視性が必要なコマンドと、開発者が対象とするアーキテクチャごとに個別にビルドする必要があるライブラリです。各ケースを、以下のサブセクションで説明します。
3.2.5.1 ISA 依存のコマンドコマンド (通常は実行可能プログラムまたはデーモン) は通常、コマンドが実行される ISA に依存しません。つまり、ビルド対象の ISA に関係なく、同じ方法でビルドおよびインストールされます。ただし一部のコマンド (主にほかのプロセス上で動作するコマンドまたはバイナリ・オブジェクトを操作するコマンド) は、システム/ターゲットによりサポートされる まず、1 つ以上の ISA 固有のプログラムが、システムの ISA 固有のディレクトリにインストールされます。これらは、/usr/bin など、通常は実行可能プログラムを含むディレクトリのサブディレクトリです。SPARC システムでは、ISA サブディレクトリには /usr/bin/sparcv7 および /usr/bin/sparcv9 が含まれ、それぞれ 32 ビット・バイナリおよび 64 ビット・バイナリが含まれます。そのほかの ISA はそのほかのシステムによりサポートされます。isalist(1) を使用することで、システムでどの ISA がサポートされているかを調べることができます。 次に、ハード・リンクが、/usr/lib/isaexec をターゲットとする通常のバイナリ・ディレクトリ (上記の例では /usr/bin) にインストールされます。これにより、ユーザが実行した ISA 依存プログラムの名前を使用して isaexec が呼び出されます。 この時点で、isaexec は最初のステップでインストールされた最も適切な ISA 固有のプログラムを選択し、それに対して プラットフォーム固有のプログラムには同様のメカニズム (/usr/lib/platexec) が存在しますが、プラットフォーム固有のプログラムは ISA 固有のプログラムよりもはるかにまれです。 このようなメカニズムはユーザ・プロセスとカーネル・データ構造体の両方とやり取りを行う必要があるため、たとえば cmd/dtrace には Makefile と Makefile.com という 2 つの makefile が含まれます。また、1 つのソース・ファイル dtrace.c と、4 つの ISA ディレクトリ (amd64、i386、sparc、および sparcv9) が含まれます。それぞれに 1 つの makefile が含まれます。uts makefile の概要を読んだ方は、トップレベルの makefile は容易に理解できるはずです。Makefile は主にボイラープレート (定型) で、カスタマイズされるのは、作成されるプログラムが ISA 固有であり、したがって isaexec プログラムへのリンクをプロトタイプ・エリアの /usr/sbin にインストールする必要があることを指定する場合のみです。
install: $(SUBDIRS)
-$(RM) $(ROOTUSRSBINPROG)
-$(LN) $(ISAEXEC) $(ROOTUSRSBINPROG)
それ以外の場合は、ISA サブディレクトリの makefile に対するすべてのビルドとインストールを単にそのままにします。Makefile.com も定型です。ビルドするプログラムの名前と、プログラムのビルド元でなければならないオブジェクトを指定します。
PROG = dtrace
OBJS = dtrace.o
続いて、次のようにオブジェクトをソースに変換します。
SRCS = $(OBJS:%.o=../%.c)
さらに、汎用のトップレベルの Makefile.cmd 部分をインクルードし、ビルド規則をピックアップします。 コンパイルとリンクのフラグが指定されます。
CFLAGS += $(CCVERBOSE)
CFLAGS64 += $(CCVERBOSE)
LDLIBS += -ldtrace -lproc
そして残り部分は少数の汎用ビルド規則から構成されます。1 つの特徴、つまりこの部分ではすべてのパスに ../ が追加されていることに注意してください。これは、(Makefile.com それ自体よりも 1 レベル深い) ISA 固有のビルド・ディレクトリから解釈された makefile ファイルにより常にインクルードするためです。 ISA 固有のビルド・ディレクトリにある makefile はさらに単純です。それぞれがわずか 2 行で構成されています。
include ../Makefile.com
install: all $(ROOTUSRSBINPROG32)
最初の行は、直前に説明した makefile 内のすべての共通の定義をピックアップし、2 行目は (間接的に) プログラムがインストールされる場所を指定します。解説を補完するため、プログラムをインストールできるさまざまな場所を定義する usr/src/cmd/Makefile.cmd を手短に調べる必要があります。ROOTUSRSBINPROG32 を定義していないため、この場所で定義する必要があります。実際には次のようになります。
ROOTUSRSBIN= $(ROOT)/usr/sbin
ROOTUSRSBINPROG=$(PROG:%=$(ROOTUSRSBIN)/%)
ROOTUSRSBIN32= $(ROOTUSRSBIN)/$(MACH32)
ROOTUSRSBINPROG32= $(PROG:%=$(ROOTUSRSBIN32)/%)
プログラムは実際には (通常はユーザの検索パス内にない) /usr/sbin/$(MACH32) にインストールされることに注意してください。ただし、$(ROOTUSRSBINPROG) から $(ISAEXEC) へのリンクを作成したことにも注意してください。これらの変数を展開することで、実際に 2 つの独立したファイルをインストールすることがわかります。
$(ROOT)/usr/sbin/dtrace -> $(ROOT)/usr/lib/isaexec
$(ROOT)/usr/sbin/$(MACH32)/dtrace (実際の実行プログラム)
isaexec プログラムは、システムのサポート対象命令セットに応じて複数のオプションの中から ISA 固有のプログラムを選択する役割があるため、一般的なシステムには 1 つ以上の
3.2.5.2 ISA 依存のライブラリライブラリは、コマンドとは異なり、常にすべてのサポート対象 ISA に対してビルドされる必要があり、また少なくともその ISA をサポートするあらゆるシステムに個別の ISA 固有のバージョンがインストールされている必要があります。実際には、システムのプロセッサ・ファミリの各 ISA 用のライブラリがインストールされます。これにより、そのシステムの開発者は、任意のサポート対象 ISA を使用するプログラムを作成し、それらを適切なシステム・ライブラリにリンクすることができます (たとえば 32 ビットのオブジェクト・ファイルと 64 ビットのライブラリをリンクすることは不可能で、またその逆も不可能です)。 ライブラリは、複数の ISA 固有の実行可能プログラムを提供する必要があるコマンドにより使用されるビルド・システムによく似たビルド・システムを使用します。ここでは、dtrace(1) のライブラリに相当する lib/libdtrace には Makefile と Makefile.com という 2 つの makefile が含まれます。また、共通コード用のディレクトリと、4 つの ISA ディレクトリ (amd64、i386、sparc、および sparcv9) が含まれます。各 ISA ディレクトリには 1 つの makefile が含まれ、場合によっては複数の ISA 固有のソースが含まれます。この場合も、トップレベルの Makefile は容易に理解できるはずです。uts および cmd の makefile によく似ていて、主に定型で使用されます。yydebug ターゲットを追加し、lex および yacc により生成されたファイルはそれらに対してビルドされたクロスリファレンスを持ってはならないことを通知する、多少のカスタマイズを行います。
yydebug := TARGET = yydebug
...
lint yydebug: $(SUBDIRS)
および
XRDIRS = common i386 sparc sparcv9
XRDEL = dt_lex.c dt_grammar.c Makefile*
それ以外の場合は、ISA サブディレクトリの makefile に対するすべてのビルドとインストールを単にそのままにします。Makefile.com はある意味においてより重要です。まず、ビルドするライブラリの名前 (静的書式。共有ライブラリ名は以降で説明するように変換される) とライブラリのバージョンを指定します。これらはすべてのライブラリ makefile で共通です。次に、ライブラリのビルドに使用されるソース・ファイルの長いリストと、OBJECTS の仕様があります。また、この特別なライブラリには、独立したオブジェクト・ファイル (drti.o) としてビルドされる D ランタイム init コードと、独立したディレクトリ /usr/lib/dtrace にインストールされる多数の D「ヘッダー」ファイルを含む、独自の特性もいくつかあります。これらの独自の特性は、以下で確認できます。
DRTISRC = drti.c
DRTIOBJ = $(DRTISRC:%.c=%.o)
DLIBSRCS += \
errno.d \
io.d \
procfs.d \
regs.d \
sched.d \
signal.d \
unistd.d
...
ROOTDLIBDIR = $(ROOT)/usr/lib/dtrace
ROOTDLIBDIR64 = $(ROOT)/usr/lib/dtrace/64
...
$(ROOTDLIBDIR):
$(INS.dir)
$(ROOTDLIBDIR64): $(ROOTDLIBDIR)
$(INS.dir)
$(ROOTDLIBDIR)/%.d: ../common/%.d
$(INS.file)
$(ROOTDLIBDIR)/%.d: ../$(MACH)/%.d
$(INS.file)
$(ROOTDLIBDIR)/%.d: %.d
$(INS.file)
D「ヘッダー」の一部は、ほかのファイルから生成されることに注意してください。この makefile には、これらの変換を行うための規則が含まれます。 LIBSRCS と OBJECTS が定義されれば、ターゲットとディレクトリを定義するため、汎用ライブラリの makefile の一部である Makefile.lib がインクルードされます。 バイナリ・オブジェクトは pics/ サブディレクトリにビルドされます。pics は position- independent code(s) (位置に依存しないコード) の省略形で、動的共有ライブラリは任意のアドレスにロードされるようにビルドされるということを意味します。これは歴史的な遺物で、OpenSolaris では静的リンクはサポートされていないため、アーカイブスタイルのライブラリのビルドに使用される非 PIC オブジェクトはビルドされません。ビルドの規則は次のとおりです。
pics/%.o: ../$(MACH)/%.c
$(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
pics/%.o: ../$(MACH)/%.s
$(COMPILE.s) -o $@ $<
$(POST_PROCESS_O)
%.o: ../common/%.c
$(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
この makefile の一部は各 ISA の makefile によりインクルードされるため、作成されるオブジェクトは各 ISA ディレクトリ内でその makefile から相対的に配置されます。この場合も、このことは、インクルードされた makefile の一部には追加の ../ コンポーネントが含まれることも意味します。 libdtrace の Makefile.com にも、 ISA 固有のビルド・ディレクトリ内の makefile も非常に単純です。たとえば SPARC 固有の makefile は、追加のアセンブラ・フラグを定義し、ライブラリ・インタフェース・マップを配置するディレクトリを指定し、共通の makefile を含みます。
ASFLAGS += -D_ASM -K PIC -P
MAPDIR = ../spec/sparc
include ../Makefile.com
この makefile は、少数の ISA 固有のソースをビルド・リストに追加する場合もあります。たとえば sparc/Makefile には次のものが含まれます。
SRCS += dt_asmsubr.s
OBJECTS += dt_asmsubr.o
またこの場合も、これら固有のライブラリとヘッダーをインストールする必要があるディレクトリを示すために、独立したインストール・ターゲットが用意されます。
install yydebug: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) \
$(ROOTDLIBS) $(ROOTDOBJS)
64 ビット・オブジェクトの独立したセットのビルドをサポートするため、sparcv9/Makefile には、わずかに異なる定義と異なるインストール・ターゲットが含まれます。
MAPDIR = ../spec/sparcv9
include ../Makefile.com
include ../../Makefile.lib.64
CPPFLAGS += -D_ELF64
...
install yydebug: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) \
$(ROOTDLIBS) $(ROOTDOBJS64)
Makefile.lib.64 が追加でインクルードされていることと、64 ビットの ELF ターゲット用の追加フラグに注意してください。また、インストール・ファイルの 64 ビット固有のバージョンが使用されています。Makefile.lib で確認できるように、/usr/lib/sparcv9 にインストールされます。
ROOTLIBDIR= $(ROOT)/usr/lib
ROOTLIBDIR64= $(ROOT)/usr/lib/$(MACH64)
...
ROOTLIBS= $(LIBS:%=$(ROOTLIBDIR)/%)
ROOTLIBS64= $(LIBS:%=$(ROOTLIBDIR64)/%)
リンカー (ld(1)) およびランタイム・ローダー (ld.so.1(1)) は、それぞれ、リンクされるオブジェクトまたは実行されるプログラムのビット数に応じて、どのディレクトリでライブラリを検索すべきかを認識しています。32 ビット・リンクと 64 ビット・リンクの対比の詳細については、http://docs.sun.com/db/doc/816-1386 にある『Solaris リンカーとライブラリ』を参照してください。
3.2.6 カーネル・モジュールのインストールについてインストール・ターゲットにより、バイナリとヘッダーは、プロトタイプ・エリアまたはプロトタイプ・エリアと呼ばれる階層にインストールされます (プロトタイプ・エリアの内容と目的の詳細については、セクション 4.4.1 を参照)。プロトタイプ・エリアのルートは、環境変数 ROOT により定義されます。この変数は、usr/src/uts/Makefile.uts において ROOT_MOD_DIR および USR_MOD_DIR を定義する際に使用されます。
ROOT_MOD_DIR = $(ROOT)/kernel
USR_MOD_DIR = $(ROOT)/usr/kernel
すべてのモジュールは、これらのディレクトリのいずれかの下にインストールされます。使用される正確なサブディレクトリは、以下で説明するモジュール・ビルド・ディレクトリの ROOTMODULE の定義に応じて決まります。 この makefile の INSTALL_TARGET 定義により、インストールされる追加ファイルが指定される場合があります。たとえば、asy makefile (usr/src/uts/intel/asy/Makefile) は次のように指定を行います。
INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) $(ROOT_ITUFILE)
これはインストール・ターゲットの共通セットであるため、各コンポーネントがどのように派生するかを調べると、次のことが分かります。 $(BINARY) は、それ自体は単なるモジュールです。その依存性と規則の詳細は上記で説明しました。$(BINARY) をこの場所に含めるには、インストールを試みる前に完全にビルドされている必要があります。 $(ROOTMODULE) はモジュールの名前に対する名前変換で、モジュールをプロトタイプ・エリアに再配置します。たとえば、usr/src/uts/intel/asy/Makefile は次のように定義を行います。
ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
ROOT_DRV_DIR には多少の補足的な説明が必要です。これは、Makefile.uts で定義されている数多くのモジュール・インストール・サブディレクトリの 1 つです。バイナリ・カーネル・モジュールの終了位置はマシン・タイプ (特に 32 ビットと 64 ビットの対比) によって決まるため、実際には複数の定義が存在します。まず、各 64 ビットのマシン・タイプのサブディレクトリ定義は次のようになります。
SUBDIR64_sparc = sparcv9
SUBDIR64_i386 = amd64
SUBDIR64 = $(SUBDIR64_$(MACH))
次に、各タイプのモジュールの 32 ビットおよび 64 ビットのインストール・ディレクトリは次のようになります。
ROOT_KERN_DIR_32 = $(ROOT_MOD_DIR)
ROOT_DRV_DIR_32 = $(ROOT_MOD_DIR)/drv
ROOT_DTRACE_DIR_32 = $(ROOT_MOD_DIR)/dtrace
ROOT_EXEC_DIR_32 = $(ROOT_MOD_DIR)/exec
...
ROOT_KERN_DIR_64 = $(ROOT_MOD_DIR)/$(SUBDIR64)
ROOT_DRV_DIR_64 = $(ROOT_MOD_DIR)/drv/$(SUBDIR64)
ROOT_DTRACE_DIR_64 = $(ROOT_MOD_DIR)/dtrace/$(SUBDIR64)
ROOT_EXEC_DIR_64 = $(ROOT_MOD_DIR)/exec/$(SUBDIR64)
...
最後に、当該ビルドの実際のビット数に基づく、32 ビットまたは 64 ビット・ディレクトリの選択を示します。
ROOT_KERN_DIR = $(ROOT_KERN_DIR_$(CLASS))
ROOT_DRV_DIR = $(ROOT_DRV_DIR_$(CLASS))
ROOT_DTRACE_DIR = $(ROOT_DTRACE_DIR_$(CLASS))
ROOT_EXEC_DIR = $(ROOT_EXEC_DIR_$(CLASS))
...
$(ROOT)/usr/kernel をベースとする USR_XXX_DIR には同じような定義が存在します。可能な ROOT_ および USR_ インストール・ディレクトリの完全なリストは、usr/src/uts/Makefile.uts を参照してください。 これらの各ディレクトリにファイルをインストールするための規則は、usr/src/uts/Makefile.targ で指定されています。
$(ROOT_MOD_DIR)/%: $(OBJS_DIR)/% $(ROOT_MOD_DIR) FRC
$(INS.file)
$(ROOT_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_DRV_DIR) FRC
$(INS.file)
...
これらの規則により、(上記で詳細を説明した) $(OBJS_DIR) に現在位置しているファイルが、プロトタイプ・エリアの適切なディレクトリにインストールされます。 $(ROOT_CONFFILE) は、プロトタイプ・エリアに変換された、モジュールの構成ファイルです (ドライバに頻繁に使用されます)。CONFFILE 変数は、usr/src/uts/Makefile.uts で次のように定義されています。
CONFFILE = $(MODULE).conf
SRC_CONFFILE = $(CONF_SRCDIR)/$(CONFFILE)
ROOT_CONFFILE_32 = $(ROOTMODULE).conf
ROOT_CONFFILE_64 = $(ROOTMODULE:%/$(SUBDIR64)/$(MODULE)=%/$(MODULE)).conf
ROOT_CONFFILE = $(ROOT_CONFFILE_$(CLASS))
各モジュールの Makefile は、CONF_SRCDIR を定義して、当該プラットフォームにインストールする必要がある構成ファイルの位置を指定します。asy makefile は次のように定義を行います。
CONF_SRCDIR = $(UTSBASE)/common/io
これにより、usr/src/uts/common/io/asy.conf は、/kernel/drv/asy.conf としてプロトタイプ・エリアにインストールされます。構成ファイルのインストール・ディレクトリは、32 ビットと 64 ビットのどちらのビルドであるかに依存しないことに注意してください。 $(ROOT_ITUFILE) は、標準ビルドでは使用されません。 混乱を招きますが、インストール・ターゲットは、実際に USR_ ディレクトリの 1 つにインストールされる場合であっても、常に ROOTMODULE、ROOT_CONFFILE などの名前が付けられることに注意してください。これにより、より高いレベルの makefile が単純になります。
3.2.7 モジュールのソースの検索すでに説明したように、ソースは、$(XXX_OBJS) と含まれる規則から派生します。ここでは、これらのソースがどこにあるかを見つけるという扱いにくい問題を説明します。間違いなく最も簡単な方法は、モジュールのオブジェクト・ディレクトリから make を実行して、実行されるコンパイル・コマンドを確認する方法です。出力には、各ソース・ファイルへのパスが含まれます。これが、モジュールのビルドにはどのソース・ファイルが必要であるかを見つける最も簡単な推奨方法です。ただし、この方法がうまくいかない場合 (多くは makefile 自体に問題がある)、または理解を深めたい場合のため、このセクションの残りでソース・ファイルを見つけるための論理的プロセスを説明します。 ベース名 (単に .o が .c により置換されている XXX_OBJS エントリ) は判明しているため、次の単純な形式を使用できます。
$ find usr/src/uts -name asy.c
同じ名前を持つ 2 つのソース・ファイルが見つかった場合は、どちらが実際に使用されているかが問題になります。この問題の答えを出すには 2 つの方法があります。簡単な方法としては、make -d を使用して、使用されている正確な依存関係を表示する方法があります。または、プラットフォームではすべてのソース・ファイルが使用されているわけではない (たとえば x86 のビルドでは usr/src/uts/sparc/* は使用されない) という事実を出発点にして、各 Makefile.rules における規則の特定の順序を調べて、この問題を議論して解決することができます。より限定的な規則がまず示され、後に来る規則よりも優先されます (事実、後に来る規則はすべて当の特定のオブジェクト・ファイルに依存性を追加しますが、規則はすべて $< を使用するため、実際には最初の依存性のみが使用されます)。 一般的に cmd および lib ディレクトリは、ライブラリまたはコマンドごとに 1 つのサブディレクトリを使用して編成され、それに従って名前が付けられるため、非カーネル・ソース・ファイルは比較的特定が容易です。主な例外としては (バイナリ・ツールのサブシステム全体が含まれる) cmd/sgs と、cmd/cmd-inet があります。cmd/cmd-inet には、Berkeley ネットワーク・コマンドおよびデーモンの大部分だけでなく、複数の追加のネットワーク関連ユーティリティが含まれ、それらは BSD スタイルのディレクトリ構造に配置されています。
3.2.8 含まれていないソース・ファイルSolaris ブランド製品のビルドに使用される一部のソースは、OpenSolaris には含まれていません。これには主な理由が 3 つあります。
一部のソースが存在しない場合であっても完全に機能するビルドを提供するために、クローズド・バイナリのセットが使用可能で、またビルド・システムはそれらを使用するように変更されています。ただし、一部の makefile は意図せずこれらのクローズド・バイナリ・ファイルを参照する場合があります。このような例に気づいた場合は、バグを送信する必要があります。最後に、ソース・ファイルが含まれていても、含まれていないそのほかのソースに依存している場合があります。このようなケースでは、検討用にソースのサブセットが使用できる場合であっても、どちらのソースもビルドされません。 |