Solaris 64 ビット 開発ガイド

第 5 章 開発環境

この章では 64 ビットアプリケーション開発環境について説明します。構築環境、その他ヘッダーおよびライブラリの問題、コンパイラオプション、リンク、およびデバッグツールについて説明します。パッケージ処理に関するガイドラインも示します。

まず、オペレーティングシステムのバージョンが 32 ビットであるかあるいは 64 ビットであるかを確認する必要があります。これを確認するには、第 3 章「32 ビットと 64 ビットインタフェースの比較」で説明した isainfo(1) コマンドを使用することができます。この章での説明は、64 ビットオペレーティングシステムを使用していると仮定しています。32 ビットオペレーティング環境を使用している場合でも、システム上に 64 ビットライブラリパッケージがインストールされていれば、64 ビットアプリケーションを構築することができます。

構築環境

構築環境には、システムヘッダー、コンパイルシステム、およびライブラリが含まれています。

ヘッダー

1 組のシステムヘッダーが 32 ビットおよび 64 ビットのコンパイル環境をサポートします。64 ビットコンパイル環境用に別のインクルードパスを指定する必要はありません。

64 ビット環境をサポートするためにヘッダーに加えられた変更をより理解するには、ヘッダーの <sys/isa_defs.h> のさまざまな定義について理解しておくことをお薦めします。このヘッダー中には #define が含まれており、それらは各命令セットアーキテクチャに対して設定されています。<sys/types.h> をインクルードすると、自動的に <sys/isa_defs.h> がインクルードされます。

次の表にあるシンボルは、コンパイル環境 (コンパイラ) によって定義されます。

__sparcSPARC ファミリーのプロセッサアーキテクチャのいずれかであることを示します。アーキテクチャには SPARC V7、SPARC V8、および SPARC V9 があります。シンボルの sparc は、慣例上 __sparc の同義語です。
__sparcv8 『SPARC Architecture Manual』のバージョン 8 で定義されている 32 ビット SPARC V8 アーキテクチャを示します。
__sparcv9 『SPARC Architecture Manual』のバージョン 9 で定義されている 64 ビット SPARC V9 アーキテクチャを示します。
__i386 このシンボルは、Intel 386 命令セットあるいはそのスーパーセットを実装するすべてのプロセッサに対する総称です。これには、386、486、および Pentium ファミリーのプロセッサのすべてのメンバーが含まれます。

シンボル __sparcv8 および __sparcv9 は、相互に排他的で (両方が同時に定義されることはありません) 、シンボル __sparc が定義されているときにだけ意味があります。

次に示すシンボルは、上記のシンボルのいくつかの組み合わせから派生したものです。

_ILP32intlong、およびポインタのサイズがすべて 32 ビットであるデータ型モデル
_LP64long およびポインタのサイズがすべて 64 ビットであるデータ型モデル

シンボル _ILP32 および _LP64 も、相互に排他的です。

完全に移植性のあるコードを書くことが不可能で、32 ビットおよび 64 ビットのそれぞれに固有のコードが必要な場合は、_ILP32 または _LP64 を使って、コードを条件付きで切り替えるようにしてください。これによって、コンパイルマシンに依存しないコンパイル環境にすることができ、アプリケーションをすべての 64 ビットプラットフォームに移植する際の移植性が高くなります。

コンパイラ

Sun WorkShop C、C++、および Fortran のコンパイル環境が拡張され、32 ビットおよび 64 ビットアプリケーションの両方を作成できるようになりました。Sun WorkShop で提供される C コンパイラの 5.0 リリースは、64 ビットコンパイルをサポートします。

ネイティブコンパイルモードおよびクロスコンパイルモードがサポートされています。デフォルトのコンパイル環境は、これまでどおり 32 ビットアプリケーションを作成します。ただし、両モードともアーキテクチャに依存します。Sun コンパイラを使用して、Intel マシン上で SPARC オブジェクトを作成したり、SPARC マシン上で Intel オブジェクトを作成することはできません。アーキテクチャやコンパイラのモードが指定されていない場合は、適宜 __sparc または __i386 シンボルがデフォルトで定義され、この一部として _ILP32 も定義されます。これによって、既存のアプリケーションおよびハードウェアにおける相互運用性が高くなります。

たとえば、Sun WorkShop C コンパイラを使用して SPARC マシンで 64 ビットコンパイル環境を使用できるようにする場合は、-xarch=v9 フラグを cc(1) への引数として指定する必要があります。

これによって LP64 コードが含まれる ELF64 オブジェクトが生成されます。ELF64 とは、64 ビットのプロセッサおよびアーキテクチャをサポートする 64 ビットオブジェクトファイル形式のことです。一方、デフォルトの 32 ビットモードでコンパイルしたときは、ELF32 オブジェクトファイルが生成されます。

-xarch=v9 フラグを使用すると、32 ビットまたは 64 ビットのどちらのシステムでもコードを生成できます。32 ビットコンパイラを使用すると、-xarch=v9 によって 32 ビットシステムで 64 ビットのオブジェクトを作成できますが、作成したオブジェクトは 32 ビットシステムでは実行できません。64 ビットライブラリに対するライブラリパスを指定する必要はありません。-l または -L オプションを使用してライブラリまたはライブラリパスを追加指定し、そのパスが 32 ビットライブラリだけを指している場合は、リンカーはそれを検出し、エラーを出力してリンク処理を異常終了します。

ライブラリ

Solaris オペレーティング環境には、32 ビットおよび 64 ビットの両コンパイル環境用の共用ライブラリが含まれています。静的ライブラリについては、32 ビットのみが含まれており、64 ビットは提供されていません。

32 ビットアプリケーションは 32 ビットライブラリとリンクし、64 ビットアプリケーションは 64 ビットライブラリとリンクしなければなりません。64 ビットライブラリを使って 32 ビットアプリケーションを作成または実行することはできません。32 ビットライブラリは、これまでどおり /usr/lib および /usr/ccs/lib に置かれています。64 ビットライブラリは、SPARC プラットフォームでは適切な lib ディレクトリの sparcv9 サブディレクトリに置かれています。32 ビットライブラリの場所は変更されていないので、Solaris 2.6 以前のオペレーティング環境で構築された 32 ビットアプリケーションとのバイナリの互換性があります。

64 ビットアプリケーションを構築するためには 64 ビットライブラリが必要です。64 ビットライブラリは、32 ビットおよび 64 ビットの両環境で利用できるため、ネイティブコンパイルもクロスコンパイルも可能です。コンパイラとその他のツール (たとえば ldaras など) は 32 ビットプログラムで、32 ビットまたは 64 ビットシステム上で 64 ビットプログラムを構築する機能があります。もちろん、32 ビットオペレーティング環境上のシステムで作成された 64 ビットプログラムは、32 ビット環境では実行できません。

リンク処理

リンカーは、32 ビットアプリケーションのままですが、ほとんどのユーザーはこのことを意識する必要がありません。通常リンカーはコンパイラドライバ (たとえば cc(1)) から間接的に呼び出されるからです。ELF32 オブジェクトファイルをリンカーへの入力として指定すると、リンカーは ELF32 出力ファイルを生成します。同様に、入力として ELF64 オブジェクトファイルを指定すれば、ELF64 出力ファイルを生成します。ELF32 と ELF64 の入力ファイルを混在させて指定しようとしてもリンカーに拒絶されます。

LD_LIBRARY_PATH

32 ビットおよび 64 ビットのアプリケーション用の動的リンカープログラムは、それぞれ /usr/lib/ld.so.1/usr/lib/sparcv9/ld.so.1 です。

これらの動的リンカーは両方とも、LD_LIBRARY_PATH 環境変数で指定された、コロンで区切られたディレクトリ名のリストを実行時に検索します。32 ビット動的リンカーは 32 ビットライブラリとだけ結合し、64 ビット動的リンカーは 64 ビットライブラリとだけ結合します。したがって、必要であれば 32 ビットおよび 64 ビットライブラリの両方を格納しているディレクトリを環境変数 LD_LIBRARY_PATH で指定することができます。

64 ビット動的リンカーの検索パスは、LD_LIBRARY_PATH_64 環境変数を使って完全に上書きする (優先させる) ことができます。

$ORIGIN

アプリケーションを配布し管理するための共通の手法として、関連するアプリケーションとライブラリを 1 つのディレクトリ階層に入れる手法があります。一般的に、アプリケーションが使用するライブラリは lib サブディレクトリに置き、アプリケーションそのものはベースディレクトリの bin サブディレクトリに置きます。このベースディレクトリは、Sun が配布するコンピューティングファイルシステムである NFSTM によりエクスポートし、クライアントマシンにマウントできます。環境によっては、オートマウンタとネームサービスを使用して、アプリケーションを配布し、すべてのクライアントにおいてアプリケーション階層のファイルシステムの名前空間を同じにすることもできます。そのような環境では、-R オプションをリンカーに指定してアプリケーションを構築できます。このオプションは、実行時に共用ライブラリを検索するディレクトリの絶対パス名を指定します。

ただし環境によっては、ファイルシステムの名前空間がうまく制御されず、開発者がデバッグ用のツール、つまり LD_LIBRARY_PATH 環境変数を使ってラッパースクリプトにライブラリの検索パスを指定するという手法を採用していました。このようなことはもはや必要ありません。これは、$ORIGIN キーワードをリンカーの -R オプションに指定されたパス名に含めることができるからです。$ORIGIN キーワードは、実行可能プログラムそのものがあるディレクトリ名に実行時に展開されます。つまり、$ORIGIN からの相対パス名でライブラリディレクトリのパス名を指定できるということです。この結果、LD_LIBRARY_PATH をまったく設定しなくても、アプリケーションのベースディレクトリを移動することができるようになります。

この機能は 32 ビットおよび 64 ビットの両方のアプリケーションで利用できます。新しいアプリケーションを作成する場合に、LD_LIBRARY_PATH を正しく構成するユーザーやスクリプトに対する依存性を減らしたいときに、この機能を利用できます。

詳細は、『リンカーとライブラリ』を参照してください。

パッケージ処理

以降の節では 32 ビットおよび 64 ビットアプリケーションのパッケージ処理について説明します。

ライブラリとプログラムの配置

新しいライブラリとプログラムの配置については、「ライブラリ」に記載されている標準規則に従います。32 ビットライブラリは従来どおり同じ場所に置かれますが、64 ビットライブラリは、通常のデフォルトのディレクトリ内の、アーキテクチャに依存する特定のサブディレクトリに置くことをお薦めします。32 ビットおよび 64 ビットにそれぞれ固有のアプリケーションは、ユーザーにとって透過的な (32 ビットと 64 ビットとの違いを意識する必要がない) 場所に置くようにしてください。

つまり SPARC マシンでは、32 ビットライブラリは同じライブラリディレクトリに置き、64 ビットライブラリは適切な lib ディレクトリ下の sparcv9 サブディレクトリに置く必要があります。

32 ビットまたは 64 ビット環境に固有のバージョンを必要とするプログラムは、通常置かれるディレクトリ下の sparcv7 または sparcv9 サブディレクトリに適宜置くことをお薦めします。

「アプリケーション命名規則」を参照してください。

パッケージ処理のガイドライン

パッケージ処理の選択肢として、32 ビットおよび 64 ビットアプリケーション用にそれぞれパッケージを別々に作成するか、あるいは 32 ビットおよび 64 ビットバージョンを 1 つの パッケージにまとめるか、という問題があります。1 つのパッケージを作成する場合は、この章で説明しているサブディレクトリの命名規則をパッケージの内容に対して適用することをお薦めします。

アプリケーション命名規則

32 ビットおよび 64 ビットのアプリケーションに対して、foo32foo64 のような特定の名前を付ける代わりに、32 ビットおよび 64 ビットアプリケーションを 「ライブラリとプログラムの配置」で説明したように、プラットフォーム固有の適切なサブディレクトリに置くことができます。このようにすると、次の項で説明しているラッパーを使用して、環境に応じて 32 ビットまたは 64 ビットのいずれかのアプリケーションを実行することができます。利点としては、プラットフォームに応じて適切なバージョンのアプリケーションが自動的に実行されるため、ユーザーは 32 ビットまたは 64 ビットのどちらであるかなどについて意識する必要がありません。

ラッパー

32 ビットおよび 64 ビット固有のバージョンのアプリケーションが必要な場合、シェルスクリプトラッパーを使うと、ユーザーがバージョンに関して意識する必要がなくなります。32 ビットおよび 64 ビットバージョンが必要な、Solaris オペレーティング環境の多くのツールが、この例として当てはまります。ラッパーを利用すると、特定のハードウェアプラットフォーム上で実行可能な固有の命令セットを isalist() コマンドを使って調べ、それに基づいて適切なバージョンのツールを実行させることができます。

次に、ネイティブ命令セットラッパーの例を示します。


#! /bin/sh 
 
CMD='basename $0'
DIR='dirname $0'
EXEC=
for isa in '/usr/bin/isalist'; do	
	if [-x ${DIR}/${isa}/${CMD}]; then		
		EXEC=${DIR}/${isa}/${CMD}
		break	
	fi
done
if [-z "${EXEC}"]; then	
		echo 1>&2 "$0: no executable for this architecture"
		exit 1
 
