4.12. 特定の段階に関するオプション

4.12.1. それぞれの段階で使われるプログラムを変更する

コンパイルシステムの段階のうち一つ一つについて、ghcに備え付けられたプログラムの代わりに別のものを使うように指定することができる。例えば、別のアセンブラを使ってみたいかもしれない。以下のオプションで、指定されたコンパイル段階で使われる外部プログラムを変更することができる。

-pgmL cmd

文芸形式の前処理器としてcmdを使う。

-pgmP cmd

Cプリプロセッサとしてcmdを使う(-cppが指定されているときのみ)

-pgmc cmd

Cコンパイラとしてcmdを使う。

-pgmlo cmd

LLVM最適化器としてcmdを使う。

-pgmlc cmd

LLVMコンパイラとしてcmdを使う。

-pgms cmd

splitterとしてcmdを使う。

-pgma cmd

アセンブラとしてcmdを使う。

-pgml cmd

リンカとしてcmdを使う。

-pgmdll cmd

DLL生成器としてcmdを使う。

-pgmF cmd

前処理器としてcmdを使う。(-Fが指定されているときのみ)

-pgmwindres cmd

Windowsにおいて、マニフェストを埋め込むためのプログラムとしてcmdを使う。通常、これは、GHCのインストールで供給されるwindresプログラムである。4.12.6. リンクに影響するオプション-fno-embed-manifest参照。

4.12.2. 特定の段階にオプションを強制する

以下のフラグを使って、特定のコンパイル段階に指定されたオプションを強制的に使わせることができる。

-optL option

optionを文芸形式の前処理器に渡す。

-optP option

optionをCPPに渡す。(-cppが有効なときのみ効果がある)

-optF option

optionを用意した前処理器に渡す。(4.12.4. Haskell前処理器に影響するオプションを見よ)

-optc option

optionをCコンパイラに渡す。

-optlo option

optionをLLVM最適化器に渡す。

-optlc option

optionをLLVMコンパイラに渡す。

-optm option

optionをmanglerに渡す。

-opta option

optionをアセンブラに渡す。

-optl option

optionをリンカに渡す。

-optdll option

optionをDLL生成器に渡す。

-optwindres option

Windowsにおいて、マニフェストを埋め込む際、optionwindresに渡す。4.12.6. リンクに影響するオプション-fno-embed-manifestを見よ。

つまり、例えば、-Ewurbleオプションをアセンブラに渡すには、-opta-Ewurbleとすれば良い。(Eの前のハイフンは必須である)

GHCはそれ自身Haskellプログラムなので、GHCのランタイムシステムに直接オプションを渡す必要があるなら、それらを+RTS ... -RTSで囲むことができる。(4.17. コンパイル済みプログラムを実行するを見よ)

4.12.3. Cプリプロセッサに影響するオプション

-cpp

HaskellコードがCプリプロセッサcppに通されるのは、-cppオプションが与えられたときのみである。大量の条件コンパイルのある大きなシステムを構築しているのでない限り、これが必要になることはないはずである。

-Dsymbol[=value]

通常の方法でマクロsymbolを定義する。注意: これはCを介してコンパイルするときにCコンパイラに渡される-Dマクロには影響しない。それには、-optc-Dfooというハックを使うこと。(4.12.2. 特定の段階にオプションを強制するを見よ)

-Usymbol

通常の方法でマクロsymbolを未定義にする。

-Idir

#includeファイルを探すディレクトリを、通常のCでの方法で指定する。

Haskellソースコード(.hsまたは.lhsファイル)をプリプロセスするとき、GHCドライバはいくつかのマクロを事前定義する。

定義されるシンボルは以下に示されている。あなたのシステムにインストールされたGHCでどのシンボルが定義されているかを確かめるには、以下の小技が有用である。

$ ghc -E -optP-dM -cpp foo.hs
$ cat foo.hspp

(foo.hsというファイルが必要だが、実際に使われることはない)

__GLASGOW_HASKELL__

GHCのバージョンx.y.zでは、__GLASGOW_HASKELL__の値は定数xyyである。(yが一桁なら、前に0が追加される。例えばGHCのバージョン6.2では__GLASGOW_HASKELL__==602である)。詳しくは1.4. GHCのバージョン番号付け規則を参照。

運が良ければ、__GLASGOW_HASKELL__は、C風プリプロセスをサポートする他の処理系では定義されていないだろう。

(参考までに、他のシステムで比較に使える名前は、Hugsは__HUGS__、nhc98は__NHC__、hbcは__HBC__である。)

注意。このマクロはHaskellソースとCソースの両方のプリプロセス時に有効である。これには、Haskellモジュールから生成されたCソースも含む。(つまり、.hs.lhs.c.hcの各ファイルである)

