VirtualBox 5 CentOS 7 GNOME Desktop |
■Makefile | Prev Top Next | |
|
Linux上でC言語を使用して(おもに組み込み系)開発を行う場合、どうもIDEは使用せずテキストエディッタを使用するのが一般的らしい。
ということで自前でコンパイルを行う方法を調べた。
まず 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.コンパイル、実行ファイルの作成を行う。
5.最後に実行する。
$ ./sample01
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' は更新済です
と表示されてコンパイルされないことが確認できる。
sample01: sample01.c最初の1行目はターゲット名: 依存ファイル名となっている。
なお make コマンド実行時にターゲット名を省略した場合は、Makefile上で最初に記述されたターゲットのccコマンドが実行される。
cc sample01.c -o sample012行目には実行する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ファイルを開く。
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
各ソースファイルのオブジェクトファイルと実行ファイルが作成されたことが確認できる。
これで修正されていないソースファイルについては何も行われなくなる。
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特に説明するところはないと思う。