この文章は,龍谷大学理工学部数理情報学科「プログラミングおよび実習II」の履修者を対象に高橋が作成しました.講義では触れられなかったmakeの使い方を補足するためのものです.
C言語ソースの分割コンパイルの仕方をちょっとはかじったことある人を対象にしていますので,「分割コンパイルって何?」という人は,こちらからどうぞ→Docs/ぶんぶん分割コンパイル
「C言語のソースをコンパイルして実行形式のプログラムを作る」というような作業の手順をファイルに書いておけば,人間のかわりにその手順を実行してくれるコマンドです.Cのソースのコンパイルに限らず,何らかのファイルを元に何かを作る作業がコマンドとして与えられるようなものならば,何でも使えます.
一度「原料」(Cの例ならソースファイル),「作りたいもの」(作りたい実行形式),「作り方」(コンパイルのコマンド)の情報をMakefileというファイルに記述しておけば,後はmakeコマンドを実行するだけで「作り方」の手順を自動的に実行してくれるようになります. したがって,人手では手間のかかる「作り方」をコンピュータにまかせて人間は楽をすることができます.
「ソース hoge.c をコンパイルして実行形式 hoge を作る」作業を考えます.普通にコンパイルするなら,
$ cc hoge.c -o hoge
とするでしょう.hoge.cを修正するたびに上の通りキーボードを打つのは面倒くさいので(ほんまか?),この作業を省力化するために make を利用してみます.つまり,この作業の「原料」,「作りたいもの」,「作り方」の情報をファイルに書いておいて,上の通り打つかわりに
$ make
とするだけで済むようにしてみよう,ちうわけです.
この例の場合,「原料」=hoge.c,「作りたいもの」=hoge,「作り方」=上の通り,ということになっています.まずは,これらの情報を,Makefile という名前のファイルに,こんなふうに記述します(ファイルの保存先は,hoge.cがあるのと同じディレクトリにします).
hoge: hoge.c cc hoge.c -o hoge
つまり,
「作りたいもの」: 「原料」 「作り方」
ということです.
!注意! 上記のMakefileの2行目の"cc"が後ろに下がっているのは,その前に「タブ文字」が入っているからです.キーボードの左の方にたぶん「Tab」と書かれたキーがありますが,それを打ちます(一度だけ「Tab」キーを打てば何文字分か空白が入るように見えるでしょう,たぶん).スペースキーを押して「空白文字」を何個か入力するのではありません(「空白文字」だとmakeの実行時にエラーが出ます).
さて,上記のような内容のファイルをMakefileという名前で作ったら,あとは,Makefileを保存したディレクトリ内で
$ make
と打つだけです(補足参照).すると,makeコマンドがMakefileを読んで人間のかわりに「ソース hoge.c をコンパイルして実行形式 hoge を作る」作業を実行し,hogeを作ってくれます.
補足 makeコマンドは,引数なしで実行される(ただmakeとだけ打って実行される)と,カレントディレクトリ(今いるディレクトリ)内からMakefile(またはmakefile)という名前のファイルを探し,それを読んで作業を行うようになっています.もしも別の名前のMakefileを使いたかったら,
$ make -f hogemake
というように -f オプションを使ってファイル名を指定します.この場合,hogemakeという名前のファイルをMakefileと思って作業を行ってくれます.
「分割コンパイルって何?」という人は,こちらからどうぞ→Docs/ぶんぶん分割コンパイル
例として, src1.c と src2.c から hoge という実行形式を作る作業を考えてみます. この場合,makeを使わずに自分でコンパイルをするとしたら,
$ cc -c src1.c
$ cc -c src2.c
$ cc src1.o src2.o -o hoge
という手順をとることになります.したがって, Makefile には,これら三つの手順を記述すればよいわけです.
ここで,1. と 2. はどちらを先にやっても構いませんが,3. の作業はそれらのあとでなければならないことに注意しましょう.ファイルの間の関係を示すと,以下のようになります.
hoge <---------+-- src1.o <----------- src1.c 3. | 1. +-- src2.o <----------- src2.c 2.
矢印の先にあるファイルは,元の方にあるファイルから作られる,という関係にあります.このとき, hoge を作るための Makefileは以下のようになります.
hoge: src1.o src2.o <3. の矢印の関係を表す> cc src1.o src2.o -o hoge <hoge の作り方> src1.o: src1.c <1. の矢印の関係を表す> cc -c src1.c <src1.o の作り方> src2.o: src2.c <2. の矢印の関係を表す> cc -c src2.c <src2.o の作り方>
このような Makefile を用意して make を実行すると,makeコマンドはまず,自分が作らねばならないターゲットが hoge であること,そして,それは上記の矢印で表されているようなファイル群から作られることを知ります.次に make コマンドは,矢印の両側のファイルの作られた時間をチェックし,先の方が古いかまたは存在しなければ,それを作ります.
例えば,一度 make を実行して hoge を作ったあとで,src1.c に修正を加えた場合を考えてみましょう.この場合 make は,
という作業を実行して,めでたく hoge を新しくすることができます.このとき, 2. の矢印の先の src2.o を作り直す必要はないことがわかっているので, make は 2. の作業をさぼっています.
これまでの説明では,最終的に作られる実行形式は一つだけでした.それでは,コンパイルするべきプログラムが複数ある場合にはどうすればよいのでしょうか.
上の hoge に加えて,honya というプログラムも作りたいとします. honya をコンパイルするためには,以下のようなファイルが必要とします.
honya <---------+-- src1.o <----------- src1.c c. | a. +-- funya.o <---------- funya.c b.
ここで,src1.c と src1.o は hoge を作る元になったファイルと同じものです.
このとき, hoge と honya の両方を作ることができる Makefile は,以下のようになります.
hoge: src1.o src2.o cc src1.o src2.o -o hoge honya: src1.o funya.o <c. の矢印の関係を表す> cc src1.o funya.o -o honya <honya の作り方> src1.o: src1.c cc -c src1.c src2.o: src2.c cc -c src2.c funya.o: funya.c <b. の矢印の関係を表す> cc -c funya.c <funya.o の作り方>
新たに追加されたのは,b. と c. の矢印の関係を表す部分です. a. の矢印すなわちsrc1.o の作り方はすでに書いてあるので,同じことをもう一度書く必要はありません.
さて,早速 make してみましょう…と言いたいところですが,実は上の Makefile ではちょっと困ったことになります.実際に試してみればわかるのですが,ただ make と打っても,hoge しか作らないのです. honya は全く作ろうとしません.それというのも,実は make コマンドは,単に make と打って実行された場合,Makefile の先頭に書いてあるもの(上の例では hoge)しか作ろうとしないからなのです.したがって,honya: ...からはじまる二行をこの Makefile の先頭にもって来れば,honya を作ることはできます.しかし,そうすると今度は hoge を作ろうとしなくなります.どっち作るか考えてそのたびに Makefile を書き換える,ちゅうのは面倒くさいですね.
これを解決するための一つの方法は,make コマンドを
$ make
と実行するかわりに,
$ make hoge
あるいは
$ make honya
とする,というものです.このようにすると,Makefile の中の項目の順番にかかわらず,make コマンドは目的のもの(hoge あるいはhonya)の作り方を見つけ出して実行してくれます.
複数の実行プログラムを作れる Makefile の書き方については,以上でO.K. なのですが,「make 何とかなんて打つのはメンドクサイ」「hogeもhonya もいっぺんに作って欲しい」という人は,次のような小技を使ってみましょう.それは,上記の Makefile の先頭に
all: hoge honya
という一行を追加する,というものです(この行が先頭にある限りは,all という名前は適当で構いません).こうしておいて make と打つと,makeコマンドはこの行を見て,「all を作るぞ,材料は hoge と honya や」と思って(?),まずは材料の hoge と honya を作ります.材料がそろったら,次に all を作ろうとするわけですが,上の文を見ればわかるように,all には作り方を表す行がありません.したがって,make コマンドは hoge と honya を作ったら満足して終了する,という具合で,make と打つだけでめでたく両方の実行プログラムができあがる,という寸法です.
工事中