UNIXプログラミング:make入門

home 一覧 掲示板 リンク 検索方法



MAKE入門
Makeの簡単な仕組み
make cleanを用意しておこう
Fortranの場合
サフィックスルールがない場合
ライブラリのリンク
自分でライブラリを作る
※書いてあることの保障はしません。

MAKE入門

プログラミングを初めて暫くすると、ソースファイルが長くなってきたりして使いづらくなってきます。そのような時、たいていは、いくつかのソースに分割して、それらをつなげて(リンクするといいます)使うことが多いのではないでしょうか? しかし、今度はそのうちコンパイルのとき、毎回すごい長さのコマンドを打たなくてはならなくなってしまいます。しかも、いくつもプログラムをつくっていくうちにどのファイルをリンクしなければならないのか、わからなくなったりして大混乱状態に陥り兼ねません。

コンパイルの例
gcc -g -o main.o main.c
gcc -g -o sub.o sub.c
gcc -g -o func.o func.c
gcc -g -o program main.o sub.o  func.o 
こんなことになってきたら、Makeをつかってソースコードの一括管理をしましょう。Makeを使えば、これは、
make program
と打つだけで良く、間違いがありません。

Makeの簡単な仕組み

MakeはディレクトリにあるMakefileというファイルを読みこみます。以下では、Cのコンパイラ、gccを使用することを考えてみます。
さきほどの例をmakeで実行するために、Makefileに以下のように書きこみます。まず、
vi Makefile
でMakefileを編集。viのかわりにemacsでもいいです。中に
CC=gcc
CFLAG=-g
OBJGROUP=main.o sub.o func.o

all: program

program: $(OBJGROUP)
(ここはタブです)$(CC) -o program $(OBJGROUP)

と書きこみます。 注意は(ここはタブです)と書かれたところはTAB一個開けるということです。スペースではだめです。では、このMakefileを説明します。
CC=gcc
のところは、Cのコンパイラをgccに指定しています。
CFLAG=-g
のところは、コンパイルの際のオプション、-gをつけています。
OBJGROUP=main.o sub.o func.o
のところは、例を見返せば分かるように、最後にリンクさせるオブジェクトファイル群です。
all: program
ここは、その下にある「program」をmakeで実行するという意味です。あとで、もう一度解説します。
program: $(OBJGROUP)
(ここはタブです)$(CC) -o program $(OBJGROUP)
これは「program」というのがOBJGROUP=main.o sub.o func.oからできることを指しています。下の段は、今までを考えると、
gcc -o program main.o sub.o func.o
のことであることが分かります。さきほどの例で、
gcc -g -o main.o main.c
gcc -g -o sub.o sub.c
gcc -g -o func.o func.c
の部分はどこへいったのでしょうか? 実は、makeは.oというファイルが.cをコンパイルしてできることを知っているので、何とか.oというのをみたら、自動的にgcc -g -oをやって、hoge.cからhoge.oを作ってくれるのです。これをサフィックスルールといいます。
Makefileが書けたら、
make program
とすれば、さきほどの例は一気にコンパイルされてしまいます。
make
でもいいです。実は省略形、makeは先のall: programに書いたものをやれという意味だったから、省略できたのです。ここに幾つもall: program1 program2 program3のように書いておけば、幾つものコンパイルがmakeだけで出来てしまうことになります。

make cleanを用意しておこう

makeの素晴らしいところは、ソースファイルの変更を判断して、それだけ再コンパイルしてくれることです。すなわち、先ほどの例でいえばfunc.cだけを変更してmakeすれば、func.oだけを再コンパイルして、リンクしてくれるのです。しかし、依存関係の問題などで全部のソースを再コンパイルして欲しい場合、Makefileに以下の行をつけくわえておきます。
clean:
(ここはタブです)\rm *.o

これで、make cleanとするだけで、全てのオブジェクトファイルを消してくれるので、全て再コンパイルされます。毎回、そうする場合は、
all: clean program
としておけばmakeだけで良いです。

Fortranの場合

fortranの場合は、CCがFCに、CFLAGがFFLAGになるだけです。以下にMakefileの例を示しておきます。
FC=f77
FFLAG=-g
OBJGROUP=main.o sub.o func.o

all: program

program: $(OBJGROUP)
(ここはタブです)$(FC) -o program $(OBJGROUP)
clean:
(ここはタブです)\rm *.o

サフィックスルールがない場合

Fortran 90などのマニアックな言語の場合、makeが何からオブジェクトファイルを作るか分からないので、それを指定してやる必要があります。以下はFortran 90をifortでコンパイルする場合です。
FC=ifort
FLAGS=-g
OBJGROUP=main.o inc.o func.o

all: program

program: $(OBJGROUP)
(ここはタブです)$(FC) -o program $(OBJGROUP)
clean:
(ここはタブです)\rm *.o
.SUFFIXES:.f90

最後の行がサフィックスルールを指定している行です

ライブラリ(書庫)のリンク

ライブラリ(書庫)のリンクは以下のような感じです。
FC=ifort
FLAGS=-g
OBJGROUP=main.o inc.o func.o
LIBDIR=/usc/local/lib/plot

all: program

program: $(OBJGROUP)
(ここはタブです)$(FC) -o program $(OBJGROUP) -L$(LIBDIR) -Vaxlib
clean:
(ここはタブです)\rm *.o
.SUFFIXES:.f90

自分でライブラリを作る

ある程度、オブジェクトファイルが集まってきたら、それらをまとめて一つのライブラリ(書庫)を作ってしまうのも、プログラムを整理するための一つの手です。 ライブラリを作成するには、arを用いますが、これもMakeで自動化してしまいましょう。Makefileに以下のようにかきます。
FC=g77
LIB=sub1.o sub2.o sub3.o sub4.o
OBJGROUP=main.o libsub.o

all: libsub.a main

libsub.a: $(LIB)
(ここはタブです)ar rv libsub.a $(LIB)
(ここはタブです)ranlib libsub.a

program: $(OBJGROUP)
(ここはタブです)$(FC) -o program $(OBJGROUP)
clean:
(ここはタブです)\rm -rf *.o *.mod
この例では、sub1.o sub2.o sub3.o sub4.o の四つのオブジェクトファイルからlibsub.aというライブライリをつくり、インデックスをつけています。そして、メインのプログラム(program)でlibsub.aを使っています。まあ、単に複数のファイルを一個にまとめているだけですが、このようにまとめておけば、他のプログラムで転用したいときなども分かり易いと思います。