CROSS_COMPILE ?= TARGET_FILE ?= i2c_bb STATIC_LIB_FILE ?= lib$(TARGET_FILE).a DYNAMIC_LIB_FILE ?= lib$(TARGET_FILE).so CC = $(CROSS_COMPILE)gcc CPP = $(CROSS_COMPILE)cpp CHECK = cppcheck LCOV = lcov GENHTML = genhtml SRC_DIR = src OBJ_DIR = obj LIB_DIR = lib BIN_DIR = bin COVERAGE_DIR = coverage UNIT_TEST_SRC_DIR = test/unit UNIT_TEST_OBJ_DIR = $(OBJ_DIR)/$(UNIT_TEST_SRC_DIR) PREFIX ?= /usr LIB_INSTALL_DIR ?= $(PREFIX)/lib/$(TARGET_FILE) INC_INSTALL_DIR ?= $(PREFIX)/include/lib$(TARGET_FILE) INCLUDES := inc INCLUDES += $(PREFIX)/include/ INCLUDES += $(EXTRA_INC) ifneq "$(findstring $(MAKECMDGOALS), build_unit_test exec_unit_test coverage)" "" INCLUDES += test/inc C_FLAGS += --coverage L_FLAGS += --coverage endif L_FLAGS += -shared -Wl,-soname,$(notdir $(DYNAMIC_LIB)) C_FLAGS += -fpic C_FLAGS += -O0 -g -Wall -Wextra -Werror CPP_FLAGS += $(addprefix -I, $(INCLUDES)) CHECK_FLAGS = --enable=all --template=gcc --error-exitcode=1 --suppress=missingIncludeSystem --inline-suppr --force C_SRCS = $(wildcard $(SRC_DIR)/*.c) C_OBJS = $(patsubst $(SRC_DIR)%,$(OBJ_DIR)%,$(patsubst %.c,%.o,$(C_SRCS))) UNIT_TEST_SRCS = $(wildcard $(UNIT_TEST_SRC_DIR)/*.c) $(filter-out %main.c,$(C_SRCS)) UNIT_TEST_OBJS = $(patsubst $(SRC_DIR)%,$(OBJ_DIR)%,$(patsubst $(UNIT_TEST_SRC_DIR)%,$(UNIT_TEST_OBJ_DIR)%,$(patsubst %.c,%.o,$(UNIT_TEST_SRCS)))) OBJS = $(C_OBJS) STATIC_LIB = $(LIB_DIR)/$(STATIC_LIB_FILE) DYNAMIC_LIB = $(LIB_DIR)/$(DYNAMIC_LIB_FILE) UNIT_TEST_TARGET = $(BIN_DIR)/$(UNIT_TEST_SRC_DIR)/$(TARGET_FILE) THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) .PHONY: all install uninstall clean all: $(STATIC_LIB) $(DYNAMIC_LIB) install: all install -d $(LIB_INSTALL_DIR) install -d $(INC_INSTALL_DIR) install -m 0644 $(STATIC_LIB) $(LIB_INSTALL_DIR) install -m 0777 $(DYNAMIC_LIB) $(LIB_INSTALL_DIR) install -m 0644 inc/* $(INC_INSTALL_DIR) uninstall: rm -f $(LIB_INSTALL_DIR)/$(STATIC_LIB) rm -f $(LIB_INSTALL_DIR)/$(DYNAMIC_LIB) rm -f $(addprefix $(INC_INSTALL_DIR)/,$(shell ls inc)) rm -rf $(INC_INSTALL_DIR) clean: rm -f $(STATIC_LIB) $(DYNAMIC_LIB) rm -f $(OBJS) $(patsubst %.o,%.d,$(OBJS)) rm -f $(UNIT_TEST_OBJS) $(patsubst %.o,%.d,$(UNIT_TEST_OBJS)) $(UNIT_TEST_TARGET) rm -f $(UNIT_TEST_OBJ_DIR)/*.gcda rm -f $(UNIT_TEST_OBJ_DIR)/*.gcno rm -f $(OBJ_DIR)/*.gcda $(OBJ_DIR)/*.gcno rm -fr $(COVERAGE_DIR) .PHONY: coverage coverage: _cov_genhtml $(eval COVERAGE:=$(shell grep 'lines' .coverage.tmp | egrep -o '[0-9]+.[0-9]+%')) @echo @echo Line coverage: $(COVERAGE) @echo @rm -f .coverage.tmp .PHONY: _cov_lcov _cov_lcov: exec_unit_test @rm -f $(UNIT_TEST_OBJ_DIR)/*.gcda @rm -f $(UNIT_TEST_OBJ_DIR)/*.gcno @mkdir -p $(COVERAGE_DIR) $(LCOV) -c -d $(OBJ_DIR) -o $(COVERAGE_DIR)/coverage.info .PHONY: _cov_genhtml _cov_genhtml: _cov_lcov $(GENHTML) -o $(COVERAGE_DIR)/html $(COVERAGE_DIR)/coverage.info > .coverage.tmp .PHONY: unit_test build_unit_test: $(UNIT_TEST_TARGET) .PHONY: unit_test exec_unit_test: $(UNIT_TEST_TARGET) $(UNIT_TEST_TARGET) .PHONY: check check: $(C_SRCS) $(CHECK) $(CPP_FLAGS) $(CHECK_FLAGS) $(C_SRCS) $(UNIT_TEST_TARGET): $(UNIT_TEST_OBJS) $(THIS_MAKEFILE) @mkdir -p $(BIN_DIR)/$(UNIT_TEST_SRC_DIR) $(CC) $(C_FLAGS) $(LD_FLAGS) $(UNIT_TEST_OBJS) -o $@ $(STATIC_LIB): $(OBJS) $(THIS_MAKEFILE) @mkdir -p $(LIB_DIR) $(AR) rcs $(STATIC_LIB) $(OBJS) $(DYNAMIC_LIB): $(OBJS) $(THIS_MAKEFILE) @mkdir -p $(LIB_DIR) $(CC) $(L_FLAGS) -o $(DYNAMIC_LIB) $(OBJS) .PRECIOUS: $(OBJ_DIR)/%.d $(OBJ_DIR)/%.d: $(SRC_DIR)/%.c @mkdir -p $(OBJ_DIR) $(CPP) -MM -MF $@ -MP -MT $(patsubst %.d,%.o,$@) $(CPP_FLAGS) $(patsubst $(OBJ_DIR)/%.d,$(SRC_DIR)/%.c,$@) .PRECIOUS: $(UNIT_TEST_OBJ_DIR)/%.d $(UNIT_TEST_OBJ_DIR)/%.d: $(UNIT_TEST_SRC_DIR)/%.c @mkdir -p $(UNIT_TEST_OBJ_DIR) $(CPP) -MM -MF $@ -MP -MT $(patsubst %.d,%.o,$@) $(CPP_FLAGS) $(patsubst $(UNIT_TEST_OBJ_DIR)/%.d,$(UNIT_TEST_SRC_DIR)/%.c,$@) $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(OBJ_DIR)/%.d @mkdir -p $(OBJ_DIR) $(CC) -c $(CPP_FLAGS) $(C_FLAGS) $< -o $@ $(UNIT_TEST_OBJ_DIR)/%.o: $(UNIT_TEST_SRC_DIR)/%.c $(UNIT_TEST_OBJ_DIR)/%.d @mkdir -p $(UNIT_TEST_OBJ_DIR) $(CC) -c $(CPP_FLAGS) $(C_FLAGS) $< -o $@ ifneq ($(MAKECMDGOALS),clean) -include $(patsubst %.o,%.d,$(OBJS)) endif