FrontPage
Makefileによるコンパイル・リンク
書式
(生成するファイル名) : (生成時に依存するファイル名)
<TAB> (ファイルを生成するためのコマンド)
Makefile
target.out : main.o hoge.o
<TAB> gcc -o target main.o hoge.o -lgsl -lgslcblas -lm
main.o : main.c hoge.h
<TAB> gcc -c main.c
main.o : hoge.c hoge.h
<TAB> gcc -c hoge.c
変数を使うと楽
コンパイルオプションの変更とか。
CC = gcc
OPT = -lm -lgsl -lgslcblas
INC = -I/usr/local/include
LIB = -L/usr/local/lib
ALL = main.o hoge.o
program : $(ALL)
<TAB> $(CC) $(LIB) -o $@.out $(ALL) $(OPT)
main.o : main.c hoge.c hoge.h
<TAB> $(CC) $(INC) -c main.c
hoge.o : hoge.c hoge.h
<TAB> $(CC) hoge.h
改行する度に新しい sh が呼ばれる。
同じ sh を使うには、セミコロンで命令を区切る。
> cd hoge; mkdir hage
:= と = は大違い!
:= は、その場で変数を評価するので、$@などを使うことはできない。
= は、実際に使われるまで変数の評価をしないので、$@などを使うことができる。
実は、これは関数を定義していることになる!
> CC_HOGE = $(CC) $(LIB) -o $(DIR_BIN)/$@.out $^ $(SHLIB)
とか、
> TAR_FILE = $(TAR_HEAD)$(shell date `+%y%m%d`).tar.gz
とかやっても、評価は呼び出すときなのでマクロ関数のようにちゃんと動く!
応用
関数的に使う方法
FUNC = @echo $(ARG)
...
ARG := hoge
$(FUNC)
特殊変数(自動変数)
$@ : ターゲット名
$^ : 全ての依存ファイル名
$? : ターゲットより新しい依存ファイル名
$* : ターゲット名のサフィックスを抜いた部分。
シェルコマンドを呼び出して,文字列化する
> ${shell <command> }
Ex. 日付を表示させる
> date :
> @echo ${shell date '+%y%m%d'} # @<command> はコマンドの実行を表示しない。
制御を含む複雑なシェルコマンドの呼び出し
シェル変数の呼び出しは,通常の $hoge から $$hoge に変わる。
NG
echo $hoge
修正版
echo $$hoge
複数行に渡るコマンドは,セミコロンで結んで1行にする。
NG
> for ...
> do ...
> done
修正版
> for ... ; do ... ; done
Ex. testで始まるソースファイルの拡張子を変更する
> for file test*cpp; do mv $$file $${file%.cpp}.ppp; done
別のディレクトリにソースとヘッダを置く
ディレクトリ構造
project/
+ Makefile
+ src/
| + hoge.cpp
+ include/
| + hoge.hpp
+ lib/
+ libhage.so
Makefile
vpath % src include ← (1) src:include のようにコロンでもおk
target : $(OBJ)
$(CC) -o $@.out $(OBJ) -Llib -lhage ← (3) 独自ライブラリには -L も必要。
.cpp.o :
$(CC) -c $< -Iinclude ← (2) こっちは g++ に対する指定。無くてもおk
hoge.cpp (2)で -I を指定した場合
#include "hoge.hpp" ← (2') とにかくファイル名だけでおk
...
hoge.cpp (2)で -I を指定しない場合
#include "../include/hoge.hpp" ← (2') パスを入れる。
...
(3') 注. 独自の共有ライブラリディレクトリを用意した場合
シェルから
> ./a.out
で実行しようとしても、
> ./a.out: error while loading shared libraries: libfonc.so: cannot open shared object file: No such file or directory
と出てしまって、このままでは実行できない。
つまり、シェルに対してもパスを通してやる必要がある。
> export LD_LIBRARY_PATH="lib"
依存関係の自動生成
> depend : $(ALL)
> [TAB] @rm depend.inc
> [TAB] @for file in $^; do \
> [TAB] cpp -MM $(INC) $$file \
> [TAB] | sed "s/[_/a-zA-Z0-9]*.cpp//g" \
> [TAB] >> depend.inc; \
> [TAB] done
得られた depend.inc を、Makefileの末尾で
> -include depend.inc
すればおk
ディレクトリの一覧を取得
> HOGE := $(shell for file in *; do if [ -d $$file ]; then ls -d $$file; fi; done )
最終更新:2010年06月06日 03:37