Makefile

実際に目にする機会の多い Makefile は、GNU Make という拡張 Makefile 仕様のものだと思います。そこで、本文では GNU Make に絞ります。とりあえず使えそうな雛型をお探しの場合は、ページ最下部にあるソースをご覧ください。

基本

Makefile の基本的な記述方法は、以下の通りです。

[作りたいファイル(ターゲット)]:[左のファイルを作るのに必要なファイル(依存ファイル)]
    実行する命令

具体的に書いてみます。同じ階層に main.c sub.c があり、そこに sample.exe を作る Makefile です。

sample.exe:main.o sub.o
    gcc -o sample.exe main.o sub.o

main.o:main.c
    gcc -o main.o -c main.c
sub.o:sub.c
    gcc -o sub.o -c sub.c

少し楽してみます。

sample.exe:main.o sub.o
    gcc -o $@ $<

%.o:%.c
    gcc -o $@ -c $<

もっと楽をします。

SRCS=main.c sub.c
OBJS=$(SRCS:.c=.o)
sample.exe:$(OBJS)
    gcc -o $@ $<

%.o:%.c
    gcc -o $@ -c $<

gcc とかもマクロにします。

CC=gcc
SRCS=main.c sub.c
OBJS=$(SRCS:.c=.o)
sample.exe:$(OBJS)
    $(CC) -o $@ $<

%.o:%.c
    $(CC) -o $@ -c $<

階層化したディレクトリ構成で使う

平たいディレクトリではなく、階層化した構造でも使えるようにします。例として、以下のようなディレクトリ構造を考えます。

project/
project/Makefile
project/src
project/objs

以下のようになります。ちょっと複雑になってきました。

CC=gcc
OBJS_DIR=objs
SRCS_DIR=src
SRCS=main.c sub.c
# *.cを*.oに変換して、先頭にobjs/を付けます
# つまりOBJS=objs/main.o objs/sub.o になります
OBJS=$(addprefix $(OBJS_DIR)/, $(SRCS:.c=.o))
# サーチパスを指定します
# .cを持つファイルをSRCS_DIR内で検索します
vpath %.c $(SRCS_DIR)

# 依存関係1
sample.exe:$(OBJS)
    $(CC) -o $@ $<

# 依存関係2
$(OBJS_DIR)/%.o:%.c
    $(CC) -o $@ -c $<

sample.exe を作ろうとすると、OBJS=objs/main.o objs/sub.o が必要です(依存関係1)。objs/main.o には main.c が必要です(依存関係2)。vpath により、.c ファイルの検索場所として SRCS_DIR を指定しているので、そこを検索して、src/main.c を見つけます。以上で、main.* について、依存関係を解決できました。sub.* についても、同様に依存関係を解決できます。

※vpath は指定されたディレクトリを検索して、最初に一致したファイルを依存対象として認識します。つまり異なるディレクトリに同じファイル名があると、ややこしいことになりますので、注意が必要です。

後始末用の clean ターゲットも用意しましょう。*.o や *.exe を消すだけです。

clean:
    # 余談ですが、*.o を一箇所にまとめておくと、こういうとき楽です
    rm $(OBJS_DIR)/*.o
    rm sample.exe

以下のように、ヘッダファイルが別ディレクトリにあった場合は、-I で指定する必要があります。同様にライブラリをリンクしたい場合も、-L -l で指定する必要があります。そこで、コンパイラへのオプションもマクロにしておきましょう。後でいじるときに楽です。

project/
project/Makefile
project/src
project/src/include
project/lib
project/objs
INCLUDE_DIRS=-I./include
LIB_DIRS=-L./lib
CFLAGS=$(INCLUDE_DIRS)
LDFLAGS=$(LIB_DIRS) -lutil

以上を全部まとめてみます。ついでに sample.exe もターゲット名としてマクロにしておきます。

TARGET=sample.exe 

# コンパイラ関連
CC=gcc
INCLUDE_DIRS=-I./include
LIB_DIRS=-L./lib
CFLAGS=$(INCLUDE_DIRS)
LDFLAGS=$(LIB_DIRS) -lutil

# 配置関連
OBJS_DIR=objs
SRCS_DIR=src
SRCS=main.c sub.c
OBJS=$(addprefix $(OBJS_DIR)/, $(SRCS:.c=.o))
vpath %.c $(SRCS_DIR)

# 依存関係
$(TARGET):$(OBJS)
    $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
$(OBJS_DIR)/%.o:%.c
    $(CC) $(CFLAGS) -o $@ -c $<
clean:
    rm $(OBJS_DIR)/*.o
    rm sample.exe

トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS