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
■ やること
- アイスを食べる
- 請求書