Skip to content

Instantly share code, notes, and snippets.

@tksmiura
Last active August 12, 2017 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tksmiura/fc273ba726ed380dcd5bf6488c24c553 to your computer and use it in GitHub Desktop.
Save tksmiura/fc273ba726ed380dcd5bf6488c24c553 to your computer and use it in GitHub Desktop.
002_simple_project_c.md

Simple project for C

aim

using make command for debug,test and coverage

usage

  • '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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment