2009年06月21日(日) [長年日記]
■ [c++][c][dev] C++用Makefileのサンプル (2)
ちょっと前にMakefileをメモしたけど、文字コードを変換してからビルドしたいケースもあるので、それに対応したMakefileも作ってみた。
- 文字コードをCP932からUTF-8へ、改行コードをCRLFからLFへ変換している。変換にはNKFを使用。
- 何もしないとコンパイルエラー時に変換後のソースファイルパスが表示されるが、それだとVimからmakeを実行したときに変換後のソースにジャンプしてしまい不便。なので、sedを使ってソースファイルパスを変換前のものに置換している。更に念のため変換後のソースから書込権限を除いておく。
- sedで上の置換をする際にパイプを使っているが、そうするとコンパイルエラーになっても終了コードがエラーにならなくなり困る。そこでBASHのpipefailオプションを使って終了コードがエラーになるようにした。
# GNU make用です build_base_dir = build program = $(build_base_dir)/sample # ここにビルド対象とするディレクトリを全て書く src_dirs = src src_dirs += src/aaa src_dirs += src/aaa/ccc src_dirs += src/bbb SHELL=/bin/bash CPPFLAGS = -I $(build_base_dir)/src CXXFLAGS = -Wall -g headers = $(wildcard $(addsuffix /*.h, $(src_dirs))) sources = $(wildcard $(addsuffix /*.cpp, $(src_dirs))) headers_utf8 = $(headers:%.h=$(build_base_dir)/%.h) sources_utf8 = $(sources:%.cpp=$(build_base_dir)/%.cpp) objects = $(sources_utf8:%.cpp=%.o) depends = $(addsuffix .d, $(objects)) build_dirs = $(addprefix $(build_base_dir)/, $(src_dirs)) .PHONY: all all: $(build_dirs) $(headers_utf8) $(sources_utf8) $(program) .PHONY: clean clean: rm -rf $(build_base_dir) $(program): $(objects) $(CXX) $(LDFLAGS) -o $@ $^ %.o: %.cpp set -o pipefail; $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< 2>&1 \ | sed --unbuffered 's|$(build_base_dir)/||' set -o pipefail; $(CXX) $(CPPFLAGS) -MM $< \ | sed 's|^\([^\.]*\)\.o|$(@D)/\1\.o|' > $@.d $(build_base_dir)/%.cpp: %.cpp rm -f $@ nkf --ic=CP932 --oc=UTF-8 -Lu -d $< > $@ chmod a-w $@ $(build_base_dir)/%.h: %.h rm -f $@ nkf --ic=CP932 --oc=UTF-8 -Lu -d $< > $@ chmod a-w $@ $(build_dirs): mkdir -p $@ -include $(depends)
先日の例と同じ構成のソースファイルをビルドすると、
.
|-- Makefile
|-- build
| |-- sample
| `-- src
| |-- aaa
| | |-- a.cpp
| | |-- a.h
| | |-- a.o
| | |-- a.o.d
| | `-- ccc
| | |-- c.cpp
| | |-- c.h
| | |-- c.o
| | `-- c.o.d
| |-- bbb
| | |-- b.cpp
| | |-- b.h
| | |-- b.o
| | `-- b.o.d
| |-- main.cpp
| |-- main.o
| `-- main.o.d
`-- src
|-- aaa
| |-- a.cpp
| |-- a.h
| `-- ccc
| |-- c.cpp
| `-- c.h
|-- bbb
| |-- b.cpp
| `-- b.h
`-- main.cpp
のようになる。buildの下にあるのが変換後のソースファイル。
手元の環境で実行すると次のように出力された。
mkdir -p build/src
mkdir -p build/src/aaa
mkdir -p build/src/aaa/ccc
mkdir -p build/src/bbb
rm -f build/src/aaa/a.h
nkf --ic=CP932 --oc=UTF-8 -Lu -d src/aaa/a.h > build/src/aaa/a.h
chmod a-w build/src/aaa/a.h
rm -f build/src/aaa/ccc/c.h
nkf --ic=CP932 --oc=UTF-8 -Lu -d src/aaa/ccc/c.h > build/src/aaa/ccc/c.h
chmod a-w build/src/aaa/ccc/c.h
rm -f build/src/bbb/b.h
nkf --ic=CP932 --oc=UTF-8 -Lu -d src/bbb/b.h > build/src/bbb/b.h
chmod a-w build/src/bbb/b.h
rm -f build/src/main.cpp
nkf --ic=CP932 --oc=UTF-8 -Lu -d src/main.cpp > build/src/main.cpp
chmod a-w build/src/main.cpp
rm -f build/src/aaa/a.cpp
nkf --ic=CP932 --oc=UTF-8 -Lu -d src/aaa/a.cpp > build/src/aaa/a.cpp
chmod a-w build/src/aaa/a.cpp
rm -f build/src/aaa/ccc/c.cpp
nkf --ic=CP932 --oc=UTF-8 -Lu -d src/aaa/ccc/c.cpp > build/src/aaa/ccc/c.cpp
chmod a-w build/src/aaa/ccc/c.cpp
rm -f build/src/bbb/b.cpp
nkf --ic=CP932 --oc=UTF-8 -Lu -d src/bbb/b.cpp > build/src/bbb/b.cpp
chmod a-w build/src/bbb/b.cpp
set -o pipefail; g++ -I build/src -Wall -g -c -o build/src/main.o build/src/main.cpp 2>&1 \
| sed --unbuffered 's|build/||'
set -o pipefail; g++ -I build/src -MM build/src/main.cpp \
| sed 's|^\([^\.]*\)\.o|build/src/\1\.o|' > build/src/main.o.d
set -o pipefail; g++ -I build/src -Wall -g -c -o build/src/aaa/a.o build/src/aaa/a.cpp 2>&1 \
| sed --unbuffered 's|build/||'
set -o pipefail; g++ -I build/src -MM build/src/aaa/a.cpp \
| sed 's|^\([^\.]*\)\.o|build/src/aaa/\1\.o|' > build/src/aaa/a.o.d
set -o pipefail; g++ -I build/src -Wall -g -c -o build/src/aaa/ccc/c.o build/src/aaa/ccc/c.cpp 2>&1 \
| sed --unbuffered 's|build/||'
set -o pipefail; g++ -I build/src -MM build/src/aaa/ccc/c.cpp \
| sed 's|^\([^\.]*\)\.o|build/src/aaa/ccc/\1\.o|' > build/src/aaa/ccc/c.o.d
set -o pipefail; g++ -I build/src -Wall -g -c -o build/src/bbb/b.o build/src/bbb/b.cpp 2>&1 \
| sed --unbuffered 's|build/||'
set -o pipefail; g++ -I build/src -MM build/src/bbb/b.cpp \
| sed 's|^\([^\.]*\)\.o|build/src/bbb/\1\.o|' > build/src/bbb/b.o.d
g++ -o build/sample build/src/main.o build/src/aaa/a.o build/src/aaa/ccc/c.o build/src/bbb/b.o
■ やること
- アイスを食べる
- 請求書
[ツッコミを入れる]