忍者ブログ

[PR]

2024年05月04日 ()
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

Makefile: build all ".c"

2008年10月13日 (c)

数行の小さいテストプログラムのためいちいちビルドするのが面倒だなと・・
カレントディレクトリの全てのソースファイルを一気にビルドできればなと・・
ネットで調べながら試行錯誤の結果・・・

source(Makefile)

# Makefile
# build all ".c" file in current directory

CC=gcc
SRCS=$(wildcard *.c)
OBJS=$(patsubst %.c,%.o,$(SRCS));
	
all: $(OBJS)
	for i in $(OBJS) \
	do \
		EXE=`basename $$i .o`; \
		$(CC) -o $$EXE $$i; \
	done

.c.o:
	$(CC) -c $<

clean:
	rm -f $(OBJS)

できた.動作確認.

sample execution

% ls 
Makefile  a.c  b.c  c.c
% make
gcc -c a.c
gcc -c b.c
gcc -c c.c
for i in a.o b.o c.o; \
	do \
		EXE=`basename $i .o`; \
		gcc -o $EXE $i; \
	done
% ls -l
total 92K
-rw-r--r-- 1 aki  256 Oct 12 03:56 Makefile
-rwxr-xr-x 1 aki 4713 Oct 13 00:46 a
-rw-r--r-- 1 aki   85 Oct 12 03:48 a.c
-rw-r--r-- 1 aki  860 Oct 13 00:46 a.o
-rwxr-xr-x 1 aki 4713 Oct 13 00:46 b
-rw-r--r-- 1 aki   85 Oct 12 02:19 b.c
-rw-r--r-- 1 aki  860 Oct 13 00:46 b.o
-rwxr-xr-x 1 aki 4713 Oct 13 00:46 c
-rw-r--r-- 1 aki   85 Oct 12 02:20 c.c
-rw-r--r-- 1 aki  860 Oct 13 00:46 c.o

完璧.が,もう少しクールなMakefileがあるかも.
今回はこれで満足

PR

Makefile

2008年09月08日 (c)

Makefile概要

Cなどでプログラムを作るとき1つのファイルで処理が終わってしまうような簡単なプログラムなら,

% ls
source.c
% gcc source.c
% ls
a.out  source.c

のようにそのソースをコンパイル&リンクして実行ファイルを得れば良いが,数10,数100のファイルなどからなる大きなプログラムになると

% ls
死ぬほど多いソースファイル
% gcc 死ぬほど多いソースファイル

などとやっていては1回の実行なら良いが,バグが見つかり1つのファイルのみを修正してコンパイル&リンクをしようとしたとき,再び全てのファイルについてコンパイル&リンクをしなくてはならず時間効率が悪い.そこでMakefilemakeコマンドを用いると,修正したファイルのみをコンパイルし,リンクを行うということが可能である.コンパイルの時間が短縮できるとともにコマンドをいちいち打つ必要がないため手間も省け,効率的である.

まずは基本

同じディレクトリ内に以下のような3つのファイルがある.(Makefile, hello.c, helloworld.c)
このうちプログラムのソースはhello.chelloworld.cこの2つのファイルをMakefilemakeコマンドを使ってコンパイル,リンクする.

source(Makefile)

# Makefile
helloworld: helloworld.o hello.o
    gcc -o helloworld helloworld.o hello.o

helloworld.o: helloworld.c
    gcc -c helloworld.c

hello.o: hello.c
    gcc -c hello.c

clean:
    rm -f helloworld.o hello.o

source(hello.c)

#include <stdio.h>

void hello(void)
{
    printf("hello world\n");
}

source(helloworld.c)

#include <stdio.h>

int main(int argc,char *argv[])
{
    void hello(void);

    hello();

    return 0;
}

ここで以下のようにコマンドを打つ

% ls
Makefile  hello.c  helloworld.c
% make
gcc -c helloworld.c
gcc -c hello.c
gcc -o helloworld helloworld.o hello.o
% ls
Makefile  hello.c  hello.o  helloworld  helloworld.c  helloworld.o
% ./helloworld 
hello world

makeコマンドを実行すると

gcc -c helloworld.c
gcc -c hello.c
gcc -o helloworld helloworld.o hello.o

の3コマンドが実行されていることがわかる.まず,上2つでコンパイルを行い,オブジェクトファイルを作成,その後リンクしhelloworldという実行ファイルを生成する.

この状態でもう一度makeする.

% make
make: `helloworld' は更新済みです

既にhelloworldは最新版でありコンパイル&リンクは必要ないので何も実行されない.
次にMakefileの最後の2行

clean:
    rm -f helloworld.o hello.o

これはmakeコマンドの引数に指定すると,指定されたコマンドを実行すると言う意味である.
この場合

rm -f helloworld.o hello.o

が実行され,helloworld.oとhello.oというリンクに使われたオブジェクトファイルが2つ削除される.

% ls   
Makefile  hello.c  hello.o  helloworld  helloworld.c  helloworld.o
% make clean
rm -f helloworld.o hello.o
% ls
Makefile  hello.c  helloworld  helloworld.c
% 

マクロ,サフィックスルール

Makefileを以下のように修正する.helloworld.chello.cは使いまわしする.

source(Makefile)

# Makefile

CC=gcc
OBJS=helloworld.o hello.o

helloworld: helloworld.o hello.o
    $(CC) -o $@ $(OBJS)

.c.o:
    gcc -c $<

clean:
    rm -f $(OBJS)

3,4行名

CC=gcc
OBJS=helloworld.o hello.o

は代入文でCCgccを,OBJShelloworld.o hello.oを代入することを表す.
代入された変数を参照するには$(変数名)のようにする.
この場合,7行目

$(CC) -o $@ $(OBJS)

$(CC)gccに,$(OBJS)helloworld.o hello.oに置き換えられる.
同じく7行目$@は現在のターゲットのフルネームを取得する.ここではhelloworldに置き換えられる.つまり7行目

$(CC) -o $@ $(OBJS)

は,

gcc -o helloworld helloworld.o hello.o

に置き換えられる.

次に9,10行目

.c.o:
    gcc -c $<

は,.cのファイルを.oファイルに変換するということを表す.
$<はターゲットに依存している単一のファイルをに置き換えられる.この場合,hello.oが依存されているときは,

gcc -c hello.c

に置き換えられ,helloworld.oが依存されているときは,

gcc -c helloworld.c

に置き換えられる.以上を踏まえてmakeコマンドを実行する.

% rm helloworld
% ls
Makefile  hello.c  helloworld.c
% make
gcc -c helloworld.c
gcc -c hello.c
gcc -o helloworld helloworld.o hello.o
% ls
Makefile  hello.c  hello.o  helloworld  helloworld.c  helloworld.o
% ./helloworld 
hello world
% make clean 
rm -f helloworld.o hello.o
% ls
Makefile  hello.c  helloworld  helloworld.c
% 

上記のmakeコマンドと同じ結果を得られた.
このようにマクロ,サフィックスルールを用いることによりMakefileの汎用性を高めることができる.

Makefileについてはこれくらい知っておけば大体大丈夫だと思う.

 | HOME |