C++ ユーザーズガイド ホーム目次前ページへ次ページへ索引


第 2 章

C++ コンパイラの使用方法

この章では、C++ コンパイラの使用方法を説明します。

コンパイラの主な目的は、C++ などの高水準言語で書かれたプログラムをコンピュータハードウェアで実行できるデータファイルに変換することです。C++ コンパイラでは次のことができます。

コンパイル方法の概要

この節では、C++ コンパイラを使って C++ プログラムのコンパイルと実行をどのように行うかを簡単に説明します。コマンド行オプションの詳しい説明については、第 3 章を参照してください。


注 - この章のコマンド行の例は、CC の使用方法を示すためのものです。実際に出力される内容はこれと多少異なる場合があります。

C++ アプリケーションを構築して実行するには、基本的に次の手順が必要です。

  1. エディタで C++ソースファイルを作成する。このソースファイルには、表 2-1 に列挙されている接尾辞のいずれかを使用します。

  2. コンパイラを起動して実行可能ファイルを作成する

  3. 実行可能ファイルの名前を入力してプログラムを実行する

次のプログラムは、メッセージを画面に表示する例です。

example% cat greetings.cc
    #include <iostream>
    int main()  {
      std::cout << "Real programmers write C++!" << std::endl;
      return 0;
    }
example% CC greetings.cc
example% a.out    
 Real programmers write C++!
example%

この例では、ソースファイル greetings.ccCC でコンパイルしています。デフォルトでは、実行可能ファイルがファイル a.out として作成されます。プログラムを起動するには、コマンドプロンプトで実行可能ファイル名 a.out を入力します。

従来、UNIX コンパイラは実行可能ファイルに a.out という名前を付けていました。しかし、すべてのコンパイルで同じファイルを使用するのは不都合な場合があります。そのファイルがすでにあれば、コンパイラを実行したときに上書きされてしまうからです。次の例のように、コンパイラオプションに -o を使用すれば、実行可能出力ファイルの名前を指定できます。

example% CC -o greetings greetings.C

この例では、-o オプションを指定することによって、実行可能なコードがファイル greetings に書き込まれます (プログラムにソースファイルが 1 つだけしかない場合は、ソースファイル名から接尾辞を除いたものを出力ファイル名にすることが一般的です)。

あるいは、コンパイルの後に mv コマンドを使って、デフォルトの a.out ファイルを別の名前に変更することもできます。いずれの場合も、プログラムを実行するには、実行可能ファイルの名前を入力します。

example% greetings 
Real programmers write C++!
example%

コンパイラの起動

この後の節では、CC コマンドで使用する規約、コンパイラのソース行指令など、コンパイラの使用に関連する内容について説明します。

コマンド構文

コンパイラの一般的なコマンド行の構文を次に示します。

CC [options] [source-files] [object-files] [libraries]

options は、先頭にダッシュ (-) またはプラス記号 (+) の付いたキーワード (オプション) です。このオプションには、引数をとるものがあります。source-files にはソースファイル、object-files にはオブジェクトファイル、libraries にはライブラリを指定します。

通常、コンパイラオプションの処理は、左から右へと行われ、マクロオプション (他のオプションを含むオプション) は、条件に応じて内容が変更されます。ほとんどの場合、同じオプションを 2 回以上指定すると、最後に指定したものだけが有効になり、オプションの累積は行われません。次の点に注意してください。

ソースファイル、オブジェクトファイル、およびライブラリは、コマンド行に指定した順にコンパイルとリンクが行われます。

次の例では、CC を使って 2 つのソースファイル (growth.Cfft.C) をコンパイルし、実行時デバッグを有効にして growth という名前の実行可能ファイルを作成します。

example% CC -g -o growth growth.C fft.C

ファイル名に関する規則

コンパイラがコマンド行に指定されたファイルをどのように処理するかは、ファイル名に付加された接尾辞で決まります。次の表以外の接尾辞を持つファイルや、接尾辞がないファイルはリンカーに渡されます。

表 2-1   C++ コンパイラが認識できるファイル名接尾辞 
接尾辞 言語 処理
.c C++ C++ ソースファイルとしてコンパイルし、オブジェクトファイルを現在のディレクトリに入れる。オブジェクトファイルのデフォルト名は、ソースファイル名に .o 接尾辞が付いたものになる。
.C C++ .c 接尾辞と同じ処理。
.cc C++ .c 接尾辞と同じ処理。
.cpp C++ .c 接尾辞と同じ処理。
.cxx C++ .c 接尾辞と同じ処理。
.i C++ プリプロセッサの出力ファイルを C++ ソースファイルとして扱い、.c 接尾辞と同じ処理をする。
.s アセンブラ ソースファイルをアセンブラを使ってアセンブルする。
.S アセンブラ C 言語プリプロセッサとアセンブラを使ってソースファイルをアセンブルする。
.il インライン展開 アセンブリ用のインラインテンプレートファイルを使ってインライン展開を行う。コンパイラはテンプレートを使って、選択されたルーチンのインライン呼び出しを展開する
(インラインテンプレートファイルは、特殊なアセンブラファイルです。inline(1) のマニュアルページを参照してください)。
.o オブジェクト
ファイル
オブジェクトファイルをリンカーに渡す。
.a 静的 (アーカイブ)
ライブラリ
オブジェクトライブラリの名前をリンカーに渡す。
.so .so.n 動的 (共有)
ライブラリ
共有オブジェクトの名前をリンカーに渡す。


複数のソースファイルの使用

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 -rf SunWS_cache と指定しても同様の結果が得られます。

コンパイルとリンク

この節では、プログラムのコンパイルとリンクについていくつかの側面から説明します。次の例では、CC を使って 3 つのソースファイルをコンパイルし、オブジェクトファイルをリンクして prgrm という実行可能ファイルを作成します。

example% CC file1.cc file2.cc file3.cc -o prgrm

コンパイルとリンクの流れ

前の例では、コンパイラがオブジェクトファイル (file1.ofile2.ofile3.o) を自動的に生成し、次にシステムリンカーを起動してファイル prgrm の実行可能プログラムを作成します。

オブジェクトファイル (file1.ofile2.ofile3.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 (未定義の外部参照がある)」エラー (ルーチンがない) で失敗します。

コンパイルとリンクの整合性

コンパイルとリンクを別々に実行する場合で、次のコンパイラオプションを使用する場合は、コンパイルとリンクの整合性を保つことが非常に重要です。

これらのオプションのいずれかを使用してサブプログラムをコンパイルした場合は、リンクでも同じオプションを使用してください。

次の例では、-xcg92 コンパイラオプションを使用してプログラムをコンパイルしています。このオプションは -xtarget=ss1000 用のマクロであり、
-xarch=v8 -xchip=super -xcache=16/64/4:1024/64/1 と展開されます。

 example% CC -c -xcg92 sbr.cc
 example% CC -c -xcg92 smain.cc
 example% 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 章を参照してください。

コマンド行に指定された引数をコンパイラが認識できない場合には、それらはリンカーオプション、オブジェクトプログラムファイル名、ライブラリ名のいずれかとみなされます。

基本的な区別は次のとおりです。

次の例で、-bitCC によって認識されないため、リンカー (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 を参照してください。

表 2-2   C++ コンパイルシステムの構成要素

構成要素

内容

使用時の注意
ccfe フロントエンド (コンパイラプリプロセッサ
(前処理系) とコンパイラ)

iropt (SPARC) コードオプティマイザ (最適化) -xO[2-5]、-fast
xcg386 (IA) 中間言語トランスレータ 必ず起動
inline (SPARC) アセンブリ言語テンプレートのインライン展開 il ファイルを指定
mwinline (IA) 関数の自動的なインライン展開 -xO4
fbe アセンブラ
cg (SPARC) コード生成、インライン機能、アセンブラ
codegen (IA) コード生成
CClink テンプレートのリンクの前処理
ld 従来のリンクエディタ
ild インクリメンタルリンクエディタ -g、-xildon

メモリー条件

コンパイルに必要なメモリー量は、次の要素によって異なります。

SPARC プラットフォームでメモリーが足りなくなると、オプティマイザは最適化レベルを下げて現在の手続きを実行することでメモリー不足を補おうとします。それ以後のルーチンについては、コマンド行の -xOlevel オプションで指定した元のレベルに戻ります。

1 つのファイルに多数のルーチンが入っている場合、それをコンパイルすると、メモリーやスワップ領域が足りなくなることがあります。その場合には、最適化レベルを下げるか、複数ルーチンからなるソースファイルを 1 つのルーチンからなるファイルに分割します。

スワップ領域のサイズ

現在のスワップ領域は swap -s コマンドで表示できます。詳細は、swap(1M) のマニュアルページを参照してください。

swap コマンドを使った例を次に示します。

example% swap -s 
total: 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 bytes 
 example# /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 バイトなら次のコマンドを使用します。

sh シェルの場合

example$ ulimit -d 16000

csh シェルの場合

example% limit datasize 16M

最適な設定は、必要な最適化レベルと使用可能な実メモリーと仮想メモリーの量によって異なります。

メモリー条件

ワークステーションには、少なくとも 24M バイトのメモリーが必要です。32M バイトを推奨します。

実際のメモリーを調べるには、次のコマンドを使用します。

example% /usr/sbin/dmesg | grep mem 
mem = 655360K (0x28000000)
avail mem = 602476544

コマンドの簡略化

CCFLAGS 環境変数で特別なシェル別名を定義するか make を使用すれば、複雑なコンパイラコマンドを簡略化できます。

C シェルでの別名の使用

次の例では、頻繁に使用するオプションをコマンドの別名として定義します。

example% alias CCfx "CC -fast -xnolibmil"

次に、この別名 CCfx を使用します。

example% CCfx any.C

上記のコマンド CCfx は、次のコマンドを実行するのと同じことです。

example% CC -fast -xnolibmil any.C

CCFLAGS によるコンパイルオプションの指定

CCFLAGS 環境変数を設定すると、一度に特定のオプションを指定できます。

CCFLAGS 変数は、コマンド行に明示的に指定できます。次の例は、CCFLAGS の設定方法を示したものです (C シェル)。

 example% setenv CCFLAGS '-xO2 -xsb'

次の例では、CCFLAGS を明示的に使用しています。

 example% CC $CCFLAGS any.cc

make を使用する場合、CCFLAGS 変数が上の例のように設定され、メークファイルのコンパイル規則が暗黙的に使用された状態で make を呼び出すと、次のコンパイルが行われます (files は、複数のファイル名を示します)。

CC -xO2 -xsb files...

make の使用

make ユーティリティは、サンのすべてのコンパイラで簡単に使用できる非常に強力なプログラム開発ツールです。詳細については make(1S) のマニュアルページを参照してください。

make での CCFLAGS の使用

メークファイルの暗黙のコンパイラ規則を使用する (つまり、C++ コンパイル行がない) 場合は、make プログラムによって CCFLAGS が自動的に使用されます。

メークファイルへの接尾辞の追加

メークファイルに別のファイルの接尾辞を追加すると、C++ にその接尾辞を取り込むことができます。次の例は、C++ ファイルに対する有効な接尾辞として .cpp を追加します。次のように、メークファイルに SUFFIXES マクロを追加してください。

 SUFFIXES: .cpp .cpp~

(この行は、メークファイル内のどこにでも入れることができます。)

次の内容をメークファイルに追加します。インデントされている行は、必ずタブでインデントしてください。

.cpp:
    $(LINK.cc) -o $@ $< $(LDLIBS)
.cpp~:
    $(GET) $(GFLAGS) -p $< > $*.cpp
    $(LINK.cc) -o $@ $*.cpp $(LDLIBS)
.cpp.o:
    $(COMPILE.cc) $(OUTPUT_OPTION) $<
.cpp~.o:
    $(GET) $(GFLAGS) -p $< > $*.cpp
    $(COMPILE.cc) $(OUTPUT_OPTION) $<
.cpp.a:
    $(COMPILE.cc) -o $% $<
    $(COMPILE.cc) -xar $@ $%
    $(RM) $%
.cpp~.a:
    $(GET) $(GFLAGS) -p $< > $*.cpp
    $(COMPILE.cc) -o $% $<
    $(COMPILE.cc) -xar $@ $%
    $(RM) $%

標準ライブラリヘッダーファイルに対する make の使用

標準のライブラリファイルは istreamfstream のような名前で、.h 接尾辞は付いていません。また、テンプレートのソースファイルは、istream.ccfstream.cc といった名前になります。

このため、Solaris 2.6 または Solaris 7 オペレーティング環境では、<istream> などの標準のライブラリヘッダーがプログラムにインクルードされていて、メークファイルに .KEEP_STATE がある場合は問題になります。たとえば、<istream> がインクルードされている場合、make ユーティリティは istream が実行可能ファイルであるとみなし、istream.cc から istream を構築するときにデフォルトの規則を使用します。このため、非常に誤解を生みやすいエラーメッセージが返されます (istreamistream.cc は両方とも C++ インクルードファイルのディレクトリにインストールされます)。1 つの解決策としては、make ユーティリティを使用せずに、dmake をシリアルモードで使用します (つまり、dmake -m serial を実行)。また、当面の回避策としては、make-r オプションを指定します。-r オプションはデフォルトの make 規則を無効にします。しかし、この解決策は構築プロセスまで破壊する可能性があります。第 3 の解決策は、.KEEP_STATE ターゲットを使用しないことです。


サン・マイクロシステムズ株式会社
Copyright information. All rights reserved.
ホーム   |   目次   |   前ページへ   |   次ページへ   |   索引