fi
exec ${EXEC} "${@}"

この例には問題が 1 つあります。$0 引数が、その引数自身の実行可能プログラムに対する完全パス名であることを前提にしていることです。このような理由から、汎用的なラッパーである isaexec() が作成され、32 ビットおよび 64 ビット固有のアプリケーションの問題に対処しています。引き続きこの isaexec(3C) ラッパーについて説明します。

/usr/lib/isaexec

isaexec(3C) は 32 ビット実行可能バイナリファイルです。直前の節で説明したようなシェルスクリプトラッパー機能を実行しますが、その際引数リストも正確に保存します。実行可能プログラムの完全パス名は /usr/lib/isaexec ですが、この名前で実行するようには設計されていません。このプログラムでは、isalist(1) によって選択された複数のバージョンで存在するプログラムの主要な名前 (プログラム実行時にユーザーが使用する名前) にコピーされたり、リンク (シンボリックリンクではなくハードリンク) される可能性があります。

たとえば、truss(1) コマンドは、次の 3 つの実行可能ファイルとして存在します。


/usr/bin/truss
/usr/bin/sparcv7/truss
/usr/bin/sparcv9/truss

sparcv7sparcv9 サブディレクトリの実行可能プログラムは、実在する truss(1) 実行可能プログラムで、それぞれ 32 ビットおよび 64 ビットプログラムです。ラッパーファイルの /usr/bin/truss は、/usr/lib/isaexec にハードリンクされています。

isaexec(3C) ラッパーは、完全に解決されたシンボリックリンクがない自分のパス名を、argv[0] 引数とは別に getexecname(3C) を使用して調べ、sysinfo(SI_ISALIST , ...) を使用して isalist(1) を取得します。そして、その結果得られた自分自身のディレクトリのサブディレクトリリストを調べ、自分の名前がある最初の実行可能ファイルに対して execve(2) を実行します。そのとき isaexec(3C) ラッパーは、引数ベクトルと環境ベクトルを変更せずに渡します。このようにして、argv[0] は最初に指定されたとおりに最終的なプログラムイメージに渡されます。サブディレクトリ名を含むように修正された完全パス名に変換された形ではありません。


注 -

ラッパーが存在する場合があるため、実行可能プログラムを他の場所に移動する際は注意が必要です。実際のプログラムではなく、ラッパーを移動してしまう可能性があります。


isaexec()

多くのアプリケーションでは、すでに起動ラッパープログラムを使用して、環境変数の設定、一時ファイルの消去、デーモンの起動などを行なっています。libc(3LIB) 内の isaexec(3C) インタフェースを利用すると、前述のようなシェルスクリプトラッパーの例で使用しているのと同じアルゴリズムを、カスタマイズしたラッパープログラムから直接呼び出すことができます。

デバッグ処理

truss(1) コマンド、/proc ツール (proc(1))、adbdbx、および adbgen などの、Solaris 上で実行できるデバッグツールのすべてが、64 ビットアプリケーションで動作するようにアップグレードされています。

これらのデバッグツールのうち、64 ビットアプリケーションをデバッグできる dbx デバッガは、Sun Workshop ツール群の一部として入手できます。それ以外のツールはすべて Solaris リリースの中に含まれています。

adbgen は、指定した adb(1) マクロを作るプログラムを生成します。64 ビットマクロを生成するために -m lp64 オプションを指定し、64 ビットシステム上で実行する必要があります。詳細は、adbgen(1M) のマニュアルページを参照してください。

adbgen 以外の上記のデバックツールのオプションには変更がありません。64 ビットプログラムをデバッグするために、adb に対しては、多数の拡張が加えられました。ポインタを間接参照するために「*」を使用すると、64 ビットプログラムに対しては 8 バイトを、32 ビットプログラムに対しては 4 バイトを参照します。さらに、次の修飾子が新たに追加されました。


Additional ?, /, = modifiers:
	
g		(8) Display 8 bytes in unsigned octal	
G		(8) Display 8 bytes in signed octal
e		(8) Display 8 bytes in signed decimal	
E		(8) Display 8 bytes in unsigned decimal
J		(8) Display 8 bytes in hexadecimal
K		(n) Print pointer or long in hexadecimal
		  Display 4 bytes for 32-bit programs
		  and 8 bytes for 64-bit programs.
y		(8) Print 8 bytes in date format
 
Additional ? and / modifiers:
 
M <value> <mask>  Apply <mask> and compare for 8-byte value;
		  move '.' to matching location.
Z		(8) write 8 bytes