You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
6.2 KiB

######################################################################
# Some helper functions
#
######################################################################
# $(call inspect,LIST)
# dump list of variables printing their values and their attributes
inspect = $(foreach v,$(1),$(info $(v) [$(origin $(v)),$(flavor $(v))] = $($(v))))
# $(call undefine_default,LIST)
# undefine default variables given in LIST)
undefine_default = $(foreach v,$(1),$(if $(filter default,$(origin $(v))),$(eval undefine $(v)),))
# $(call setdef_ifdef,VAR,DEFVAR)
# if DEFVAR exists, set default value of VAR to $(DEFVAR)
setdefault_ifdef = $(if $(filter undefined,$(origin $(2))),,$(eval $(1) ?= $($(2))))
# $(call clean_bool_true,VALUE)
# $(call clean_bool_false,VALUE)
# $(call clean_bool,VALUE)
# clean_bool,clean_bool_true:
# if VALUE is identified as true (true, on, yes, enable, 1, ...) returns 1
# clean_bool,clean_bool_false:
# if VALUE is identified as false (false, off, no, disable, 0, ...) returns an empty string
clean_bool_true = $(if $(filter true TRUE on ON yes YES enable ENABLE,$(1)),1,$(1))
clean_bool_false = $(if $(filter false FALSE off OFF no NO disable DISABLE 0,$(1)),,$(1))
clean_bool = $(call clean_bool_false,$(call clean_bool_true,$(1)))
# $(call quote_spaces,STR)
# return STR, surrounded by double quotes if it contains spaces
quote_spaces = $(if $(filter 0 1,$(words $1)),$1,"$1")
# $(call pathsearch,EXEC)
# returns the full path of EXEC if it exists somewhere in $PATH
# if not found, returns the unmodified EXEC
pathsearch = $(if $(filter 1,$(words $(1))),$(firstword $(wildcard $(1) $(addsuffix /$(1),$(subst :, ,$(PATH)))) $(1)),$(1))
# $(call prepend_ccache,PREFIX,EXEC)
# return 'ccache EXEC' if ccache is not already detected in EXEC
prepend_ccache = $(if $(filter ccache,$(subst /, ,$(1))),$(1),ccache $(1))
# $(call clean_path,PATH)
# return a sanitized path: remove //, trailing /
clean_path = $(subst //,/,$(patsubst %/,%,$1))
# ($call quiet-command,CMD,MSG)
# execute CMD and display MSG
# if verbose mode is enabled (with 'make V=1`) print full CMD instead of MSG
quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
######################################################################
# Cached configuration support
#
# variables listed in CONFIG_VARS are stored in CONFIG_MAK file
# containing lines `cache_VAR=value`
# This file is read on subsequent invocation and set default values
# of these variables.
#
# The file is automatically generated but can be hand-edited.
#
######################################################################
CONFIG_MAK = config.mak
CONFIG_VARS = max
CONFIG_STRING = $(foreach var,$(CONFIG_VARS),$(var)=$(call quote_spaces,$($(var))))
# undefine variables which have a default value set by make itself
# (mainly CC and CXX)
$(call undefine_default,$(CONFIG_VARS))
# read the cached variables
-include $(CONFIG_MAK)
# for all undefined variables set their default values from ones
# stored in included CONFIG_MAK.
$(foreach var,$(CONFIG_VARS),$(call setdefault_ifdef,$(var),cache_$(var)))
#default (non false) values
# max ?= 10
# cleanup "False" boolean values, set them to empty value
$(foreach var,$(CONFIG_VARS),$(eval override $(var):=$(call clean_bool_false,$($(var)))))
# print out user configuration
# (only once in case the makefile has been reloaded)
ifndef MAKE_RESTARTS
$(info CONF $(CONFIG_STRING))
endif
######################################################################
# Flags generation
#
######################################################################
CFLAGS =
ifdef max
CFLAGS += -DFIBO_MAX=$(max)
endif
######################################################################
# Source and objects collection
#
######################################################################
.SUFFIXES:
.SUFFIXES: .c .o
ifdef srcdir
srcdir := $(patsubst %/,%,$(srcdir))
else
srcdir := $(patsubst %/,%,$(dir $(realpath $(firstword $(MAKEFILE_LIST)))))
endif
INCLUDES := src \
src/version \
src/fibo
SRCS := src/main.c \
src/version/version_tools.c \
src/fibo/fibo.c
OBJS += src/version/version.o
OBJS += $(SRCS:%.c=%.o)
VPATH += $(srcdir)
VPATH += .
CFLAGS += $(addprefix -I$(srcdir)/,$(INCLUDES))
GENERATED += $(OBJS)
GENERATED += $(DEPDIR)
GENERATED += src/version/version.c
GENERATED += fibo
######################################################################
# Dependencies tracking
#
######################################################################
DEPDIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td #generate dependency file in a temporary file
#Rename the generated temporary dependency file to the real dependency file.
#We do this in a separate step so that failures during the compilation wont leave a corrupted dependency file
#in some rare cases dep file can end up beeing newer than object, final touch ensures that object will always
#be newer.
POSTCOMPILE = @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@
CFLAGS += $(DEPFLAGS)
######################################################################
# Targets
#
######################################################################
.SECONDEXPANSION:
all: fibo
fibo: $(OBJS)
$(call quiet-command, $(CC) $^ -o $@, "LINK $@")
%.c: %.c.in FORCE
@mkdir -p $(@D)
@sed -e 's#@@GIT_SHA1@@#$(shell git describe --all --long --dirty)#' $< > $@.tmp
@cmp -s $@.tmp $@ || (echo "GEN $@"; mv $@.tmp $@)
@rm -f $@.tmp
.PRECIOUS: src/version/version.c
%.o: %.c | $(DEPDIR)/$$(@D)/
$(call quiet-command, $(CC) $(CFLAGS) $(IFLAGS) -o $@ -c $<, "CC $@")
$(POSTCOMPILE)
%/:
@mkdir -p $@
# Generate the cached configuration make script
# - always generated
# - file is written out only if modified
$(CONFIG_MAK): FORCE
@echo "# automatically generated" > $@.tmp
@$(foreach var,$(CONFIG_VARS),echo cache_$(var)=$($(var)) >> $@.tmp;)
@cmp -s $@.tmp $@ || (echo "GEN $@"; mv $@.tmp $@)
@rm -f $@.tmp
$(OBJS): $(MAKEFILE_LIST)
inspect:
$(call inspect,srcdir)
$(call inspect,SRCS)
$(call inspect,OBJS)
$(call inspect,SHELL)
clean:
$(call quiet-command, rm -rf $(GENERATED), "CLEAN")
distclean:
$(call quiet-command, rm -rf $(GENERATED) $(CONFIG_MAK) Makefile, "DISTCLEAN")
.PHONY: FORCE clean inspect
# include all potential dependencies files
-include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))