4.5. 実行モード

GHCの振る舞いはまずモード指定フラグによって制御される。これらのフラグのうちただ一つだけを使うことができるが、コマンド行において最初のオプションである必要はない。

モードフラグがない場合、コマンド行にソースファイルがあるならGHCはmakeモード(4.5.1. ghc --makeを使う)に入り、そうでないならコマンド行中で指定されたオブジェクトをリンクして実行ファイルを作る。

以下のモードフラグが利用できる。

ghc --interactive

対話的モード。ghciとしても使える。対話的モードは第2章. GHCiを使うで詳しく説明されている。

ghc --make

このモードでは、GHCは複数のモジュールから成るHaskellのプログラムを、依存性を解析しながら自動的にビルドする。単純なHaskellプログラムなら、これはmakeを使うのに比べてずっと簡単で、しかも速い。makeモードは4.5.1. ghc --makeを使うで説明されている。

コマンド行中に一つでもHaskellソースファイルがあるなら、このモードがデフォルトであり、この場合--makeオプションは省略できる。

ghc -e expr

式を評価するモード。これは対話的モードによく似ているが、評価する式は一つだけで、コマンド行から与えられる。さらなる詳細は4.5.2. 式評価モードを見よ。

ghc -E
ghc -C
ghc -S
ghc -c

これは伝統的な一括処理コンパイラモードである。このモードでは、GHCは一度に一つのソースファイルをコンパイルするか、オブジェクトファイルをリンクして実行可能ファイルを作る。コマンド行でモードが指定されなかった場合も、このモードが使われる。このときは、指定されたファイルをコンパイルして、さらにリンクしてプログラムを作る、という動作になる。4.5.3. 一括処理コンパイラモードを見よ。

ghc -M

依存性生成モード。このモードでは、GHCはMakefileで使うのに適した依存性情報を生成する。4.7.11. 依存関係を生成するを見よ。

ghc --mk-dll

DLL作成モード。(Windowsのみ)13.6.1. DLLを作成するを見よ。

ghc --help
ghc -?

使いかたに関する長いメッセージを標準出力に吐いて、終了する。

ghc --show-iface file

file中のインタフェースを読んで、それをテキストとしてstdoutにダンプする。例えば、ghc --show-iface M.hiのようにする。

ghc --supported-extensions
ghc --supported-languages

対応している言語拡張を表示する。

ghc --show-options

対応しているコマンド行オプションを印字する。シェルでの自動補完のために使うことができる。

ghc --info

コンパイラに関する情報を表示する。

ghc --version
ghc -V

GHCのバージョン番号を含む一行の文字列を印字する。

ghc --numeric-version

GHCの数値的なバージョン番号のみを印字する。

ghc --print-libdir

GHCのライブラリディレクトリのパスを表示する。これはGHCのライブラリファイル、インタフェースファイル、およびインクルードファイルが置かれているディレクトリツリーの最上位である。(Unixではふつう/usr/local/lib/ghc-5.04のようなところである)これはパッケージ設定ファイルにおけるlibdirの値である。(4.9. パッケージ を見よ)

4.5.1. ghc --makeを使う

このモードではGHCは複数のモジュールから成るプログラムをビルドする。このとき、GHCは根となる一つ以上のモジュール(ふつうはMainだけ)から出発して依存性を追跡する。例えば、MainモジュールがMain.hsというファイルに置かれているとすると、次のようにしてこのプログラムをコンパイル・リンクすることができる。

ghc --make Main.hs

実際には、コマンド行中にHaskellソースファイルが一つでもあり、他のモードが指定されてもいないなら、GHCは自動的にmakeモードに入るので、この例では次のように入力するだけでも良い。

ghc Main.hs

ソースファイル名やモジュール名はいくつ指定しても良い。それらを初期モジュールとしてインポートを追いかけることで、GHCはプログラムの全てのモジュールを見つけ出す。次に、古くなったモジュールの再コンパイルが試みられ、最後に、もしMainモジュールがあるなら、プログラムはリンクされて実行可能形式になる。

