シンプルなC言語のプロジェクトを作ってみる
目的は、とりあえず、何をするにもmake xxxで済ませたい。
http://qiita.com/tksmiura/items/0a77e5c301532ae30c9a
の続き
http://qiita.com/szkny/items/07b4c93702b3f8090fa3
あたりを参考にして
ut_*.c という名前のソースをテストプログラムとしてビルドして実行する。(make のwildcardを利用するのでファイルを増やしてもMakefileの変更は不要)
make testとかmake gcovとか実行するビルドして、テストやカバレッジを取ってくれる。
% make test
cc -o ut_main ut_main.c
cc -o ut_sub ut_sub.c
result ut_main.c 3/3
result ut_sub.c 0/0
make debugと実行するとデバッグビルドしてgdbの起動まで行う。
http://www.ne.jp/asahi/hishidama/home/tech/unix/cmd/make2.html
あたりを参照
プロジェクト全体は、
https://gist.github.com/tksmiura/fc273ba726ed380dcd5bf6488c24c553
にあげておきます。
#TARGETS
PROGRAM = main
DEBUG_TARGET = main_debug
HEADERS = $(wildcard *.h)
SRCS = main.c
TEST_SRCS = $(wildcard ut_*.c)
TESTS = $(basename $(TEST_SRCS))
GCOV_TESTS = $(TEST_SRCS:.c=_gcov)
# ENVIRONMENT
CC ?= gcc
CFLAGS ?= -Wall -O2
DEBUG_OPTION ?= -O0 -g
DEBUGGER = gdb -tui
GCOV = gcov
# suffixes
.SUFFIXES: .c .o .debug_o
#default target
all: $(PROGRAM)
#
# target
#
# サフィックスルール
.c.o:
$(CC) $(CFLAGS) -c $<
#依存関係
define MAKEOBJECTS
$(1:.c=.o): $(1) $(HEADERS)
endef
$(foreach VAR,$(SRCS),$(eval $(call MAKEOBJECTS,$(VAR))))
$(PROGRAM): $(SRCS:.c=.o)
$(CC) -o $(PROGRAM) $^
#
# debug(gdb)
#
.c.debug_o:
$(CC) $(CFLAGS) $(DEBUG_OPTION) -o $@ -c $<
#依存関係
define MAKEDEBUG
$(1:.c=.debug_o): $(1) $(HEADERS)
endef
$(foreach VAR,$(SRCS),$(eval $(call MAKEDEBUG,$(VAR))))
$(DEBUG_TARGET): $(SRCS:.c=.debug_o)
$(CC) -o $@ $^
.PHONY: debug
debug: $(DEBUG_TARGET)
$(DEBUGGER) $^
#
# unit test
#
# targets for test
define MAKETARGETS
$(1): $(1).c $(HEADERS)
$(CC) -o $(1) $(1).c
endef
$(foreach VAR,$(TESTS),$(eval $(call MAKETARGETS,$(VAR))))
.PHONY: test
test: $(TESTS)
@for test in $(TESTS) ; do \
./$$test ;\
done
#
# gcov
#
# target gov (unit test only)
define MAKETARGETS_GCOV
$(1)_gcov: $(1).c
$(CC) -o $(1)_gcov --coverage $(1).c
endef
$(foreach VAR,$(TESTS),$(eval $(call MAKETARGETS_GCOV,$(VAR))))
.PHONY: gcov
gcov: $(GCOV_TESTS)
@for test in $(GCOV_TESTS) ; do \
./$$test ;\
done
$(GCOV) -b $(TEST_SRCS:.c=.gcda)
#
# clean
#
.PHONY: clean
clean:
$(RM) $(PROGRAM) $(DEBUG_TARGET) $(TESTS) $(GCOV_TESTS)
$(RM) $(SRCS:.c=.o) $(SRCS:.c=.debug_o)
$(RM) *.gcda *.gcno *.gcov
全体的に手抜きなので、ヘッダはwildcardで*.hを検索し、
HEADERS = $(wildcard *.h)
どれかが変更されれば、リビルドされるように設定。
(defineでルールを定義してforeachで展開)
#依存関係
define MAKEOBJECTS
$(1:.c=.o): $(1) $(HEADERS)
endef
$(foreach VAR,$(SRCS),$(eval $(call MAKEOBJECTS,(VAR))))
実際、#includeしてない場合も考えられますが、いちいち依存関係を記述する手間を省くため。こうしています。
デバッグ用のオブジェクトを*.debug_oとしているは自分でもどうかと思っていますが、フォルダ分けとかも面倒な感じなのでこうしています。