前回の記事(
make入門 #1 makeとは)では、makeがどのようなものかを説明しました。
今回は、C言語を使った開発などでよくある複数のソースファイルから1つの実行ファイルを作成するMakefileの書き方を説明します。
処理のフロー
図のように3つのソースファイルを用意します。それぞれのファイルの概要は次のとおりです。
ファイル名 |
説明 |
main.c |
メインのソースコード |
sub.c |
ユーザ定義関数を含むソースコード |
sub.h |
ユーザ定義関数のヘッダファイル |
*.o |
*.cファイルをコンパイルして生成したオブジェクトファイル |
prog2 |
2つのオブジェクトファイルをリンクして作成される実行ファイル |
これを行うMakefileは次のようになります。
prog2: main.o sub.o
gcc -o prog2 main.o sub.o
main.o: main.c sub.h
gcc -c -o main.o main.c
sub.o: sub.c sub.h
gcc -c -o sub.o sub.c
各ソースコードについては、
末尾に掲載します。
Makefileの説明
処理ルールと入力ファイル
図の青い部分は、処理を表しています。Makefileでもそれに対応して、3つのルールが記載されています。
前回は、
:の右側の入力ファイルがひとつだけの例を紹介しました。今回の例のように入力ファイルを複数記述することも可能です。
その場合、入力ファイルのどれか一つでも変更があれば、出力ファイルを作成するための処理が実行されます。
ルール記述の順序
Makefileの中でprog2の作成ルールが最も先頭に記載されています。例えば、main.oの作成ルールを先頭にすることはできません。
なぜなら、Makefileは、複数のルールが記述されていた場合、先頭のルールで記述された出力ファイルを作成しようとするからです。
つまり、main.oの作成ルールが先頭にあると、makeを実行してもmain.oが作成されて動作が完了します。
prog2の入力ファイルとしてmain.oとsub.oが記述されています。
初めてmakeを実行する場合、これらのファイルが存在しません。
その場合、makeは、次のようにmain.oとsub.oの作成ルールにしたがって、それらを作成します。
$ make
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -o prog2 main.o sub.o
一部のファイルを更新
ここで、sub.cだけを更新してみます。実際には内容を更新しますが、ここではmakeの動作を確かめるのが目的なので、
touchコマンドでタイムスタンプのみ更新します。
touch sub.c
makeを実行するとsub.oが再作成され、それに依存しているprog2も再作成されました。
main.oについては、その入力ファイルであるmain.cが更新されていないため、なにも処理が行われませんでした。
このように依存関係にしたがって、必要な処理のみを実行することがmakeの利点です。
$ make
gcc -c -o sub.o sub.c
gcc -o prog2 main.o sub.o
ヘッダファイルの更新
sub.hは、main.cでもsub.cでも使われており、main.oおよびsub.o両方の入力ファイルとしてMakefileに記載されています。
このヘッダファイルを更新すると、以下のようにどちらの.oファイルが更新されて、それに依存するprog2も再作成されます。
$ touch sub.h
$ make
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -o prog2 main.o sub.o
ソースコード
main.c
#include <stdio.h>
#include "sub.h"
int main() {
printf("Calculated result: %d\n", calc(1, 3));
return 0;
}
sub.h
int calc(int a, int b);
sub.c
int calc(int a, int b)
{
return a * 2 + b - 1;
}
まとめ
本記事では、複数のルールをMakefileに記述する方法について説明しました。
次回は、自動変数と拡張子ルールという機能を説明します。
以下には、make入門の全記事がリストアップされています。