Skip to content

Instantly share code, notes, and snippets.

@r10r
Last active July 31, 2016 21:39
Show Gist options
  • Save r10r/9362957 to your computer and use it in GitHub Desktop.
Save r10r/9362957 to your computer and use it in GitHub Desktop.
Generic Makefile honoring 'Why recursive make is harmful' http://aegis.sourceforge.net/auug97.pdf
#!/bin/sh --posix
SRC="$1"
DIR=`dirname $SRC`
SUFFIX=o.mk
shift 1
# append dependency information
RULE=`cc -MM -MG "$@"`
#OBJ=`echo "$RULE" | cut -d':' -f 1`
SRC=`echo "$RULE" | cut -d':' -f 2`
cat <<EOF
${DIR}/${RULE}
SRC += ${SRC}
EOF
-include Settings.mk
# [ project ]
# ===========
default: all
# [ settings ]
# ============
BASE_DIR := $(realpath $(PWD))
BUILD_DIR := $(BASE_DIR)/build
OS := $(shell uname -s)
GCOV_TOOL ?= gcov
CFLAGS += -I$(INCLUDE_DIR)
# use this in modules to reference to the included modules.mk
DIR = $(realpath $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))))
# each module may append to this
OBJS :=
SRC :=
PROGRAMS :=
TESTS :=
# include the description for each module
-include module.mk
include $(patsubst %,%/module.mk,$(MODULES))
# look for include files in each of the modules
# use -isystem ?
CFLAGS += $(patsubst %,-I%,$(MODULES))
all: $(OBJS) $(PROGRAMS) $(TESTS)
# [ os ]
# ======
ifeq ($(DEBUG), true)
ifeq ($(OS),Darwin)
CFLAGS += -gdwarf-2 -g -O0 -fno-inline
endif
ifeq ($(OS),Linux)
CFLAGS += -g -O0 -fno-inline
endif
endif
# [ build ]
# =========
define PROGRAM_template
$(1): $$($(2)_OBJS) $(1).c
$$(CC) $$(CFLAGS) $$($(2)_CFLAGS) $$(LDFLAGS) $$($(2)_LDFLAGS) \
-o $(1) $$($(2)_OBJS)
OBJS += $$($(2)_OBJS)
endef
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(notdir $(prog)))))
define TEST_template
$(1): $$($(2)_OBJS) $(1).c
$$(CC) $$(CFLAGS) $$($(2)_CFLAGS) $$(LDFLAGS) $$($(2)_LDFLAGS) \
-o $(1) $$($(2)_OBJS) && $(1)
OBJS += $$($(2)_OBJS)
endef
$(foreach prog,$(TESTS),$(eval $(call TEST_template,$(prog),$(notdir $(prog)))))
# [ headers ]
# ===========
# calculate C include dependencies
%.o.mk: %.c
$(BASE_DIR)/depend.sh $*.c $(CFLAGS) $*.c > $@
# include the C include dependencies
include $(OBJS:=.mk)
# [ uncrustify ]
# ==============
.uncrustify: $(SRC)
uncrustify --mtime -c $(BASE_DIR)/uncrustify.cfg --replace $? &&\
touch .uncrustify
uncrustify: .uncrustify;
# [ ragel ]
# ===========
# object generation rules
.PRECIOUS: %.c
%.c: %.rl
ragel -L -G2 -o $@ $<
%.dot: %.rl
ragel -V -p -o $@ $<
%.png: %.dot
dot -Tpng $< -o $@
# [ gcov/lcov ]
# =============
LCOV_INFO_FILE := coverage.info
LCOV_DIR := coverage
$(LCOV_DIR)/index.html: $(LCOV_INFO_FILE)
genhtml --ignore-errors source $(LCOV_INFO_FILE) \
--output-directory $(LCOV_DIR)
$(LCOV_INFO_FILE): $(TESTS)
lcov --capture --directory $(BASE_DIR) \
--no-external --output-file $(LCOV_INFO_FILE) \
--gcov-tool $(GCOV_TOOL)
coverage: $(LCOV_DIR)/index.html;
# [ clean ]
# =========
# contains only existing artifacts
ARTIFACTS := $(OBJS) $(OBJS:=.mk) \
$(OBJS:.o=.gcda) $(OBJS:.o=.gcno) \
$(LCOV_DIR) $(LCOV_INFO_FILE)
clean:
rm -rf $(ARTIFACTS)
-include Rules.mk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment