Previous Contents Next
Chapter 11 Native-code compilation (ocamlopt)

この章では Objective Caml の高パフォーマンスネイティブコンパイラ ocamlopt の解説をします。ocamlopt は Caml のソースファイルをネイティブコードのオブジェクトファイルにコンパイルしたり、そのオブジェクトファイルをリンクして実行可能なファイルを作成したりできます。

ネイティブコードコンパイラは特定のプラットフォームでしか使用できません。ネイティブコードは ocamlc で生成したバイトコードより実行速度が速い代わりに、コンパイルに時間がかかり実行ファイルのサイズが大きくなります。バイトコードコンパイラとの互換性が非常に高く、同一のソースコードを ocamlcocamlopt でコンパイルすると同じように動作するはずです。

ocamlc で生成したネイティブコードオブジェクトファイルと ocamlopt で生成したバイトコードオブジェクトファイルを一緒にすることはできません。プログラムはすべて ocamlopt でコンパイルするか、すべて ocamlc でコンパイルするかのどちらかにしてください。ocamlopt で生成したネイティブコードオブジェクトファイルを、対話式システム ocaml でロードすることはできません。

11.1 Overview of the compiler

ocamlopt コマンドは、ocamlc と非常によく似たコマンドラインインターフェイスになっています。引数にはいくつか型があります。 リンク段階で出力されるファイルは通常の Unix の実行ファイルです。実行に ocamlrun は必要ありません。

11.2 Options

ocamlopt に認識されるコマンドラインオプションは以下の通りです。
-a
コマンドラインに与えられたオブジェクトファイル (.cmx/.o) をとり、ライブラリ (.cmxa/.a) を作成します。実行ファイルは生成されません。ライブラリの名前は -o オプションで指定できます。デフォルトでは library.cmxa です。

コマンドラインに -cclib-ccopt オプションが渡されたら、これらのオプションは出力される .cmxa ライブラリに保存され、このライブラリをリンクするときに自動的に -cclib-ccopt が追加されます (ただしリンク時に -noautolink が指定されない場合) 。

-c
コンパイルのみ行います。リンクを行いません。ソースコードファイルをコンパイル済みファイルに変換しますが、実行ファイルは生成されません。このオプションはモジュールの分割コンパイル時に使用できます。

-cc ccomp
最終的な実行ファイルを生成する C リンカや .c ソースファイルをコンパイルする C コンパイラとして ccomp を使用します。

-cclib -llibname
C リンカにオプションとして -llibname を渡し、指定された C ライブラリをプログラムにリンクします。

-ccopt option
C コンパイラやリンカに与えられたオプションを渡します。例えば、-ccopt -Ldir なら C リンカは C ライブラリを探す際ディレクトリ dir を見るようになります。

-compact
生成するコードを実行時間よりサイズに対して最適化します。プログラムはいくらか小さくなりますが実行速度が遅くなります。デフォルトではスピードに対して最適化します。

-i
実装ファイル (.ml) をコンパイルする際、定義されている名前をすべて型と定義付きで表示します。コンパイラがどのように型推論をしているかチェックするときに使用できます。また出力はインターフェイスの文法に従っているので、インターフェイスファイル (.mli) を書くときの手助けになります。標準出力を .mli ファイルにリダイレクトして、非公開な名前の宣言を消していくだけです。

-I directory
コンパイル済みインターフェイスファイル (.cmi) 、コンパイル済みオブジェクトコードファイル (.cmx) 、ライブラリ (.cmxa) 、-cclib -lxxx で指定される C ライブラリを検索する際検索しに行くディレクトリのリストに与えられたディレクトリを追加します。デフォルトでは、まずカレントディレクトリが、それから標準ライブラリディレクトリが検索されます。-I で追加されたディレクトリは、カレントディレクトリより後に、標準ライブラリディレクトリより前に、コマンドラインに与えられた順に検索されます。

+ で始まるディレクトリ名は、標準ライブラリディレクトリからの相対パスとみなされます。例えば -I +labltk は標準ライブラリのサブディレクトリ labltk を検索パスに追加します。

-inline n
インライン化の度合いを正整数 n に設定します。-inline 0 と指定すると、どの関数もインライン化されません (ただし関数の本体が呼び出し動作より小さい場合を除きます) 。これでインライン化がコードサイズを大きくすることはありません。デフォルトでインライン化の度合いは -inline 1 に設定されています。これだと多少大きな関数でもインライン化するため、コードサイズがいくらか大きくなります。-inline オプションで高い値を設定すると、より大きな関数でもインライン化の候補となるため、コードサイズは相当に大きくなります。

-linkall
ライブラリに含まれるモジュールをすべて強制的にリンクします。このフラグが与えられなかったら、参照されないモジュールはリンクされません。ライブラリを作成するときに (-a flag) これを与えると、そのライブラリを使用するプログラムをリンクする際、ライブラリ内のモジュールはすべて強制的にリンクされます。

-noassert
assertion のチェックをやめます。assertion はコンパイルされません。 すでにコンパイルされたファイルをリンクする場合には、このフラグは何の意味も持ちません。

-noautolink
.cma ファイルをリンクするとき、ライブラリが潜在的に持つ -cclib-ccopt といったオプション (ライブラリを作成するときに指定されたもの) を無視します。ライブラリが間違った C ライブラリや C オプションの指定をしているときに使用できます。この場合、リンクの際コマンドラインで -noautolink を指定して、正しい C ライブラリやオプションを指定し直してください。

-nolabels
型の中でオプションではないラベルを無視します。適用にラベルは使用できません。パラメータの順序が絶対になります。

-o exec-file
リンカが出力するファイルの名前を指定します。デフォルトの出力名は Unix の伝統に則り a.out です。-a が指定されている場合は生成されるライブラリ名の指定になります。-output-obj が指定されている場合は生成されるファイル名の指定になります。

-output-obj
リンカは実行ファイルではなく C オブジェクトファイルを生成します。C のプログラムから呼べるように、Caml のコードを C のライブラリとしてラップするのに使います。18 章のセクション 18.7.5 を見てください。出力されるオブジェクトファイルの名前はデフォルトで camlprog.o です。-o オプションで変更可能です。

-p
実行されたときにプロファイル情報を書き出すコードを追加したプログラムを生成します。このプロファイル情報は解析プログラム gprof で調べることができます (プロファイリングについて詳しくは 17 章を見てください) 。-p オプションはコンパイル時にもリンク時にも与えてください。-p オプションなしでコンパイルされたオブジェクトファイルをリンクすることもできますが、プロファイリングが不正確になってしまいます。

  Unix:
プロファイルについて詳しくは gprof(1) の Unix マニュアルを見てください。

gprof を完全にサポートしているのは一部のプラットフォームだけです (今のところ Intel x86/Linux と Alpha/Digital Unix) 。その他のプラットフォームでは -p オプションを付けてもプロファイルは不正確なものになります (コール・グラフ情報はなく、時間のプロファイルだけです) 。
  Windows:
Windows では -p オプションは動きません。


-pack
コマンドラインで与えられた .cmx オブジェクトファイルをまとめて、オブジェクトファイル (.cmx/.o) とそのコンパイル済みインターフェイス (.cmi) を生成します。元のオブジェクトは出力された .cmx ファイルのサブモジュールとなります。出力される .cmx ファイルの名前は -o オプションで必ず与えてください。
        ocamlopt -pack -o p.cmx a.cmx b.cmx c.cmx
例として、上記のコマンドは p.cmxp.op.cmi を生成します。それらは 3 つのサブモジュール ABC を持ち、それぞれオブジェクトファイル a.cmxb.cmxc.cmx の内容に対応します。他のプログラムからは、P.AP.BP.C などとしてこれらの内容を参照することができます。

  Unix:
-pack オプションは GNU binutils tools nmobjcopy がないプラットフォームでは利用できません。


-pp command
コンパイラは与えられたコマンド command をプリプロセッサとしてすべてのソースファイルに適用します。command の出力は一時ファイルにリダイレクトされてからコンパイルされます。コンパイルでエラーが発生しなかったら一時ファイルは削除されます。ソースファイルのベース名と拡張子 .ppi (インターフェイス .mli の場合) もしくは .ppo (実装 .ml の場合) から構成される名前が一時ファイルの名前になります。

-principal
型チェックの際 information path をチェックします。すべての型が principal way で導出されているか確認します。-principal モードでコンパイルの通るプログラムは必ずデフォルトモード (equivalent type) でもコンパイルが通ります (ただしバイナリの signature は異なります) 。

-rectypes
型チェックの際、任意の再帰的な型を許します。デフォルトでは、オブジェクト型を経由する再帰による再帰的な型しかサポートされません。

-S
コンパイルの際生成されるアセンブリコードを保存します。ソースファイル x.ml のアセンブリコードは x.s というファイルに保存されます。

-thread
24 章で解説される threads ライブラリと組み合わせてマルチスレッドプログラムをコンパイル、リンクします。このオプションを付けると、特別なスレッドセーフな標準ライブラリを選択するようになります。

-unsafe
配列や文字列アクセスのバウンダリチェックをオフにします (v.(i)s.[i]) 。-unsafe でコンパイルされたプログラムはいくらか速くなりますが安全ではありません。プログラムが配列や文字列のバウンド外をアクセスした場合何が起こるかわかりません。

-v
コンパイラのバージョンと標準ライブラリディレクトリを表示して終了します。

-verbose
外部コマンドを実行する前に、そのコマンドを表示します。特にC コンパイラやリンカの起動を表示します。

-version
コンパイラのバージョンを短い表記 (3.06 みたいに) 表示して終了します。

-w warning-list
警告を有効/無効にします。引数 warning-list は文字列で、各文字は以下の意味を持ちます。
A/a
すべての警告を有効/無効にする
C/c
コメントかどうか疑わしいものに対する警告を有効/無効にする
D/d
推奨されていない (deprecated) 機能に対する警告を有効/無効にする
F/f
関数の部分適用に対する警告を有効/無効にする (つまり f x; expr のようなコードで、適用 f x が関数型を持つようなとき).
L/l
適用でラベルが省略されていることに対する警告を有効/無効にする
M/m
メソッドのオーバーライドに対する警告を有効/無効にする
P/p
部分マッチ (パターンマッチでどれにもマッチしない場合があるもの) に対する警告を有効/無効にする
S/s
文が unit 型以外を持つことに対する警告を有効/無効にする (例えば expr1; expr2 のようなコードで、expr1unit 以外の型を持つようなとき)
U/u
使用されない (冗長な) マッチケースに対するに対する警告を有効/無効にする
V/v
隠れたインスタンス変数に対する警告を有効/無効にする
X/x
その他の警告すべてを有効/無効にする
デフォルトでは -w Al になります (ラベル以外はすべて有効) 。

-warn-error warning-list
引数 warning-list で示される警告をエラーとして扱います。コンパイラはそのような警告が発生したらすぐにエラーとして停止して処理をやめます。warning-list の意味は -w オプションと同じで、大文字だと該当する警告をエラーとし、小文字だとエラーとしません。デフォルトでは -warn-error a になります (どの警告もエラーとしては扱わない) 。

-where
標準ライブラリの位置を表示して終了します。
11.3 Common errors

エラーメッセージはほとんど ocamlc と同じです。セクション 8.4 を見てください。

11.4 Compatibility with the bytecode compiler

このセクションではバイトコードコンパイラとネイティブコードコンパイラの非互換性を解説します。以下に述べる点を除いては、これらのコンパイラが生成するコードは同じように動作するはずです。 これらの非互換性を避けるためには、例外 Division_by_zeroStack_overflow のトラップは決してしないことです。ネイティブコードコンパイラと同じように、バイトコードコンパイラでもこれらは致命的エラーとして扱うのです。大抵の場合除算などは、例外が発生したあとそれをトラップするのではなく、処理を行う前にチェックすることが可能です。


Previous Contents Next