make入門 #2 複数のルール

前回の記事(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入門の全記事がリストアップされています。

0 件のコメント: