summaryrefslogtreecommitdiff
path: root/mk/skel.mk
diff options
context:
space:
mode:
Diffstat (limited to 'mk/skel.mk')
-rw-r--r--mk/skel.mk254
1 files changed, 254 insertions, 0 deletions
diff --git a/mk/skel.mk b/mk/skel.mk
new file mode 100644
index 0000000..99547ea
--- /dev/null
+++ b/mk/skel.mk
@@ -0,0 +1,254 @@
+# For the reference here are some automatic variables defined by make.
+# There are also their D/F variants e.g. $(<D) - check the manual.
+#
+# $@ - file name of the target of the rule
+# $% - target member name when the target is archive member
+# $< - the name of the first dependency
+# $? - the names of all dependencies that are newer then the target
+# $^ - the names of all dependencies
+
+########################################################################
+# User defined variables #
+########################################################################
+
+# VERB_VARS is a list of variables that you'd like to record on per
+# directory level. So if you set it to say AUTOTEST then each each
+# directory will have it's own AUTOTEST_$(dir) variable with value taken
+# from appropriate Rules.mk
+VERB_VARS :=
+
+# OBJ_VARS - like VERB_VARS but all values taken from Rules.mk have
+# $(OBJPATH) prepended so instead of saying:
+# INSTALL_$d := $(OBJPATH)/some_target
+# you can say simply
+# INSTALL := some_target
+OBJ_VARS := INSTALL_BIN INSTALL_LIB
+
+# DIR_VARS - like VERB_VARS but all values taken from Rules.mk have $(d)
+# prepended (unless value is an absolute path) so you can say:
+# INSTALL_DOC := Readme.txt
+# instead of:
+# INSTALL_DOC_$d := $(d)/Readme.txt
+DIR_VARS := INSTALL_DOC INSTALL_INC
+
+# NOTE: There is generic macro defined below with which you can get all
+# values of given variable from some subtree e.g.:
+# $(call get_subtree,INSTALL,dir)
+# will give you value of all INSTALL variables from tree starting at
+# 'dir'
+
+########################################################################
+# Directory specific flags #
+########################################################################
+
+# You just define in Rules.mk say
+# INCLUDES_$(d) := ....
+# and this will get expanded properly during compilation (see e.g. COMPILE.c)
+# Of course you can still use the target specific variables if you want
+# to have special setting for just one target and not the whole
+# directory. See below for definition of @RD variable.
+DIR_INCLUDES = $(addprefix -I,$(INCLUDES_$(@RD)))
+DIR_CPPFLAGS = $(CPPFLAGS_$(@RD))
+DIR_CFLAGS = $(CFLAGS_$(@RD))
+DIR_CXXFLAGS = $(CXXFLAGS_$(@RD))
+
+########################################################################
+# Global flags/settings #
+########################################################################
+
+CFLAGS = -g -W -Wall $(DIR_CFLAGS)
+CXXFLAGS = -g -W -Wall $(DIR_CXXFLAGS)
+
+OPT_FLAGS := -O3
+
+# List of includes that all (or at least majority) needs
+INCLUDES :=
+
+# Here's an example of settings for preprocessor. -MMD is to
+# automatically build dependency files as a side effect of compilation.
+# This has some drawbacks (e.g. when you move/rename a file) but it is
+# good enough for me. You can improve this by using a special script
+# that builds the dependency files (one can find examples on the web).
+# Note that I'm adding DIR_INCLUDES before INCLUDES so that they have
+# precedence.
+CPPFLAGS = -MMD -D_REENTRANT -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ \
+ $(DIR_CPPFLAGS) $(DIR_INCLUDES) $(addprefix -I,$(INCLUDES))
+
+# Linker flags. The values below will use what you've specified for
+# particular target or directory but if you have some flags or libraries
+# that should be used for all targets/directories just append them at end.
+LDFLAGS = $(LDFLAGS_$(@)) $(addprefix -L,$(LIBDIRS_$(@RD)))
+
+# List of libraries that all targets need (either with specific command
+# generated by this makefile system or for which make has built in rules
+# since LDLIBS is a variable that implicit make rules are using).
+# LDLIBS can be either simple or recursive, but simpler version is
+# suggested :).
+LDLIBS :=
+
+########################################################################
+# The end of generic flags #
+########################################################################
+
+# Now we suck in configuration ...
+include $(MK)/config.mk
+
+# ... optional build mode specific flags ...
+ifdef BUILD_MODE
+ -include $(MK)/build-$(BUILD_MODE).mk
+endif
+
+# ... host and build specific settings ...
+ifneq ($(wildcard $(MK)/config-$(BUILD_ARCH)_$(HOST_ARCH).mk),)
+ include $(MK)/config-$(BUILD_ARCH)_$(HOST_ARCH).mk
+else
+ include $(MK)/config-default.mk
+endif
+
+# ... and here's a good place to translate some of these settings into
+# compilation flags/variables. As an example a preprocessor macro for
+# target endianess
+ifeq ($(ENDIAN),big)
+ CPPFLAGS += -DBIG_ENDIAN
+else
+ CPPFLAGS += -DLITTLE_ENDIAN
+endif
+
+# Use host/build specific config files to override default extension
+# for shared libraries
+SOEXT := $(or $(SOEXT),so)
+
+########################################################################
+# A more advanced part - if you change anything below #
+# you should have at least vague idea how this works :D #
+########################################################################
+
+# I define these for convenience - you can use them in your command for
+# updating the target.
+DEP_OBJS = $(filter %.o, $^)
+DEP_ARCH = $(filter %.a, $^)
+DEP_LIBS = $(addprefix -L,$(dir $(filter %.$(SOEXT), $^))) $(patsubst lib%.$(SOEXT),-l%,$(notdir $(filter %.$(SOEXT), $^)))
+
+# Kept for backward compatibility - you should stop using these since
+# I'm now not dependent on $(OBJDIR)/.fake_file any more
+?R = $?
+^R = $^
+
+# Targets that match this pattern (make pattern) will use rules defined
+# in:
+# - def_rules.mk included below (explicit or via `skeleton' macro)
+# - built in make rules
+# Other targets will have to use _DEPS (and so on) variables which are
+# saved in `save_vars' and used in `tgt_rule' (see below).
+AUTO_TGTS := %.o
+
+# Where to put the compiled objects. You can e.g. make it different
+# depending on the target platform (e.g. for cross-compilation a good
+# choice would be OBJDIR := obj/$(HOST_ARCH)) or debugging being on/off.
+OBJDIR := $(if $(BUILD_MODE),obj/$(BUILD_MODE),obj)
+
+# Convenience function to convert from a build directory back to the
+# "real directory" of a target
+define build_to_real_dir
+$(if $(strip $(TOP_BUILD_DIR)),$(patsubst $(TOP_BUILD_DIR)%/$(OBJDIR),$(TOP)%,$(1)),$(patsubst %/$(OBJDIR),%,$(1)))
+endef
+
+# Convenience function to convert from the "real directory" to the build
+# directory
+define real_to_build_dir
+$(if $(strip $(TOP_BUILD_DIR)),$(TOP_BUILD_DIR)$(subst $(TOP),,$(1))/$(OBJDIR),$(1)/$(OBJDIR))
+endef
+
+# By default OBJDIR is relative to the directory of the corresponding Rules.mk
+# however you can use TOP_BUILD_DIR to build all objects outside of your
+# project tree. This should be an absolute path. Note that it can be
+# also inside your project like example below.
+#TOP_BUILD_DIR := $(TOP)/build_dir
+OBJPATH = $(call real_to_build_dir,$(d))
+CLEAN_DIR = $(call real_to_build_dir,$(subst clean_,,$@))
+DIST_CLEAN_DIR = $(patsubst %/$(OBJDIR),%/$(firstword $(subst /, ,$(OBJDIR))),\
+ $(call real_to_build_dir,$(subst dist_clean_,,$@)))
+
+# This variable contains a list of subdirectories where to look for
+# sources. That is if you have some/dir/Rules.mk where you name object
+# say client.o this object will be created in some/dir/$(OBJDIR)/ and
+# corresponding source file will be searched in some/dir and in
+# some/dir/{x,y,z,...} where "x y z ..." is value of this variable.
+SRCS_VPATH := src
+
+# Target "real directory" - this is used above already and is most
+# reliable way to refer to "per directory flags". In theory one could
+# use automatic variable already defined by make "<D" but this will not
+# work well when somebody uses SRCS_VPATH variable.
+@RD = $(call build_to_real_dir,$(@D))
+
+# These are commands that are used to update the target. If you have
+# a target that make handles with built in rules just add its pattern to
+# the AUTO_TGTS below. Otherwise you have to supply the command and you
+# can either do it explicitly with _CMD variable or based on the
+# target's suffix and corresponding MAKECMD variable. For example %.a
+# are # updated by MAKECMD.a (exemplary setting below). If the target
+# is not filtered out by AUTO_TGTS and there's neither _CMD nor suffix
+# specific command to build the target DEFAULT_MAKECMD is used.
+MAKECMD.a = $(call echo_cmd,AR $@) $(AR) $(ARFLAGS) $@ $(DEP_OBJS) && $(RANLIB) $@
+MAKECMD.$(SOEXT) = $(LINK.cc) $(DEP_OBJS) $(DEP_ARCH) $(DEP_LIBS) $(LIBS_$(@)) $(LDLIBS) -shared -o $@
+DEFAULT_MAKECMD = $(LINK.cc) $(DEP_OBJS) $(DEP_ARCH) $(DEP_LIBS) $(LIBS_$(@)) $(LDLIBS) -o $@
+
+########################################################################
+# Below is a "Blood sugar sex^H^H^Hmake magik" :) - don't touch it #
+# unless you know what you are doing. #
+########################################################################
+
+# This can be useful. E.g. if you want to set INCLUDES_$(d) for given
+# $(d) to the same value as includes for its parent directory plus some
+# add ons then: INCLUDES_$(d) := $(INCLUDES_$(parent_dir)) ...
+parent_dir = $(patsubst %/,%,$(dir $(d)))
+
+define include_subdir_rules
+dir_stack := $(d) $(dir_stack)
+d := $(d)/$(1)
+$$(eval $$(value HEADER))
+include $(addsuffix /Rules.mk,$$(d))
+$$(eval $$(value FOOTER))
+d := $$(firstword $$(dir_stack))
+dir_stack := $$(wordlist 2,$$(words $$(dir_stack)),$$(dir_stack))
+endef
+
+define save_vars
+DEPS_$(1)$(2) = $(value $(2)_DEPS)
+LIBS_$(1)$(2) = $(value $(2)_LIBS)
+LDFLAGS_$(1)$(2) = $(value $(2)_LDFLAGS)
+CMD_$(1)$(2) = $(value $(2)_CMD)
+$(2)_DEPS =
+$(2)_LIBS =
+$(2)_LDFLAGS =
+$(2)_CMD =
+endef
+
+define tgt_rule
+abs_deps := $$(foreach dep,$$(DEPS_$(1)),$$(if $$(or $$(filter /%,$$(dep)),$$(filter $$$$%,$$(dep))),$$(dep),$$(addprefix $(OBJPATH)/,$$(dep))))
+-include $$(addsuffix .d,$$(basename $$(abs_deps)))
+$(1): $$(abs_deps) $(if $(findstring $(OBJDIR),$(1)),| $(OBJPATH),)
+ $$(or $$(CMD_$(1)),$$(MAKECMD$$(suffix $$@)),$$(DEFAULT_MAKECMD))
+endef
+
+# subtree_tgts is now just a special case of a more general get_subtree
+# macro since $(call get_subtree,TARGETS,dir) has the same effect but
+# I'm keeping it for backward compatibility
+define subtree_tgts
+$(TARGETS_$(1)) $(foreach sd,$(SUBDIRS_$(1)),$(call subtree_tgts,$(sd)))
+endef
+
+define get_subtree
+$($(1)_$(2)) $(foreach sd,$(SUBDIRS_$(2)),$(call get_subtree,$(1),$(sd)))
+endef
+
+# if we are using out of project build tree then there is no need to
+# have dist_clean on per directory level and the one below is enough
+ifneq ($(strip $(TOP_BUILD_DIR)),)
+dist_clean :
+ rm -rf $(TOP_BUILD_DIR)
+endif
+
+# Suck in the default rules
+include $(MK)/def_rules.mk