__PARALLEL_HASKELL__

-parallelが使われているときのみ定義される。このシンボルはHaskell(入力)とC(GHCの出力)をプリプロセスするときに定義される。

os_HOST_OS=1

この定義を使ってOSに基づく条件コンパイルをすることができる。ただし、osは使われているOSの名前である。(例えばlinux、Windowsではmingw32solarisなど)

arch_HOST_ARCH=1

この定義を使ってホストのアーキテクチャに基づく条件コンパイルをすることができる。ただし、archは使われているアーキテクチャの名前である。(例えばi386x86_64powerpcsparcなど)

4.12.3.1. CPPと文字列間隙

警告を少々。-cppは「文字列間隙」との相性があまりよくない。言い替えると、次のような文字列間隙は-cppの使用下ではうまく動かない。

strmod = "\
\ p \
\ "

/usr/bin/cppがバックスラッシュと改行を消し去るからである。

一方、行末にスペースを加えれば、cpp(少なくともGNU cpp、他のcppもそうかもしれない)はバックスラッシュと空白の対をそのまま残し、文字列間隙は期待どおりに働く。

4.12.4. Haskell前処理器に影響するオプション

-F

Haskellソースファイルは、-Fオプションが与えられたときのみ選んだ前処理器に通される。

選んだ前処理器をコンパイル時に走らせるのは、場合によっては適切で、便利である。-Fオプションを使うと、前処理器はGHCの総合的なコンパイルパイプラインの一部として走る。このため、Haskell前処理器を別に走らせるのと比べると、解釈実行モードでもうまく動いたり、GHCの再コンパイル検査器の恩恵に浴することができるという点で有利である。

前処理器が走るのはHaskellコンパイラがHaskell入力を処理する直前、ただし文芸的マーク付けが落とされ、(場合によっては)Cプリプロセッサが入力を洗浄した後である。

-pgmF cmdを使って、前処理器として使うプログラムを選ぶことができる。起動されるとき、cmd前処理器はコマンド行から最低三つの引数を渡される。最初の引数は元のソースファイルの名前であり、二番目は入力の置かれているファイルの名前であり、三番目はcmdが出力を書き込むべきファイルの名前である。

前処理器への追加の引数は-optFオプションで渡すことができる。これらは、コマンド行において、三つの標準的な入出力引数の後に置かれる。

前処理器の例として、ソースファイルを、GHCが期待するエンコーディングに変換するというのがあげられる。つまり、以下のようなスクリプトconvert.shを作るのだ。

#!/bin/sh
( echo "{-# LINE 1 \"$2\" #-}" ; iconv -f l1 -t utf-8 $2 ) > $3

そして、GHCに-F -pgmF convert.shを渡す。-f l1オプションはあなたのLatin-1ファイル(引数$2に与えられる)を変換するように指示し、「-t uft-8」オプションはUTF-8でエンコードされたファイルを返すように指示している。結果は引数$3にリダイレクトされる。echo "{-# LINE 1 \"$2\" #-}"は、エラーがあったとき、その位置を元のソースファイルの物として報告させるようにするためのものである。

4.12.5. コード生成に影響するオプション

-fasm

LLVMを介するのではなく、GHCのネイティブコード生成器を使ってコンパイルする。-fasmはデフォルトである。

-fllvm

ネイティブコード生成器を使わず、LLVMを介してコンパイルする。これは一般的に、ネイティブコード生成器に比べてやや長いコンパイル時間が掛かる。生成されたコードは一般的に、他の二つのコード生成器と同等か、それより速い。LLVMを介したコンパイルには、LLVMがパスにあることが必要である。

-fno-code

コード生成(と、それ以降の段階全て)を完全に省略する。コンパイルの中間段階の出力を見たいだけのときには使い道があるかもしれない。

-fobject-code

オブジェクトコードを生成する。GHCi以外ではこれがデフォルトであり、GHCiでは、バイトコードよりもオブジェクトコードを優先して生成するようにすることができる。

-fbyte-code

オブジェクトコードの代わりにバイトコードを生成する。GHCiではこれがデフォルトである。現在、バイトコードは対話的インタプリタでのみ使え、ディスクに保存することができない。このオブションが役に立つのは、-fobject-codeの効果を反転させるときだけである。

-fPIC

位置独立なコード(共有ライブラリや共有バイナリに置けるコード)を生成する。これは現在、Linux x86とx86-64において動作する。Windowsでは位置独立コードは決して使われないので、このプラットフォームではこのフラグは何もしない。

-dynamic

