+c++ext = cc C cxx cpp
+c++sources = $(foreach ext,$(c++ext),$(filter %.$(ext),$(1)))
+
+###
+# template_variables - variables common to program, libraries, ...
+#
+define template_variables
+USER_IDLS += $$($(1)_SERVER_IDL) $$($(1)_CLIENT_IDL) $$($(1)_IDL)
+$(1)_GEN_SOURCES += $$(call IDL_SERVER_SOURCES,$$($(1)_SERVER_IDL))
+$(1)_GEN_SOURCES += $$(call IDL_CLIENT_SOURCES,$$($(1)_CLIENT_IDL))
+$(1)_GEN_SOURCES += $$(sort $$(call IDL_SERVER_SOURCES,$$($(1)_IDL)) \
+ $$(call IDL_CLIENT_SOURCES,$$($(1)_IDL)))
+USER_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+$(1)_OBJS += $(foreach ext,c $(c++ext),$$(patsubst %.$(ext),%.o,$$(filter %.$(ext),$$($(1)_SOURCES) $$($(1)_GEN_SOURCES))))
+$(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%)) # Why is here the backslash substitution???
+$(1)_OBJS := $$(addprefix $(USER_OBJS_DIR)/,$$(sort $$($(1)_OBJS:%/=%)))
+
+USER_OBJS += $$($(1)_OBJS)
+USER_SOURCES += $$($(1)_SOURCES)
+endef
+
+###
+# program_template
+#
+# Usage: $(call program_template,<executable-name>,<bin|utils|test>)
+define program_template
+$(template_variables)
+$$(eval $$(call prepare_rule_goal,\
+ $(USER_BIN_DIR)/$(1)$(EXE_SUFFIX),\
+ $$($(1)_OBJS),\
+ "LINK ",\
+ $$(call program_cmd,$(1))))
+endef
+
+###
+# library_template
+#
+# Usage: $(call library_template,<library-name>)
+define library_template
+$(template_variables)
+$$(eval $$(call prepare_rule_goal,\
+ $(USER_LIB_DIR)/lib$(1).a,\
+ $$($(1)_OBJS),\
+ "AR ",\
+ $$(call library_cmd,$(1))))
+endef
+
+###
+# solib_template
+#
+# Usage: $(call solib_template,<library-name>)
+define solib_template
+$(template_variables) # FIXME: OBJSLO, etc.
+# TODO: Add dependencies on other shared libraries ala:
+# $(1)_libs += $$($(1)_LIBS) $$(lib_LOADLIBES)
+# $(1)_shared_libs = $$(patsubst %,$(USER_LIB_DIR)/lib%.$(SOLIB_EXT),$$(filter $$(shared_libs),$$($(1)_libs)))
+
+$$(eval $$(call prepare_rule_goal,\
+ $(USER_LIB_DIR)/lib$(1).$(SOLIB_EXT),\
+ $$($(1)_OBJS),\
+ "LINK ",\
+ $$(call solib_cmd,$(1))))
+endef
+
+prepare-pass: create-build-dirs
+create-build-dirs::
+ifneq ($(bin_PROGRAMS)$(test_PROGRAMS)$(utils_PROGRAMS)$(lib_LIBRARIES)$(shared_LIBRARIES),)
+create-build-dirs::
+ @$(call mkdir_def,$(USER_OBJS_DIR))
+endif
+
+# TODO: $(foreach cmetrh,...)
+
+$(foreach prog,$(bin_PROGRAMS),$(eval $(call program_template,$(prog),bin)))
+$(foreach prog,$(utils_PROGRAMS),$(eval $(call program_template,$(prog),utils)))
+$(foreach prog,$(test_PROGRAMS),$(eval $(call program_template,$(prog),test)))
+$(foreach lib,$(lib_LIBRARIES),$(eval $(call library_template,$(lib))))
+$(foreach lib,$(shared_LIBRARIES),$(eval $(call solib_template,$(lib))))
+
+$(foreach src,$(filter %.c,$(USER_SOURCES)),\
+ $(eval $(call prepare_rule,\
+ $(USER_OBJS_DIR)/$(src:%.c=%.o),\
+ $(SOURCES_DIR)/$(src),\
+ "CC ",\
+ $(c_o_cmd))))