伝統的なMakefileに比べて、ghc --makeを使うことの利点は、以下のようなことである。

  • コンパイルのためにGHCを再起動する必要がないので、コンパイル間で情報をキャッシュすることができる。複数のモジュールから成るプログラムをghc --makeでコンパイルすると、個々のソースファイルに対してghcを走らせたときに比べて二倍も速いことがある。

  • Makefileを書く必要がない。

  • 起動されるたびにGHCが依存関係を再計算するので、ソースとの整合性が失われることがない。

  • -jフラグを使うと、モジュールを並列にコンパイルできる。N個のジョブを並列コンパイルするには-jNと指定すれば良い。

この章でこれ以降に解説されるコマンド行オプションは全て--makeとともに用いることができる。ただし、コマンド行から与えられたオプションは全てのソースファイルに適用されるので、単一のソースファイルにのみ適用したいオプションについてはOPTIONS_GHCプラグマ(4.2.2. ソースファイル中のコマンド行オプションを見よ)を使う必要があることに注意せよ。

プログラムを追加のオブジェクト(例えばCの補助コード)にリンクする必要があるなら、そのオブジェクトファイルをコマンド行で与えれば、GHCは実行ファイルをリンクするときにそれを含める。

GHCはソースファイルがあるときしか依存関係を追跡できないので、ソースコードのないモジュールがプログラムに含まれていると、たとえオブジェクトファイルとインタフェースファイルがあったとしても、GHCは文句を言うことに注意せよ。パッケージのモジュールはこの規則の例外で、ソースファイルがあってもなくても良い。

プログラムのソースファイルが全て同じディレクトリにある必要はない。-iオプションを使ってディレクトリを探索パスに加えることができる。(4.7.3. 探索パスを見よ)

4.5.2. 式評価モード

式を評価するモード。これは対話的モードによく似ているが、評価する式は一つだけで、コマンド行から-eオプションの引数として与えられる。

ghc -e expr

コマンド行からHaskellソースファイルを指定することもでき、それらは対話的モードと全く同じようにロードされる。指定された式はロードされたモジュールの文脈で評価される。

例えば、Mainというモジュールを含むHaskellプログラムをロードして走らせるには、次のようにすれば良い。

ghc -e Main.main Main.hs

また、このモードを、単に式をPreludeの文脈で評価するのに使うこともできる。

$ ghc -e "interact (unlines.map reverse.lines)"
hello
olleh

4.5.3. 一括処理コンパイラモード

一括処理モードでは、GHCはコマンド行で与えられた一つ以上のソースファイルをコンパイルする。

コンパイルが、複数ある段階のどこから始まるかは、それぞれの入力ファイルの接尾辞によって決定される。また、どこで終わるかは、フラグによって決定される。もしこれに関連するフラグが与えられなかったときは、リンクまでの全ての段階を実行する。次の表はこれをまとめたものである。

コンパイルシステムの段階 ここから開始する接尾辞 ここまでで終了することを指示するフラグ 出力ファイル(の接尾辞)
文芸形式プリプロセッサ .lhs - .hs
Cプリプロセッサ(省略可能) .hs (-cppが与えられたとき) -E .hspp
Haskellコンパイラ .hs -C, -S .hc, .s
Cコンパイラ(省略可能) .hc or .c -S .s
アセンブラ .s -c .o
リンカ other - a.out

そういうわけで、次のようなものがよくある起動のされかたである。

ghc -c Foo.hs

これはHaskellソースファイルFoo.hsをコンパイルしてオブジェクトファイルFoo.oを生成する。

注意: Haskellコンパイラが実際に出力するのが何かはバックエンドのコード生成器が何かによる。詳しくは、4.11. GHCのバックエンドを見よ。

注意: Cプリプロセスは省略可能であり、-cppフラグによって有効になる。詳しくは4.12.3. Cプリプロセッサに影響するオプションを見よ。

注意: -Eオプションはコンパイラをプリプロセス段階まで走らせ、結果をファイルに出力する。

4.5.3.1. ファイルに対するデフォルトの振る舞いを上書きする

上記のように、GHCがファイルを処理する方法はその接尾辞による。これは-xオプションを使って変更できる。

-x suffix

コマンド行においてこれに続く全てのファイルをsuffixという接尾辞を持つかのように扱う。例えば、M.my-hsというファイルにあるHaskellモジュールをコンパイルするには、ghc -c -x hs M.my-hsとすれば良い。