コード生成に際して、別パッケージからインポートされた実体は別の共有ライブラリやバイナリにあると仮定する。

このオプションをリンク時に使うと、GHCは共有ライブラリをリンクするのに注意。

4.12.6. リンクに影響するオプション

GHCはあなたのコードをいろいろなライブラリとリンクしなければならない。これには、ユーザ供給のもの、GHC供給のもの、システム供給のもの(例えば-lm数学ライブラリ)が含まれ得る。

-llib

libライブラリをリンクする。Unixシステムでは、これはライブラリディレクトリパスのどこかにあるliblib.aまたはliblib.soというファイルに置かれる。

大部分のUNIXリンカは悲しい状態にあって、こういうオプションの順序に意味がある。ライブラリfooがライブラリbarを必要とするなら、一般に、コマンド行中で、-lfoo-lbarよりも前に来なければならない。

外部ライブラリを使うときに心に留めた方がいい罠がもう一つある。もしライブラリにmain()関数があるなら、これはGHCのmain()関数よりも優先して使われるということである。(例えば、libf2cliblには独自のmain()がある)。これは、GHCのmain()HSrtsライブラリ由来であり、通常コマンド行中で他の全てのライブラリよりも後に置かれるからである。GHCのmainが他の外部ライブラリ由来のmain()よりも優先して使われるようにするには、単に-lHSrtsオプションをコマンド行で他のライブラリよりも前に置けば良い。

-c

リンクを省略する。––makeと併用して、プログラムにMainモジュールがあったときに行われる自動リンクを避けることができる。

-package name

Haskell「パッケージ」(4.9. パッケージ を見よ)を使っているなら、関係する-packageをリンク時にも忘れずに指定する必要がある。こうすることで、必要なライブラリがプログラムにリンクされる。-packageを忘れると何ページにもわたるリンクエラーが起こるだろう。

-framework name

Darwin/MacOS Xのみ。フレームワークnameをリンクする。このオプションはAppleのリンカの-frameworkオプションに相当する。フレームワークとパッケージは別々のものだということに注意してほしい。フレームワークはHaskellのコードを含まない。むしろ、これは共有ライブラリをパッケージ化するApple流のやりかたである。例えば、Appleの「Carbon」APIにリンクするには、-framework Carbonを使うことができる。

-Ldir

ユーザ供給のライブラリを探す場所。ディレクトリdirをライブラリディレクトリパスの先頭に加える。

-framework-pathdir

Darwin/MacOS Xのみ。ディレクトリdirをフレームワークディレクトリパスの先頭に加える。これはAppleのリンカの-Fオプションに相当する。(GHCでは-Fは別の要素に使用済みである)

-split-objs

通常生成されるような単一のオブジェクトファイルを分割して、モジュール中のHaskell関数や型一つずつにオブジェクトファイルを生成するようにリンカに指示する。これはライブラリに対してのみ意味を持つ。この場合、そのライブラリにリンクされる実行ファイルは、必要なオブジェクトファイルとのみリンクされるので、よりファイルサイズが小さくなる。しかし、全てのセクションを別々に組み立てるのは高価なので、これはふつうにコンパイルするよりも遅い。我々はこの機能をGHCのライブラリをビルドするのに使っている。(警告: 自分が何をしているか分かっているのでない限り、このオプションを使わないように!)

-static

可能なら共有Haskellライブラリを避けるようにリンカに指示する。これはデフォルトである。

-dynamic

このオプションは、Haskellの共有ライブラリをリンクするようにGHCに指示する。このフラグは依存するライブラリの選択に影響するだけであり、現在作っているものの形式には影響しない(-sharedを見よ)。作り方に関しては4.13. 共有ライブラリを使うを見よ。

このオプションはコード生成にも影響を与えることに注意。(上記参照)

-shared

このフラグが与えられると、実行可能形式を作る代わりにGHCは共有オブジェクトを生み出す。対象のOSによって、これはELF DSOだったり、Windows DLLだったり、Mac OSのdylibだったりする。GHCはこの統一フラグのもとにOSの詳細を隠す。

生成される共有オブジェクトが-packageオプションで与えられたHaskellのパッケージライブラリに静的にリンクされるか動的にリンクされるかは、-dynamic/-staticフラグによって制御される。Haskell以外のライブラリはそのシステムでgccが通常にリンクするのと同じようにリンクされる。例えば、大部分のELFシステムでは、動的ライブラリが見つかった場合はそれが使われる。

共有オブジェクトへとリンクされるオブジェクトファイルは-fPICでコンパイルされなければならない。4.12.5. コード生成に影響するオプションを見よ。

Haskellパッケージのために共有オブジェクトを作る場合、そのパッケージにリンクされるときにGHCがその共有オブジェクトを認識できるように、その共有オブジェクトには正しい名前が付けられねばならない。共有オブジェクトの名前manglingを見よ。

-dynload

このフラグは、実行時に共有ライブラリを探すときのいくつかの方式から一つを選ぶものである。それぞれの方式については4.13.4. 実行時における共有ライブラリの発見を見よ。

-main-is thing

Haskellの通常の規則では、プログラムはMainmain関数を供給する必要がある。テスト時には、どの関数が「主要な(main)」ものであるかを変えられると便利であり、これを可能にするのが-main-isフラグである。thingは次のうちいずれかである。

  • 小文字で始まる識別子foo。GHCはMain.fooがmain関数だとみなす。

  • モジュール名A。GHCはA.mainがmain関数だとみなす。

  • 修飾名A.foo。GHCはA.fooがmain関数だとみなす。

厳密に言うと、-main-isはそもそもリンク時フラグではない。リンク段階ではなんの効果も及ぼさない。このフラグは、指定されたmain関数のあるモジュール(例えば上記のうち後ろ二つではAである)をコンパイルするときに指定する必要がある。他のモジュールには影響がないので、ghc --makeに与えても安全である。ただし、main関数の指定を変更したとき、どのモジュールにもそれ以外に変更がないなら、新旧両方の「main」のモジュールを強制的に再コンパイルさせないといけない。ghcはこれらが両方とも再コンパイルを要していると判断できるほど賢くないのである。再コンパイルを強制するには、オブジェクトファイルを削除しても良いし、-fforce-recompフラグを使っても良い。

-no-hs-main

ghcでコンパイルされたコードを別の(非Haskellの)プログラムの一部として使いたいときは、RTSはmain()の定義をリンク時に供給せず、あなたが供給せねばならない。このことをリンク時にコンパイラに伝えるのが-no-hs-mainである。8.2.1.1. 自分で用意したmain()を使うも見よ。

リンカにわたされるコマンド行はかなり複雑なので、複数言語のアプリケーションの最終リンクにはghcを使うのが良いだろう。ただしこれは必須ではない。ドライバがどんなオプションをリンカに渡しているかを見るには一度-v付きでリンクしてみるだけで良い。

-no-hs-mainフラグは、--makeモードにおいて、HaskellのMainモジュールがないときでもコンパイラにリンクを行わせるために使うこともできる。(通常、Mainがないときはコンパイラはリンクを試みない)

-rtsoptsおよび-with-rtsoptsフラグは、GHCが生成するmainの定義を変更することで実装されているので、-no-hs-mainと共に使われると効果がない。自分のmainを使っている場合に-rtsopts-with-rtsoptsの効果を得る方法については8.2.1.1. 自分で用意したmain()を使うを見よ。

-debug

プログラムをデバッグ版のランタイムシステムにリンクする。デバッグランタイムは大量のアサーションと正気度チェックを有効にし、実行時にデバッグ出力を生成するためのオプションを提供する。(一覧を見るにはプログラムを+RTS -?付きで実行せよ)

-threaded

プログラムを「スレッド化された」版のランタイムシステムにリンクする。スレッド化ランタイムシステムは複数のOSスレッドを管理するのでこう呼ばれる。これに対して、デフォルトのランタイムシステムは純粋に単一スレッドである。

並行性を使うのに-threadedは必要ない。単一スレッドのランタイムはHaskellスレッド間の並行性をちゃんと扱う。

スレッド化ランタイムシステムには次のような利点がある。

  • RTSオプション-Nを使うことを可能にする。これはプログラムをマルチプロセッサあるいはマルチコアの機械上でスレッドを並列に動作させられるようにする。4.15. SMP並列計算を使うを見よ。

  • あるスレッドが他言語呼び出しを行なったとき、(その呼び出しがunsafeと標示されていなければ)その呼び出しの実行中にプログラム中の他のHaskellスレッドが走り続ける。さらに、foreign exportされたHaskell関数が複数のOSスレッドから同時に呼ばれても良い。8.2.4. マルチスレッドとFFIを見よ。

-eventlog

プログラムを"eventlog"版のランタイムシステムにリンクする。この方法でリンクされたプログラムは、実行時にイベント(スレッドの開始/停止など)の追跡情報をprogram.eventlogというバイナリファイルに生成することができる。このファイルは後でいろいろなツールによって解釈できる。さらなる情報は4.17.6. 追跡情報を得るを見よ。

-eventlog-threadedと併用することができる。また-debugによって自動的に有効になる。

-rtsopts

