Oracle® Solaris 11.2 リンカーとライブラリガイド

印刷ビューの終了

更新: 2014 年 7 月
 
 

条件付き入力

mapfile 内の行は、特定の ELFCLASS (32 ビットまたは 64 ビット) あるいは機械タイプにのみ適用されるように条件付けできます。

        $if expr
        ....
        [$elif expr]
        ....
        [$else]
        ....
        $endif

条件付き入力式は、論理的な true または false の値に評価されます。それぞれの指令 ($if$elif$else、および $endif) は 1 行に 1 つ記述します。$if 行と後続の $elif 行の中の式は、true と評価される式が見つかるまで順番に評価されます。false の値を持つ行に続くテキストは、破棄されます。true の指令の行に続くテキストは、通常どおり処理されます。この説明のテキストとは、条件文の一部でない任意の内容を表します。true となる $if または $elif が見つかり、そのテキストが処理されると、後続の $elif および $else 行に加え、それらのテキストも破棄されます。すべての式がゼロで、$else がある場合、$else に続くテキストが通常どおり処理されます。

$if 指令の範囲は、複数の mapfile を超えることはできません。$if 指令は、$if 指令を使用する mapfile 内で、対応する $endif によって終了する必要があり、終了しない場合はリンカーはエラーを生成します。

リンカーは、$if および $elif によって評価される論理式に使用できる名前の内部テーブルを保持します。このテーブルは起動時に、次の表内のそれぞれの名前で初期化され、作成中の出力オブジェクトに適用されます。

表 8-4  定義済みの条件式の名前
名前
意味
_ELF32
32 ビットオブジェクト
_ELF64
64 ビットオブジェクト
_ET_DYN
共有オブジェクトファイル
_ET_EXEC
実行可能オブジェクト
_ET_REL
再配置可能オブジェクト
_sparc
SPARC マシン (32 ビットまたは 64 ビット)
_x86
x86 マシン (32 ビットまたは 64 ビット)
true
常に定義済み

名前は大文字と小文字を区別して、示されたとおりの名前を使用する必要があります。たとえば、true は定義されていますが、TRUE は定義されていません。これらのすべての名前は、それ自体を論理式として使用できます。次に例を示します。

        $if _ELF64
        ....
        $endif

出力オブジェクトが 64 ビットの場合、この例は true に評価され、リンカーは囲まれたテキストを処理します。これらの論理式では数値は許可されませんが、特殊な例外として、値 1true に評価され、0false に評価されます。

未定義のすべての名前は false に評価されます。一般的に、無条件にスキップする必要がある入力行を指定するために、未定義の名前 false を使用します。

        $if false
        ....
        $endif

次の表に示す演算子を使用すると、さらに複雑な論理式を記述できます。

表 8-5  条件式の演算子
演算子
意味
&&
論理積
||
論理和
( 式 )
式の一部
!
後続の式のブール値を否定します

式は左から右に評価されます。式の一部は、それを囲む式の前に評価されます。

たとえば、x86 プラットフォーム用の 64 ビットオブジェクトを構築するとき、次の構造構文が評価されます。

        $if _ELF64 && _x86
        ....
        $endif

$add 指令を使用すると、リンカーの既知の名前テーブルに新しい名前を追加できます。前の例を使用すると、$if 指令を簡素化するために、64 ビット x86 オブジェクトを表す amd64 という名前を定義すると便利な場合もあります。

        $if _ELF64 && _x86
        $add amd64
        $endif

これを使用すると、前の例を簡素化できます。

        $if amd64
        ....
        $endif

リンカーの –z mapfile-add オプションを使用することによって、リンカーの既知の名前のテーブルに新しい名前を追加することもできます。このオプションは、使用中のコンパイラなどの外部環境の属性に基づいて、mapfile 入力を条件的に有効にする必要がある場合に役立ちます。

$clear 指令は $add 指令の逆です。これは内部テーブルから名前を削除するために使用されます。

        $clear amd64

$add 指令の効果は、$add を使用する mapfile の終わりを超えて持続し、同じリンク操作内でリンカーによって処理される後続の mapfile でも使用できます。この動作を望まない場合は、$add が含まれる mapfile の最後で $clear を使用して定義を削除します。

最後に、$error 指令を使用すると、リンカーは行の残りのすべてのテキストを重大なエラーとして出力し、リンク操作を停止します。$error 指令は、プログラマがオブジェクトを新しい機械タイプに移植する際、必要な mapfile 定義が欠落した正しくないオブジェクトを暗黙のうちに構築できないようにするために使用できます。

        $if _sparc
        ....
        $elif _x86
        ....
        $else
        $error unknown machine type
        $endif

C 言語のプログラマであれば、mapfile の条件付き入力に使用される構文は、C プリプロセッサのマクロ言語の構文と似ていることがわかります。この類似性は意図的なものです。ただし、mapfile の条件付き入力の指令は、設計上、C プリプロセッサによって提供されるものよりも、ずっと機能が劣ります。クロスプラットフォーム環境でのリンク操作をサポートするために必要なもっとも基本的な機能のみが提供されます。

2 つの言語の大きな違いは次のとおりです。

  • C プリプロセッサは完全なマクロ言語を定義し、マクロはソーステキストと、#if および #elif プリプロセッサステートメントによって評価される式の両方に適用されます。リンカーの mapfile にはマクロ機能が実装されていません。

  • C プリプロセッサによって評価される式には、数値の型と豊富な演算子セットが含まれます。mapfile 論理式には、ブール型の true および false 値と、限定された演算子セットが含まれます。

  • C プリプロセッサ式は、マクロとして定義されることがある任意の数値を含み、指定のマクロが定義されたものかどうかを評価するために defined() が使用されます。これによって、true (ゼロ以外) または false (ゼロ) 値が生成されます。mapfile 論理式ではブール値のみを操作でき、名前は defined() 操作を使用せずに直接使用されます。指定された名前はリンカーの既知の名前テーブルにある場合は true と見なされ、そうでない場合は false と見なされます。

高度なマクロ処理が必要な場合、m4 (1) などの外部マクロプロセッサの使用を検討する必要があります。