はじめに
今回の記事は、テーマにもある通りC言語で作成したプログラムをコンパイル、ビルドする時に使用する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の中身に何を記載するのかというと、利用する各ファイルの関係性やファイルを更新するためのルール的なものを記載するものと書かれています。
以上のことからMakefileについて簡単にまとめると
Makefileを使ってC言語のプログラムをコンパイル&ビルド
前項でMakefileが何かというのは説明しました。
なので、ここからはより具体的にどうやって使うのかという部分に入っていきます。
ここからはC言語のプログラムをgccを使ってコンパイル&ビルドする時のMakefileについてまとめていきます。
このときにMakefileを書く際、私が毎回あれ?これどうやって書くんだっけ?ってなって調べるのがめんどくさいのが理由です。
想定しているディレクトリ構造
まずは、今回想定しているディレクトリ構造(ツリー構造)から。
中間ファイルや実行ファイルの出力先やソースコードの置き場所などなど以下の画像のようなものを想定しています。
次からいくつかの項目に分けてMakefileの書き方を確認していきます。
まずは簡単にmain.cファイルだけで考える
まずは、何も考えずにmain.cファイルだけをコンパイル&ビルドする方法から。
なるべく不要なものを記述しないようにします。
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)
基本的な部分については触れませんが、記号であったり関数などについては少しだけ解説を加えておきます。
複数ファイルやヘッダーファイルを含めるパターン
開発の規模が大きくなるにつれてソースファイルもmain.cだけとはいかなくなりますね。
処理毎にファイルを生成したりヘッダーファイルを用意したりライブラリを使ったりもしますよね。
次は、それらを考慮したMakefileです。
以下では、main.cの他に四則演算関数を記載したarithmeticOperations.cを用意しました。
それと追加でincludeディレクトリにarithmeticOperations.hを追加しました。
それでも追記は1箇所です。ファイルを追加したのでその追加したファイルを記載するだけです。
CC = gcc
CFLAGS = -g -Wall -O2
INCLUDE = -I ../include
TARGET = ../bin/hello
OBJDIR = ../obj
#変更点
# - SOURCE = main.c
# + SOURCE = main.c arithmeticOperations.c
SOURCE = main.c arithmeticOperations.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)
ライブラリをリンクする方法
開発を行っていれば、ライブラリを使用することがあるはずです。
例えば、数値演算を使用したいのであればmathライブラリがありますね。
mathライブラリを使用するためには、
・ソースコード内に include <math.h> を追加
・コンパイルする時に -lm をリンクする必要があります。
1番目はソースコードに記載しますが、2番目はMakefileに記述する必要があります。
その場合の変更点は以下です。
CC = gcc
CFLAGS = -g -Wall -O2
INCLUDE = -I ../include
TARGET = ../bin/hello
OBJDIR = ../obj
#追加
# + LIBS = -lm
LIBS = -lm
SOURCE = main.c arithmeticOperations.c
OBJECTS = $(addprefix $(OBJDIR)/, $(SOURCE:.c=.o))
#変更点 リンクオプションを追加
# - $(CC) $^ -o $(TARGET)
# + $(CC) $^ -o $(TARGET) $(LIBS)
$(TARGET) : $(OBJECTS)
mkdir -p $(dir $@)
$(CC) $^ -o $(TARGET) $(LIBS)
$(OBJDIR)/%.o : %.c
mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $<
all : $(TARGET)
clean :
rm -rf $(OBJECTS) $(TARGET)
もちろんリンクするライブライが変わるときにはそれに置換した対応が必要になります。
Makefileでマクロを定義する方法
次は、マクロをMakefile内で定義することも可能ですのでそれについてもメモしておきます。
gccコンパイラではDオプションを利用することでマクロ定義を行うことができます。
オブジェクトファイル生成時にDオプションを利用してください。
CC = gcc
CFLAGS = -g -Wall -O2
INCLUDE = -I ../include
TARGET = ../bin/hello
OBJDIR = ../obj
LIBS = -lm
#追加 -Dオプションでマクロ定義
# + MACRO = -DDEV
MACRO = -DDEV
SOURCE = main.c arithmeticOperations.c
OBJECTS = $(addprefix $(OBJDIR)/, $(SOURCE:.c=.o))
$(TARGET) : $(OBJECTS)
mkdir -p $(dir $@)
$(CC) $^ -o $(TARGET) $(LIBS)
#変更点
# - $(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $<
# + $(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $< $(MACRO)
$(OBJDIR)/%.o : %.c
mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $< $(MACRO)
all : $(TARGET)
clean :
rm -rf $(OBJECTS) $(TARGET)
まとめ
これで自分でMakefileを記述するときに毎度これどうやって書くんだっけな~で迷わなくて済みます。
めでたしめでたし。
参考
ここまでの内容を調べるときに参考にしたものです。
コメント