[an error occurred while processing this directive] [an error occurred while processing this directive]

makeの使い方・分割コンパイル

C言語のプログラムは、いくつかのファイルに分けて書くことができます。 モジュールごとに別のファイルにすることで、コンパイルが早くなったり、デバッグが楽になったりします。

準備

例えば、こういうプログラム(sample.c)があります。
#include <stdio.h>

void printHello(void){
  printf("Hello\n");
}

int main(void){
  printHello();
}
このプログラムをコンパイルするには、
$ gcc sample.c
とすると、a.out (Cygwinだとa.exe)が出来ます。
$ gcc sample.c -o sample
と書くと、sampleという名前の実行ファイルが出来ます。

分割してみる

ここで、printHello()を別のファイルに分けてみます。まず、printHello()を書いたファイルを作ります。
[hello.c]
#include <stdio.h>
 
void printHello(void){
  printf("Hello\n");
}
次に、これを用いるmain()を書きます。
[sample.c]
#include <stdio.h>
 
void printHello(void);
 
int main(void){
  printHello();
}
ポイントは、sample.cに書いてある、
void printHello(void);
です。これがないと、コンパイルした時に「printHello()という関数は見つからない」というエラーが出ます。 このため、「別のファイルにprintHello()がちゃんと書かれている」ことを示すために、この一行を書いておきます。これをプロトタイプ宣言といいます。
これをコンパイルするには、以下のようにします。
$ gcc -c hello.c
$ gcc -c sample.c
$ gcc sample.o hello.o -o sample
C言語のプログラムは、内部的にはオブジェクトファイル(なんとか.o)というファイルを一度作って、その後プログラムを作っています。
分割コンパイルをする時には、まず中間ファイルを作って、それを最後に組み合わせます。
ちゃんとsampleが実行できることを確認しましょう。

ヘッダファイルを書く

先ほどの方法だと、hello.cを色々なファイルで用いる場合、いちいち関数のプロトタイプを書く必要があります。他にも、structの宣言や#defineでの定数の宣言など、色々なファイルに共通して書かないといけない処理はいろいろあります。これを簡単に書くためにあるのが"ヘッダファイル"です。以下のようなファイルを書いてみます。
[hello.h]
void printHello(void);
そして、sample.cに以下の一行を加えます。
 [sample.c]
 #include "hello.h"
これで、先ほど書いたprintHello()関数のプロトタイプが不要になります。 もう一度全部書くと、以下のようになります。
[hello.c]
#include <stdio.h>
  
void printHello(void){
  printf("Hello\n");
}
[hello.h]
void printHello(void);
[sample.c]
#include "hello.h"
  
int main(void){
  printHello();
}
コンパイルは上と同じように出来ます。
$ gcc -c hello.c
$ gcc -c sample.c
$ gcc sample.o hello.o -o sample

Makefileを書く

これでめでたくプログラムの分割が出来ましたが、コンパイルはけっこう面倒です。でも、makeというプログラムを書くと、簡単、しかも早くコンパイルをすることができます。
hello.cがあるのと同じディレクトリに、Makefileというファイルを作って、以下のように書きます。
sample : sample.o hello.o
(タブ) gcc -o sample sample.o hello.o
 
.c.o :
(タブ) gcc -c $<
(タブ)と書いたところは、タブを入力して下さい。初めの方はsampleというプログラムを作るにはsample.oとhello.oが必要で、実行するコマンドは"gcc -o sample sample.o hello.o" だという意味です。
次のブロックは、.oを.cファイルから生成するためのルールです。
これは一々
sample.o : sample.c
(タブ) gcc -c sample.c
 
hello.o : hello.c
(タブ) gcc -c hello.c
と書いてもいいですが、先のように書くことで、あらゆる.oファイルを.cファイルから作る、という意味になります。

これで、
$ make sample
と打つと、目的のプログラムが得られます。
[an error occurred while processing this directive]