VirtualBox 5
 CentOS 7
 GNOME Desktop

■Makefile Prev Top Next
関連ページ:

Linux上でC言語を使用して(おもに組み込み系)開発を行う場合、どうもIDEは使用せずテキストエディッタを使用するのが一般的らしい。
ということで自前でコンパイルを行う方法を調べた。

まず Makefile とは何かって話だが、大規模なプログラムを作成していると、コマンドでコンパイルするのが面倒である。
また、一部のソースファイルを書き換えだけなのに全部をコンパイルし直すのは時間の無駄である。
これらの問題を解決する目的で使用するのが Makefile ファイルである。


■Makefileなしでコンパイルと実行ファイル作成

1.任意のディレクトリに移動し、下記コマンドを実行してソースファイルを作成する。
$ touch sample01.c

2.下記のコマンドを実行してソースファイルを編集するエディッタを起動する。
&をつけないとエディタ起動中はシェルでロックがかかるので & つけたほうがよい。
$ gedit sample01.c &

3.次のようにコーディング。

// sample01.c

#include <stdio.h>

int main(){
   printf("Hallo World\n");
   
   return 0;
}
4.コンパイル、実行ファイルの作成を行う。
$ cc sample01.c -o sample01

5.最後に実行する。
$ ./sample01


■Makefileを使用してコンパイルと実行ファイル作成

1.Makefileを作成する。なお慣例としてMakefileの先頭一文字は大文字らしい。
$ touch Makefile

2.geditで開く。なおエディッタを既に起動中の場合は & は不要。
$ gedit Makefile

3.次のようにコーディング。

# Makefile

sample01: sample01.c
	cc sample01.c -o sample01

4.Makefileを使用してコンパイル、実行ファイルの作成を行う。
パラメータである sample01 はターゲット名である。
※sample01.cが変更されていない場合はコンパイルされないので、rm sample01 を使用して実行ファイルを削除するか
touch -m sample01.c を使用してソースファイルの最終更新日時を更新する。
$ make sample01

5.最後に実行する。
$ ./sample01

ここで再度 make sample01 コマンドを実行してみると、
make: 'sample01' は更新済です
と表示されてコンパイルされないことが確認できる。


■Makefileについて

sample01: sample01.c
最初の1行目はターゲット名: 依存ファイル名となっている。
ターゲット名: make コマンド実行時に指定する名称。一般的に作成されるファイルのファイル名にする。(別名にすることもできるらしい)
依存ファイル名:指定されたファイルのうち一つでも変更があった場合、ccコマンドを実行する。

なお make コマンド実行時にターゲット名を省略した場合は、Makefile上で最初に記述されたターゲットのccコマンドが実行される。

	cc sample01.c -o sample01
2行目には実行するccコマンドを記述する。インデントはtabであることに注意する。


■複数のソースファイルを使用してコンパイル、実行ファイルの作成

1.下記コマンドを実行してソースファイルを作成する。
$ touch sample02.c isGuusuu.c

2.geditでsample02.cファイルを開く。
$ gedit sample02.c

3.次のようにコーディング。

// sample02.c

#include <stdio.h>

int main(){
   printf("%d\n", isGuusuu(20));
   
   return 0;
}
4.geditでisGuusuu.cファイルを開く。
$ gedit isGuusuu.c

5.次のようにコーディング。

// isGuusuu.c

int isGuusuu(int m){
   return m % 2 == 0;
}
6.Makefileを下記のように修正する。
# Makefile

sample02: sample02.c isGuusuu.c
	cc sample02.c isGuusuu.c -o sample02

7.コンパイルと実行ファイルの作成
$ make

8.最後に実行する。
$ ./sample02

しかしこの場合は、依存ファイルに指定されたソースファイルのうち一つでも変更された場合、
すべてのソースファイルがコンパイルされてしまうため無駄な処理が発生する。


■分割コンパイル

1.Makefileを下記のように修正する。

# Makefile

