🐧 Linux 総合学習プラットフォーム
C・ビルドツール ・ 中級

gccでCソースをコンパイルする

Cのソースコードは、そのままでは実行できません。コンパイラ gcc に渡して、CPUが解釈できる機械語の実行ファイルへ変換します。最も単純には gcc hello.c とだけ打つと、a.out という名前の実行ファイルが生成されます。-o オプションで出力名を指定すれば、gcc hello.c -o hello のように好きな名前の実行ファイルを作れます。生成した実行ファイルは ./hello のようにパスを付けて起動します。

C言語で書いたプログラムは、ファイルに書いた時点ではただのテキストにすぎません。書いてある内容は人間が読むための英単語と記号の集まりで、CPUはそれをそのまま実行できません。CPUが直接理解できるのは機械語と呼ばれる0と1の命令列だけです。そこで、人が書いたソースコードをCPU向けの機械語へ翻訳する処理が必要になります。この翻訳がコンパイルで、翻訳を担うプログラムをコンパイラと呼びます。Linux環境で最も広く使われるCコンパイラが gcc(GNU Compiler Collection)です。gcc にソースファイルを渡すと、その内容を解析して機械語に変換し、そのまま起動できる実行ファイルを生成します。つまり「書く→コンパイルする→動かす」という3拍子が、Cでプログラムを動かすときの基本リズムになります。

いちばん単純なコンパイル

例として、画面に文字を表示するだけの hello.c があるとします。中身は #include <stdio.h> から始まり、main 関数の中で printf を呼ぶだけの数行のプログラムです。これをコンパイルする最も短い書き方は、ターミナルで gcc hello.c と打つことです。エラーがなければ、gcc は何もメッセージを出さずに終わります。Linuxのコマンドは成功すると黙るのが流儀なので、「何も出ないのは失敗ではなく成功」と覚えておきましょう。このとき、カレントディレクトリには a.out という名前のファイルができています。これが翻訳の成果物である実行ファイルで、リンクまで終えて生成される最終成果物です。なぜ a.out という名前かというと、これは assembler output(アセンブラの出力)に由来する歴史的な既定名で、出力名を指定しなかったときに gcc が使う名前です。ls で確認すると、ソースの hello.c と並んで a.out が増えているのが見えます。a.out は実行可能な状態になっていて、ファイルには実行権限(x)が付いています。

出力名を指定する -o オプション

毎回 a.out という名前ができると、複数のプログラムを作ったときにどれがどれだか分からなくなります。そこで -o オプションを使い、出力する実行ファイルの名前を自分で指定します。たとえば gcc hello.c -o hello と打てば、a.out ではなく hello という名前の実行ファイルが作られます。-o は output の頭文字で、その直後に書いた名前が出力ファイル名になります。オプションとソースファイルの順序は自由で、gcc -o hello hello.c と書いても結果は同じです。実務ではほぼ必ずこの -o を付けて、ソース名と対応した分かりやすい名前を付けるのが習慣です。

作った実行ファイルを動かす

生成した実行ファイルは、ファイル名をそのまま打つだけでは起動できないことがあります。hello とだけ打つと「コマンドが見つかりません(command not found)」と言われがちです。これはシェルが、コマンドを決まった検索パス(環境変数 PATH に並んだディレクトリ群)の中からしか探さず、カレントディレクトリは原則その対象に含めないためです。これはセキュリティ上の配慮で、いまいる場所にたまたま置かれた紛らわしい名前のプログラムを、うっかり実行してしまわないようにする仕組みです。そこで ./hello のように、先頭に ./ を付けて「いまいるディレクトリのこのファイル」と明示的に指定します。. は現在地を表す記号なので、./hello は「カレントディレクトリにある hello を実行せよ」という意味になります。実行すると、プログラムが動いて結果が画面に表示されます。自分で作ったコマンドをどこからでも呼べるようにしたいときは、置き場所を PATH に加える、という発展的なやり方もあります。

よくある失敗

初学者がつまずきやすいのは、まず ./ の付け忘れです。hello だけ打って command not found が出たら、ほぼこれが原因です。次に多いのが、ソースに文法ミスがあってコンパイル自体が通らないケースです。セミコロンの付け忘れやかっこの対応ミスがあると、gcc は error: と書かれたメッセージを行番号付きで出して止まります。このときは実行ファイルは作られないので、慌てず指摘された行を直して再度コンパイルします。また、ヘッダファイル(.h)の取り込みは必要ですが、printf などを使うのに必要な宣言が無いと warning(警告)が出ることがあります。これらの宣言は #include で取り込みますが、その仕組みは後の段階で詳しく扱います。warning はエラーと違ってコンパイル自体は止まらず実行ファイルもできてしまうため、つい見過ごしがちですが、潜在的な不具合の予告であることが多いので、出たらできるだけその場で解消する習慣をつけましょう。なお、コンパイルが通っても実行ファイルに実行権限が無いと動かせないことがあり、その場合は権限を付与する必要があります。これらのつまずきは、4段階の工程やヘッダとライブラリの関係を学ぶと、なぜ起きるのかが腑に落ちるようになります。

実務での位置づけ

gcc によるコンパイルは、C/C++を扱うあらゆる開発の出発点です。組込みLinuxの世界でも、デバイスを制御する小さなツールから、カーネルモジュール、各種ライブラリまで、土台はこのコンパイルの上に成り立っています。最初は gcc ソース -o 名前 で実行ファイルを作り、./名前 で動かす——この一往復を、手を動かして体に覚え込ませることが何より大切です。ソースが1つのうちはこの単純な形で十分ですが、ファイルが増えてくると、後述する4段階の理解や Makefile による自動化が効いてきます。まずは「翻訳して、できた実行ファイルを起動する」という最小の流れを、確実に再現できるようにしておきましょう。

この項目に出てくる用語

コンパイルこんぱいる
人が書いたソースコードを、CPUが実行できる機械語へ翻訳する処理。
実行ファイルじっこうふぁいる
そのまま起動して動かせる、完成した機械語のプログラム。
ヘッダファイルへっだふぁいる
関数や定数の宣言をまとめた、#include で取り込む .h ファイル。

関連コマンド

gcc./a.out

▶ 学習アプリでこの続きを学ぶ・演習する