今日はプログラマの必須ツールであるmakeについて説明しましょう。 by Y.O
なお、私が何いってるのかさっぱりわからないという新入生の皆さん、何も心配しなくても一年後にはだいたい分かるようになります。
知らない方のために説明するとmakeはプログラムの複雑なコンパイルを自動化するためのツールです。通常コンパイルは一つのファイルを変更すると複数のファイルに影響が出るため、影響があるものだけをコンパイルし直すのが普通です。全部コンパイルし直せばよいと思われるかもしれませんが、FirefoxやOpenOfficeのように巨大なプログラムになるとそうもいきません。さらにC++言語になると一つ一つのファイルのコンパイルに結構時間がかかるようになります。
この問題を解決するためにはVisualStudioやXcodeのように自動的に再コンパイルが必要なファイルを判別してくれるソフトを使うか、このmakeを使うことになります。しかし、makeはとても古いソフトであると同時にC言語やC++言語のみを目的に作られたソフトではありません。そのため、あるファイルを変更したときに、どのファイルをコンパイルし直さねばならないかを指定する必要があります。makeの説明を検索すればその方法はたくさん出てきます。
しかし、いちいち指定するのは結構めんどうです。#includeの追加のたびに直さねばなりません。この問題を解決するために最近のGCCには依存関係を自動的に探し出し、Makefileの形式で出力してくれるオプションがあります。このオプションを用いてファイルごとに依存関係を書き出し、MakefileからincludeしてやることでMakefileを書き換えるのはファイルを追加したときだけでよくなります。そのように書かれたMakefileのテンプレートを以下に示しておきます。
[text]
# Hey Emacs, this is a -*- makefile -*-
# Target Executable file
TARGET = hello
# C source code
SRC = hello.c
# CPP source code
CPPSRC =
# Common Flags
COMPILE_FLAGS = -Wall -pipe
COMMON_FLAGS =
# C compiler
CC = gcc
CFLAGS =
# C++ compiler
CPP = g++
CPPFLAGS =
# Linker
LD = gcc # set g++ to use c++
LDFLAGS =
# Windows Executable file’s extension
ifdef windir
EXE = $(TARGET).exe
COMMON_FLAGS +=
else
EXE = $(TARGET)
LDFLAGS +=
endif
# Debug Options
ifdef DEBUG
COMMON_FLAGS += -g -O0
else
COMMON_FLAGS += -Os -mtune=native
endif
# generate dependence file
OBJDIR = ./objs
COMPILE_FLAGS += -MMD -MP -MF $(OBJDIR)/$(@F).d
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o)
DEPENDS = $(SRC:%.c=$(OBJDIR)/%.o.d) $(CPPSRC:%.cpp=$(OBJDIR)/%.o.d)
all:$(EXE)
$(EXE):$(OBJ)
$(LD) $(COMMON_FLAGS) $(LDFLAGS) -o $(EXE) $(OBJ)
$(OBJDIR)/%.o : %.c
$(CC) $(COMMON_FLAGS) $(COMPILE_FLAGS) $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o : %.cpp
$(CPP) $(COMMON_FLAGS) $(COMPILE_FLAGS) $(CPPFLAGS) -c $< -o $@
clean:
-rm $(OBJ)
-rm $(DEPENDS)
-rm $(EXE)
# -rm -r $(OBJDIR)
.PHONY:clean all
-include $(shell mkdir $(OBJDIR) 2>/dev/null) $(wildcard $(OBJDIR)/*.d)
[/text]
一応動作説明をしますと46行目でコンパイルオプションを依存関係ファイルを生成するように追加してあります。そうして生成されたファイルを最終行で読み込んでいます。行頭に-がついているのは、もし読み込めなくてもエラーを無視するためです。特に最初はファイルがありませんのでエラーになっては困る訳です。
ちなみに以前LinuxでもAVR(2)で紹介されていたMakefileからエッセンスを凝縮するとこのようになります。以前紹介されていたMakefileは依存関係ファイルを.depという不可視フォルダに作りますが、見えないものは気持ち悪いのでobjフォルダに作るようにしました。その他にもパソコン用に少し手を加えてあります。