sample02: sample02.o isGuusuu.o
	cc -o sample02 sample02.o isGuusuu.o

sample02.o: sample02.c
	cc -c sample02.c -o sample02.o

isGuusuu.o: isGuusuu.c
	cc -c isGuusuu.c -o isGuusuu.o

2.コンパイルとオブジェクトファイルの作成とリンケージと実行ファイルの作成
$ make

各ソースファイルのオブジェクトファイルと実行ファイルが作成されたことが確認できる。
これで修正されていないソースファイルについては何も行われなくなる。


■分割コンパイル用のMakefileについて

sample02: sample02.o isGuusuu.o
	cc -o sample02 sample02.o isGuusuu.o
最初にオブジェクトファイルのリンケージを設定する。

sample02.o: sample02.c
	cc -c sample02.c -o sample02.o

isGuusuu.o: isGuusuu.c
	cc -c isGuusuu.c -o isGuusuu.o
次に各ソースファイルごとに実行するccコマンドを記述する。

ここで注意が必要なのはソースファイル名に -c オプションを指定していることである。
これはソースファイルごとに .o ファイルを作成することを指定するためのオプションである。


■オブジェクトファイルと実行ファイルの削除

オブジェクトファイルと実行ファイルを削除する方法を示す。

1.Makefileを下記のように修正する。

# Makefile

sample02: sample02.o isGuusuu.o
	cc -o sample02 sample02.o isGuusuu.o

sample02.o: sample02.c
	cc -c sample02.c -o sample02.o

isGuusuu.o: isGuusuu.c
	cc -c isGuusuu.c -o isGuusuu.o

clean:
	rm -f sample02 sample02.o isGuusuu.o

2.実行する。
$ make clean

ls コマンドを実行すると、 sample02、sample02.o、isGuusuu.o ファイルが削除されたことが確認できる。

ここで clean というファイルを作成して、再度 make clean を実行するとcleanが行われない。
これは依存ファイルを指定していないため、cleanファイルは常に最新であると判断されてコマンドの実行を行わないためである。

これを回避するために Makefile を下記のように修正する。

# Makefile

sample02: sample02.o isGuusuu.o
	cc -o sample02 sample02.o isGuusuu.o

sample02.o: sample02.c
	cc -c sample02.c -o sample02.o

isGuusuu.o: isGuusuu.c
	cc -c isGuusuu.c -o isGuusuu.o

.PHONY: clean
clean:
	rm -f sample02 sample02.o isGuusuu.o
これにより clean ファイルの有無に関係なく常にコマンドを実行するようになる。


■オブジェクトファイル作成時のコマンドを共通化する

上記の方法の場合、ソースファイルを追加するたびにオブジェクトファイル作成用のコマンド行を追加する必要があり面倒である。
それを共通化する。

1.Makefileを下記のように修正する。

# Makefile

sample02: sample02.o isGuusuu.o
	cc -o sample02 sample02.o isGuusuu.o

%o: %c
	cc -c $< -o $@

.PHONY: clean
clean:
	rm -f sample02 sample02.o isGuusuu.o
これはサフィックスルールに従ってオブジェクトファイルとソースファイルとが関連づけられている。
つまり拡張子を除くファイル名が同一のものをそれぞれ組み合わせている。


■実行ファイル名とオブジェクトファイル名をマクロ定義を使用して一か所にまとめる

リンケージの記述を見ると実行ファイル名とオブジェクトファイル名の記述が2か所あるため、
ソースファイルを追加した時の修正箇所が2か所必要となる。
マクロ定義を使用してこれを一か所にまとめる。

1.Makefileを下記のように修正する。

# Makefile

PROGRAM = sample02
OBJS = sample02.o isGuusuu.o

$(PROGRAM): $(OBJS)
	cc -o $(PROGRAM) $(OBJS)

%o: %c
	cc -c $< -o $@

.PHONY: clean
clean:
	rm -f sample02 sample02.o isGuusuu.o
特に説明するところはないと思う。


Prev Top Next
inserted by FC2 system