using make command for debug,test and coverage
- 'make' build target normally
- 'make debug' build target with debug option and run debugger(gdb -tui)
- 'make test' build unit test and run
- 'make gcov' build unit test and run get coverage using gcov
#include <stdio.h> | |
#include "sub.h" | |
static int func1(int parm) | |
{ | |
if (parm >= 0) | |
return 1; | |
return 0; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
printf("Hello World!\n"); | |
printf("arg test %d\n", func1(argc)); | |
return 0; | |
} |
#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 |
#ifndef __SUB_H__ | |
#define __SUB_H__ | |
// for test nothing define | |
inline int sub1(void) | |
{ | |
return 0; | |
} | |
#endif |
#include <stdio.h> | |
#include <dlfcn.h> | |
#include <stdbool.h> | |
/* test function prototype */ | |
typedef bool (*Test)(void); | |
#define main __original_main | |
#include "main.c" | |
#undef main | |
#define UT_ASSERT(f) {if (!(f)) {printf("%s:%u: '%s' is NG\n", __FILE__,__LINE__,#f);return false;}} | |
bool test001(void) | |
{ | |
UT_ASSERT(func1(1) == 1); | |
return true; | |
} | |
bool test002(void) | |
{ | |
UT_ASSERT(func1(0) == 1); | |
return true; | |
} | |
bool test003(void) | |
{ | |
UT_ASSERT(func1(-1) == 0); | |
return true; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
Test t; | |
bool ret; | |
int i; | |
char func_name[100]; | |
unsigned int count_ok = 0, count = 0; | |
for (i = 0; i < 100; i++) { | |
sprintf(func_name, "test%03d", i); | |
t = (Test) dlsym(RTLD_DEFAULT, func_name); | |
if (t != NULL) { | |
count++; | |
ret = (*t)(); | |
if (ret) | |
count_ok++; | |
else | |
printf("test NG %s\n", func_name); | |
} | |
} | |
printf("result %s %u/%u \n", __FILE__, count_ok, count); | |
} | |
#include <stdio.h> | |
int main(int argc, char *argv[]) | |
{ | |
printf("result %s %u/%u \n", __FILE__, 0, 0); | |
} | |