このオプションは、コマンド行やGHCRTSで与えられるRTS制御オプションの処理に影響する。可能なのは以下の三つ。

-rtsopts=none

すべてのRTSオプションの処理を無効にする。+RTSがコマンド行内のいずれかの位置に現れた場合、プログラムはエラーメッセージを出力して異常終了する。GHCRTS環境変数が設定されている場合、プログラムは警告メッセージを出力し、GHCRTSを無視し、通常通りに実行される。

-rtsopts=some

[これがデフォルトの設定である]「安全」なRTSオプション(現在-?--infoのみ)だけを有効にする。これら以外のRTSオプションがコマンド行やGHCRTSで使われていた場合、プログラムはエラーメッセージを出力して異常終了する。

-rtsopts=all, or just -rtsopts

コマンド行とGHCRTSの両方で、全てのRTSオプションの処理を有効にする。

GHC 6.12.3以前では、全てのRTSオプションを処理するのがデフォルトだった。しかし、RTSオプションは任意のファイルに対するログデータの書き込みを、実行プログラムのコンテキストで許すので、セキュリティ上の問題が発生する余地がある。このため、GHC 7.0.1以降のデフォルトは-rtsopts=someである。

-rtsoptsは、-no-hs-mainを使っているときには効果がないことに注意。詳細は8.2.1.1. 自分で用意したmain()を使うを見よ。

-with-rtsopts

このオプションは、RTSオプションのデフォルトをリンク時に設定できるようにする。例えば、-with-rtsopts="-H128m"はヒープのデフォルトの大きさを128MBにする。このプログラムのデフォルトのヒープサイズは、ユーザによって上書きされない限り、常にこれになる。(-rtsoptsオプションの設定によっては、ユーザが実行時にRTSオプションを設定することができないかもしれない。その場合には-with-rtsoptsがそれを設定する唯一の方法である。)

-with-rtsoptsは、-no-hs-mainを使っているときには効果がないことに注意。詳細は8.2.1.1. 自分で用意したmain()を使うを見よ。

-fno-gen-manifest

Windowsでは、バイナリをリンクする際、GHCは通常マニフェストファイルを生成する。マニフェストはprog.exe.manifestというファイルに置かれる。ここで、prog.exeが実行ファイルの名前である。現在、このマニフェストファイルの役割は唯一つである。Windows Vistaにおける「インストーラの検知」を無効にするのだ。(これは、ある種の名前(例えば、「install」「setup」「patch」を含む名前)の実行ファイルの権限を昇格させようとするものだ)。マニフェストファイルを使ってインストーラ検知を無効にしないと、Windowsがインストーラだと見なした実行ファイルを実行しようと試みた場合、起動者にパーミッションエラーのコードが返されることになる。この結果、起動者によって、ユーザに昇格の許可を求めるダイアログボックスを表示したり、単に権限不足のエラーになるかもしれない。

インストーラ検知は、セキュリティコントロールパネルを使って大域的に無効にすることもできるが、GHCはデフォルトで、ユーザがインストーラ検知を無効にしてあることに依存しないバイナリを生成する。

-fno-gen-manifestはこのマニフェストファイルの生成を無効にする。こうすることの一つの理由としては、例えば自分でマニフェストファイルを用意した場合というのがあるだろう。

将来的には、GHCはマニフェストファイルをもっと多くのことに使うようになるかもしれない。依存しているDLLの位置を指定するなど。

-fno-gen-manifest-fno-embed-manifestも有効にする。下記参照。

-fno-embed-manifest

WindowsにおいてGHCがバイナリのリンク時に生成するマニフェストファイルは、デフォルトで、実行ファイル自体に埋め込まれる。これによって、バイナリを、マニフェストファイルを同時に供給する必要なしで配布することができる。この埋め込みは、windresを走らせることによって為される。マニフェストを埋め込むためにGHCが何をしているが正確に知るには、-vフラグを使うとよい。このために、GHCのインストールにはwindresのコピーが付属している。

-pgmwindres(4.12.1. それぞれの段階で使われるプログラムを変更する)と-optwindres(4.12.2. 特定の段階にオプションを強制する)も参照。

-dylib-install-name path

Darwin/MacOS Xでは、動的ライブラリにはビルド時に「install name」が付加される。これは、そのライブラリの最終的なインストールパスである。後にこのライブラリをリンクするライブラリや実行ファイルは、このライブラリを実行時に探索する場所としてこのパスを選ぶ。デフォルトでは、ghcはライブラリがビルドされた場所をinstall nameとして設定する。このオプションは、指定したパスでそれを上書きすることを可能にする。(Appleのリンカに-install_nameを渡すものである)。他のプラットフォームでは無視される。