はじめに
今回の記事は、テーマにもある通りC言語で作成したプログラムをコンパイル、ビルドする時に使用するMakefileについてのメモ書きです。

以下に該当する人は是非読んで見てね
- C言語使い始めてMakefileって何???
- Makefileが何かは知ってるけど、実際に自分で書いたことないって人
- Makefileで利用されている変数が曖昧って人
- 中間ファイルの出力先を別ディレクトリにしたい等
Makefileってなに?
まずは、Makefileとは?というところから。
もちろんそんなことは知ってますという人は読み飛ばして下さい。
manコマンドを使って確認した内容を一部抜粋します。
To prepare to use make,
man makeコマンドのドキュメントから抜粋
you must write a file called the makefile that describes the relationships among files in your program,
and the states the commands for updating each file.
引用した文章によると、Makefileはmakeコマンドを利用する時に使われるファイルとのこと。
そのMakefileの中身に何を記載するのかというと、利用する各ファイルの関係性やファイルを更新するためのルール的なものを記載するものと書かれています。

結局Makefikeって…
- makeコマンドを使う時に呼ばれるファイル
- Makefileは各ソースファイルの関係性や更新するためのルールを記述するもの
- 結果、gccなどのコンパイルを自動化することが出来るので便利
Makefileを使ってC言語のプログラムをコンパイル&ビルド
さっそく、C言語のプログラムをgccを使ってコンパイル&ビルドする時のMakefileについて確認していきます。
想定しているディレクトリ構造
まずは、今回想定しているディレクトリ構造から。
中間ファイルや実行ファイルの出力先、ソースコードの置き場所など以下のように考えています。

次からMakefileの書き方を確認していきます。
簡単なmain.cファイルだけでビルドする
まずは、何も考えずにmain.cファイルだけをコンパイル&ビルドする方法から。
なるべく不要なものを記述しないようにします。

まずは、bin,inlucde,lib,obj,srcディレクトリを作成して、
srcフォルダの直下にmain.cファイルを作成してみよう。
main.cファイルを作成したら、お決まりの「hello world」を返すプログラムを記述
#include <stdio.h>
int main() {
printf("hello World\n");
return 0;
}

次にsrcフォルダの直下にMakefileを作成
記述するMakefileはなるべく不要なものは記述しないようします。
CC = gcc
CFLAGS = -g -Wall -O2
INCLUDE = -I ../include
TARGET = ../bin/hello
OBJDIR = ../obj
SOURCE = main.c
OBJECTS = $(addprefix $(OBJDIR)/, $(SOURCE:.c=.o))
$(TARGET) : $(OBJECTS)
mkdir -p $(dir $@)
$(CC) $^ -o $(TARGET)
$(OBJDIR)/%.o : %.c
mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $<
all : $(TARGET)
clean :
rm -rf $(OBJECTS) $(TARGET)
基本的なことは既に紹介されている記事もあるので触れませんが、記号であったり使用している関数については少しだけ解説を加えておきます。
addprefix関数・・・先頭に文字を追加することが可能です。
$(addprefix {追加文字}, {対象})
9行目では、先頭にオブジェクトファイルを作成するディレクトリを追加しています。
dir関数・・・ディレクトリ情報を抽出することが可能です。
12.16行目ではディレクトリ情報をもとにmkdirコマンドでディレクトリを作成します。
mkdirコマンドを使用してディレクトリを作成した際に
既に作成されている場合エラーが発生するがします。でもpオプションをセットすることによってそのエラーを無視することが出来ます。
$@,$<などは自動変数と呼ばれるものです。いくつかの意味は以下で説明します。
- $@・・・ターゲット名
- $^・・・ターゲットの依存関係の名前
- $<・・・ターゲットの依存関係の一番最初の名前
これで、あとはmakeコマンドを使うだけ。
srcディレクトリで「make all」と入力すれば、
中間ディレクトリであるobjディレクトリにmain.oファイルが作成され、binディレクトリには実行ファイルであるhelloファイルが作成されるはずです。
あとは、binディレクトリにあるhelloでプログラムを実行できるはずです。
「make clean」と入力すれば自動で作成された実行ファイルや中間ファイルを削除できます。
もちろん、mainファイルだけであればわざわざ手間をかけてMakefileなんて用意する必要ないんですけどね…
まとめ
これで、基本的なMakefileの書き方はメモできました。
もちろん、実際に使用するときにはもっとたくさんのことを記述する必要があります。
- 他のソースファイルやヘッダファイルを追加する場合
- ライブラリをリンクする場合
それたについてもいずれまとめたいと思ったのですが、想定していたより長くなったのでとりあえずここまで。
追記:以下のページ追記しました。