| C++ ユーザーズガイド |
第 2 章
C++ コンパイラの使用方法
コンパイラの主な目的は、C++ などの高水準言語で書かれたプログラムをコンピュータハードウェアで実行できるデータファイルに変換することです。C++ コンパイラでは次のことができます。
- ソースファイルを再配置可能なバイナリ (
.o) ファイルに変換する。
これらのファイルはその後、実行可能ファイル、(-xarオプションで) 静的 (アーカイブ) ライブラリ (.a) ファイル、動的 (共有) ライブラリ (.so) ファイルなどにリンクされます。- オブジェクトファイルとライブラリファイルのどちらか (または両方) をリンク (または再リンク) して実行可能ファイルを作成する。
- 実行時デバッグを (
-gオプションで) 有効にして、実行可能ファイルをコンパイル
する。- 文レベルや手続きレベルの実行時プロファイルを (
-pgオプションで) 有効にして、実行可能ファイルをコンパイルする。コンパイル方法の概要
この節では、C++ コンパイラを使って C++ プログラムのコンパイルと実行をどのように行うかを簡単に説明します。コマンド行オプションの詳しい説明については、第 3 章を参照してください。
注 - この章のコマンド行の例は、CCの使用方法を示すためのものです。実際に出力される内容はこれと多少異なる場合があります。
C++ アプリケーションを構築して実行するには、基本的に次の手順が必要です。
- エディタで C++ソースファイルを作成する。このソースファイルには、表 2-1 に列挙されている接尾辞のいずれかを使用します。
- コンパイラを起動して実行可能ファイルを作成する
- 実行可能ファイルの名前を入力してプログラムを実行する
この例では、ソースファイル
greetings.ccをCCでコンパイルしています。デフォルトでは、実行可能ファイルがファイルa.outとして作成されます。プログラムを起動するには、コマンドプロンプトで実行可能ファイル名a.outを入力します。従来、UNIX コンパイラは実行可能ファイルに
a.outという名前を付けていました。しかし、すべてのコンパイルで同じファイルを使用するのは不都合な場合があります。そのファイルがすでにあれば、コンパイラを実行したときに上書きされてしまうからです。次の例のように、コンパイラオプションに-oを使用すれば、実行可能出力ファイルの名前を指定できます。
example%CC -o greetings greetings.Cこの例では、
-oオプションを指定することによって、実行可能なコードがファイルgreetingsに書き込まれます (プログラムにソースファイルが 1 つだけしかない場合は、ソースファイル名から接尾辞を除いたものを出力ファイル名にすることが一般的です)。あるいは、コンパイルの後に
mvコマンドを使って、デフォルトのa.outファイルを別の名前に変更することもできます。いずれの場合も、プログラムを実行するには、実行可能ファイルの名前を入力します。
example%greetingsReal programmers write C++!example%コンパイラの起動
この後の節では、
CCコマンドで使用する規約、コンパイラのソース行指令など、コンパイラの使用に関連する内容について説明します。コマンド構文
CC[options] [source-files] [object-files] [libraries]options は、先頭にダッシュ (
-) またはプラス記号 (+) の付いたキーワード (オプション) です。このオプションには、引数をとるものがあります。source-files にはソースファイル、object-files にはオブジェクトファイル、libraries にはライブラリを指定します。通常、コンパイラオプションの処理は、左から右へと行われ、マクロオプション (他のオプションを含むオプション) は、条件に応じて内容が変更されます。ほとんどの場合、同じオプションを 2 回以上指定すると、最後に指定したものだけが有効になり、オプションの累積は行われません。次の点に注意してください。
ソースファイル、オブジェクトファイル、およびライブラリは、コマンド行に指定した順にコンパイルとリンクが行われます。
次の例では、
CCを使って 2 つのソースファイル (growth.Cとfft.C) をコンパイルし、実行時デバッグを有効にしてgrowthという名前の実行可能ファイルを作成します。
example%CC -g -o growth growth.C fft.Cファイル名に関する規則
コンパイラがコマンド行に指定されたファイルをどのように処理するかは、ファイル名に付加された接尾辞で決まります。次の表以外の接尾辞を持つファイルや、接尾辞がないファイルはリンカーに渡されます。
複数のソースファイルの使用
C++ コンパイラでは、複数のソースファイルをコマンド行に指定できます。コンパイラが直接または間接的にサポートするファイルも含めて、コンパイラによってコンパイルされる 1 つのソースファイルを「コンパイル単位」といいます。C++ では、それぞれのソースが別個のコンパイル単位として扱われます。1 つのソースファイルには、手続き (メインプログラム、関数、モジュールなど) をいくつでも組み込めます。ただし、関連する手続きを 1 つのファイルに集めることに利点があるように、1 つのファイルに 1 つの手続きが入るようにアプリケーションを編成することにも利点があります。このことに関しては、『C++ プログラミングガイド』に説明があります。
バージョンが異なるコンパイラでのコンパイル
Sun WorkShop 6 C++ 以降のコンパイラはテンプレートキャッシュディレクトリにテンプレートキャッシュのバージョンを示す文字列を付けます。
コンパイラは、キャッシュディレクトリのバージョンを調べ、キャッシュのバージョンに問題があれば、エラーメッセージを発行します。将来の Sun WorkShop C++ コンパイラもキャッシュのバージョンを調べます。たとえば、将来のコンパイラは異なるテンプレートキャッシュのバージョン識別子を持っているため、現在のリリースで作成されたキャッシュディレクトリを処理しようとすると、次のエラーを発行します。
SunWS_cache: エラー: /SunWS_cache のテンプレートデータベースはこのコンパイラと互換性がありません同様に、現在のリリースのコンパイラで以降のバージョンのコンパイラで作成されたキャッシュディレクトリを処理しようとすると、エラーが発行されます。
Sun WorkShop C++ コンパイラ 5.0 で作成されたテンプレートキャッシュディレクトリにはバージョン識別子が付けられていません。しかし、Sun WorkShop 6 C++ コンパイラは、5.0 のキャッシュディレクトリをエラーや警告なしに処理できます。これは、Sun WorkShop 6 C++ コンパイラが 5.0 のキャッシュディレクトリを、Sun WorkShop 6 C++ コンパイラが使用できるディレクトリ形式に変換するためです。
Sun WorkShop C++ コンパイラ 5.0 は、Sun WorkShop 6 C++ コンパイラ (または、これ以降のリリース) で作成されたキャッシュディレクトリを使用できません。Sun WorkShop C++ コンパイラ 5.0 は形式の違いを認識できず、Sun WorkShop 6 C++ コンパイラ (または、これ以降のリリース) で作成されたキャッシュディレクトリを処理しようとすると、エラーを発行します。
コンパイラをアップグレードするときは、テンプレートキャッシュディレクトリが格納されているディレクトリごとに
CCadmin-cleanを実行する習慣を付けることをお勧めします (ほとんどの場合、テンプレートキャッシュディレクトリの名前はSunWS_cacheです)。CCadmin-cleanの代わりに、rm-rfSunWS_cacheと指定しても同様の結果が得られます。コンパイルとリンク
この節では、プログラムのコンパイルとリンクについていくつかの側面から説明します。次の例では、
CCを使って 3 つのソースファイルをコンパイルし、オブジェクトファイルをリンクしてprgrmという実行可能ファイルを作成します。
example%CC file1.cc file2.cc file3.cc -o prgrmコンパイルとリンクの流れ
前の例では、コンパイラがオブジェクトファイル (
file1.o、file2.o、file3.o) を自動的に生成し、次にシステムリンカーを起動してファイルprgrmの実行可能プログラムを作成します。オブジェクトファイル (
file1.o、file2.o、file3.o) はコンパイルの後も消去されないので、ファイルを簡単に再リンクしたり、再コンパイルすることができます。
注 - ソースファイルが 1 つだけであるプログラムに対してコンパイルとリンクを同時に行なった場合は、対応する.oファイルが自動的に削除されます。複数のソースファイルをコンパイルする場合を除いて、すべての.oファイルを残すためにはコンパイルとリンクを別々に行なってください。
コンパイルが失敗すると、エラーごとにメッセージが返されます。エラーがあったソースファイルの
.oファイルは生成されず、実行可能プログラムも作成されません。コンパイルとリンクの分離
コンパイルとリンクは別々に行うことができます。
-cオプションを指定すると、ソースファイルがコンパイルされて.oオブジェクトファイルが生成されますが、実行可能ファイルは作成されません。-cオプションを指定しないと、コンパイラはリンカーを起動します。コンパイルとリンクを分離すれば、1 つのファイルを修正するためにすべてのファイルを再コンパイルする必要はありません。次の例では、最初の手順で 1 つのファイルをコンパイルし、次の手順でそれを他のファイルとリンクします。
example%CC -c file1.cc←新しいオブジェクトファイルを作成するexample%CC -o prgrm file1.o file2.o file3.o←実行可能ファイルを作成するリンク時には、完全なプログラムを作成するのに必要なすべてのオブジェクトファイルを指定してください。オブジェクトファイルが足りないと、リンクは「undefined external reference (未定義の外部参照がある)」エラー (ルーチンがない) で失敗します。
コンパイルとリンクの整合性
コンパイルとリンクを別々に実行する場合で、次のコンパイラオプションを使用する場合は、コンパイルとリンクの整合性を保つことが非常に重要です。
-fast-g-g0-library-misalign-mt-p-xa-xarch=isa-xcg92および-xcg89-xpg-xprofile-xtarget=t-xvectorまたは-xvector=yesこれらのオプションのいずれかを使用してサブプログラムをコンパイルした場合は、リンクでも同じオプションを使用してください。
-library、-fast、-xarchオプションの場合、コンパイルとリンクを同時に行えば渡されるはずのリンカーオプションも含める必要があります。-p、-xpg、-xprofileオプションの場合、ある段階ではオプションを指定して別の段階では指定しないと、プログラムの正しさには影響はありませんが、プロファイル処理ができなくなります。-g、-g0オプションの場合、ある段階ではオプションを指定して別の段階では指定しないと、プログラムの正しさには影響はありませんが、プログラムを正しくデバッグできなくなります。次の例では、
-xcg92コンパイラオプションを使用してプログラムをコンパイルしています。このオプションは-xtarget=ss1000用のマクロであり、-xarch=v8 -xchip=super -xcache=16/64/4:1024/64/1と展開されます。
example%CC -c -xcg92 sbr.ccexample%CC -c -xcg92 smain.ccexample%CC -xcg92 sbr.o smain.oプログラムがテンプレートを使用する場合は、リンク時にその中のいくつかがインスタンス化される可能性があります。その場合、インスタンス化されたテンプレートは最終行 (リンク行) のコマンド行オプションを使用してコンパイルされます。
SPARC V9 のためのコンパイル
64 ビットオブジェクトのコンパイル、リンク、実行には、V9 SPARC の Solaris 7 または Solaris 8 環境で 64 ビットカーネルが動作していなければなりません。64 ビットのコンパイルは、
-xarch=v9オプション、-xarch=v9aオプションまたは、-xarch=v9bオプションで指定します。コンパイラの診断
-verboseオプションを使用すると、プログラムのコンパイル中に役立つ情報を表示できます。このオプションについては、第 3 章を参照してください。コマンド行に指定された引数をコンパイラが認識できない場合には、それらはリンカーオプション、オブジェクトプログラムファイル名、ライブラリ名のいずれかとみなされます。
- 認識できないオプション (先頭にダッシュ (
-) かプラス符号 (+) の付いたもの) には、警告が生成されます。- オプション以外のもの (先頭にダッシュ (
-) もプラス符号 (+) も付いていないもの) には警告は生成されません (ただし、それらはリンカーに渡されます。リンカーも認識できないと、リンカーからエラーメッセージが生成されます)。次の例で、
-bitはCCによって認識されないため、リンカー (ld) に渡されます。リンカーはこれを解釈しようとします。単一文字のldオプションは連続して指定できるので、リンカーは-bitを-b、-i、-tとみなします。これらはすべて有効なldオプションです。しかし、これは本来の意図とは異なります。
example%CC -bit move.cc<- -bit は CC オプションとして認識されないCC: 警告: ld が起動される場合は、オプション-bit は ld に渡されます。それ以 外は無視されます。次の例では、
CCオプション-fastを指定しようとしましたが、先頭のダッシュ (-) を入力しませんでした。コンパイラはこの引数もリンカーに渡します。リンカーはこれをファイル名とみなします。
example%CC fast move.cc<- ユーザーは -fast と入力するつもりだったmove.C:ld: 重大なエラー: ファイル fast: ファイルをオープンできません:ファイルもディレクトリもありません。ld: 重大なエラー: ファイル処理エラー。 a.out へ書き込まれる出力がありません。コンパイラの構成
C++ コンパイラパッケージは、フロントエンド (
CCコマンド本体)、オプティマイザ (最適化)、コードジェネレータ (コード生成)、アセンブラ、テンプレートのプリリンカー (リンクの前処理をするプログラム)、リンクエディタから構成されています。CCコマンドは、これらの構成要素をそれぞれ自動的に起動します (コマンド行オプションを使用して自動起動されないように指定することもできます)。図 2-1 に C++ コンパイルの流れを示します。図 2-1 に、構成要素がコンパイラから呼び出される順番を示します。これらの構成要素はいずれもエラーを生成する可能性があり、構成要素はそれぞれ異なる処理を行うため、エラーを生成した構成要素を識別することがエラーの解決に役立つことがあります。
図 2-1 コンパイルの流れ![]()
次の表に示すように、コンパイラの構成要素への入力ファイルには異なるファイル名接尾辞が付いています。どのようなコンパイルを行うかは、この接尾辞で決まります。ファイル接尾辞の意味については、表 2-1 を参照してください。
メモリー条件
コンパイルに必要なメモリー量は、次の要素によって異なります。
SPARC プラットフォームでメモリーが足りなくなると、オプティマイザは最適化レベルを下げて現在の手続きを実行することでメモリー不足を補おうとします。それ以後のルーチンについては、コマンド行の
-xOlevel オプションで指定した元のレベルに戻ります。1 つのファイルに多数のルーチンが入っている場合、それをコンパイルすると、メモリーやスワップ領域が足りなくなることがあります。その場合には、最適化レベルを下げるか、複数ルーチンからなるソースファイルを 1 つのルーチンからなるファイルに分割します。
スワップ領域のサイズ
現在のスワップ領域は
swap-sコマンドで表示できます。詳細は、swap(1M) のマニュアルページを参照してください。
example%swap -stotal: 40236k bytes allocated + 7280k reserved = 47516k used, 1058708k availableスワップ領域の増加
ワークステーションのスワップ領域を増やすには、
mkfile(1M) とswap(1M) コマンドを使用します (そのためには、スーパーユーザーでなければなりません)。mkfileコマンドは特定サイズのファイルを作成し、swap -aはこのファイルをシステムのスワップ領域に追加します。
example#mkfile -v 90m /home/swapfile/home/swapfile 94317840 bytesexample#/usr/sbin/swap -a /home/swapfile仮想メモリーの制御
1 つの手続きが数千行からなるような非常に大きなルーチンを
-xO3以上でコンパイルすると、非常に多くのメモリーが必要になることがあります。このようなときには、システムのパフォーマンスが低下します。これを制御するには、1 つのプロセスで使用できる仮想メモリーの量を制限します。
shシェルで仮想メモリーを制限するには、ulimitコマンドを使用します。詳細は、sh(1) のマニュアルページを参照してください。次の例では、仮想メモリーを 16M バイトに制限しています。
example$ulimit -d 16000
cshシェルで仮想メモリーを制限するには、limitコマンドを使用します。詳細は、csh(1) のマニュアルページを参照してください。次の例でも、仮想メモリーを 16M バイトに制限しています。
example%limit datasize 16Mどちらの例でも、オプティマイザは データ空間が 16M バイトになった時点でメモリー不足が発生しないような手段をとります。
仮想メモリーの限度は、システムの合計スワップ領域の範囲内でなければなりません。さらに実際は、大きなコンパイルが行われているときにシステムが正常に動作できるだけの小さい値でなければなりません。
スワップ領域の半分以上がコンパイルによって使用されることがないようにしてください。
スワップ領域が 32M バイトなら次のコマンドを使用します。
example$ulimit -d 16000
example%limit datasize 16M最適な設定は、必要な最適化レベルと使用可能な実メモリーと仮想メモリーの量によって異なります。
メモリー条件
ワークステーションには、少なくとも 24M バイトのメモリーが必要です。32M バイトを推奨します。
example%/usr/sbin/dmesg | grep memmem = 655360K (0x28000000)avail mem = 602476544コマンドの簡略化
CCFLAGS環境変数で特別なシェル別名を定義するかmakeを使用すれば、複雑なコンパイラコマンドを簡略化できます。C シェルでの別名の使用
次の例では、頻繁に使用するオプションをコマンドの別名として定義します。
example%alias CCfx "CC -fast -xnolibmil"
example%CCfx any.C上記のコマンド
CCfxは、次のコマンドを実行するのと同じことです。
example%CC -fast -xnolibmil any.C
CCFLAGSによるコンパイルオプションの指定
CCFLAGS環境変数を設定すると、一度に特定のオプションを指定できます。
CCFLAGS変数は、コマンド行に明示的に指定できます。次の例は、CCFLAGSの設定方法を示したものです (C シェル)。
example%setenv CCFLAGS '-xO2 -xsb'
example%CC $CCFLAGS any.cc
makeを使用する場合、CCFLAGS変数が上の例のように設定され、メークファイルのコンパイル規則が暗黙的に使用された状態でmakeを呼び出すと、次のコンパイルが行われます (files は、複数のファイル名を示します)。
makeの使用
makeユーティリティは、サンのすべてのコンパイラで簡単に使用できる非常に強力なプログラム開発ツールです。詳細についてはmake(1S) のマニュアルページを参照してください。
makeでのCCFLAGSの使用メークファイルの暗黙のコンパイラ規則を使用する (つまり、C++ コンパイル行がない) 場合は、
makeプログラムによってCCFLAGSが自動的に使用されます。メークファイルへの接尾辞の追加
メークファイルに別のファイルの接尾辞を追加すると、C++ にその接尾辞を取り込むことができます。次の例は、C++ ファイルに対する有効な接尾辞として
.cppを追加します。次のように、メークファイルにSUFFIXESマクロを追加してください。SUFFIXES: .cpp .cpp~(この行は、メークファイル内のどこにでも入れることができます。)
次の内容をメークファイルに追加します。インデントされている行は、必ずタブでインデントしてください。
標準ライブラリヘッダーファイルに対する
makeの使用標準のライブラリファイルは
istream、fstreamのような名前で、.h接尾辞は付いていません。また、テンプレートのソースファイルは、istream.cc、fstream.ccといった名前になります。このため、Solaris 2.6 または Solaris 7 オペレーティング環境では、
<istream>などの標準のライブラリヘッダーがプログラムにインクルードされていて、メークファイルに.KEEP_STATEがある場合は問題になります。たとえば、<istream>がインクルードされている場合、makeユーティリティはistreamが実行可能ファイルであるとみなし、istream.ccからistreamを構築するときにデフォルトの規則を使用します。このため、非常に誤解を生みやすいエラーメッセージが返されます (istreamとistream.ccは両方とも C++ インクルードファイルのディレクトリにインストールされます)。1 つの解決策としては、makeユーティリティを使用せずに、dmakeをシリアルモードで使用します (つまり、dmake -m serialを実行)。また、当面の回避策としては、makeに-rオプションを指定します。-rオプションはデフォルトのmake規則を無効にします。しかし、この解決策は構築プロセスまで破壊する可能性があります。第 3 の解決策は、.KEEP_STATEターゲットを使用しないことです。
|
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |