Merge branch 'master' of pitec:the_march
[henge/webcc.git] / src / Makefile
index b5e6754..06466c6 100644 (file)
@@ -86,10 +86,11 @@ c_OBJ      := $($(c_C)_OBJ)
 # binaries.
 MODULES    := $(filter-out $(DRIVER_DIR),$(subst /,,$(shell ls -d */)))
 
+#AWK_REVERSE_SQUASH##############################################################
 # The following awk program reverses the order of a list while also removing
 # duplicate entries.  The effect of this when run on the dependency tree is that
 # it will remove duplicates occurring in reverse order, allowing the most deeply
-# nested libraries to be built, and linked, first.
+# nested libraries to be built, and linked, first. ##############################
 define AWK_REVERSE_SQUASH =
 awk \
 '
@@ -99,19 +100,29 @@ awk \
   print ""
 }
 '
+#/AWK_REVERSE_SQUASH#############################################################
 endef
 
-# Compile any source-to-source languages before executing the majority of make
+#PREMAKE_SOURCE_COMPILER#########################################################
+# Compile any source-to-source languages before executing the majority of make ##
+#################################################################################
 define PREMAKE_SOURCE_COMPILER =
 # Find the sources for each source-to-source language
 $(foreach slang,$(SLANGS),
-$(eval SLANG_SRC := $(patsubst ./%,%,$(filter-out .%,$(shell find -name "*.$(slang)"))))
+$(eval SLANG_SRC := $(patsubst  ./%, %,$(shell find -name "*.$(slang)" -not -name ".*")))
 # Foreach target type in the source-to-source language, add this source's
 # targets to the list of the current source-to-source language targets
+$(eval undefine SLANG_TRG)
 $(foreach trg,$($(slang)_TRG),
 $(eval SLANG_TRG += $(SLANG_SRC:%.$(slang)=%.$(if $($(slang)_STEM),$($(slang)_STEM).)$(trg))))
 # Stat the source file's last-modified time to the var SRC_TIME
 $(foreach src,$(SLANG_SRC),
+# Establish a command to run for compiling this file
+$(eval SHELL_CMD := cd $(dir $(src)) && $($(slang)_C) $($(slang)_FLAGS) $(notdir $(src)))
+# Evaluate missing targets
+$(eval FOUND_TRG := $(shell find $(dir $(src)) -name "$(basename $(notdir $(src))).*" -not -name ".*"))
+$(eval MISSING_TRG := $(filter-out $(FOUND_TRG), $(SLANG_TRG)))
+# Check timings of existing files
 $(eval SRC_TIME := $(shell stat -c %Y $(src)))
 # For each of the targets created by this source language, evaluate the
 # last-modified times of each potential target.  If the file does not exist, set
@@ -127,19 +138,24 @@ $(eval NEWEST_TRG_TIME := $(word 1,$(subst ==, ,$(TRG_TIMES))))
 # Find the older of the two times (between SRC_TIME and NEWEST_TRG_TIME)
 $(eval OLDER_TIME := $(firstword $(sort $(NEWEST_TRG_TIME) $(SRC_TIME))))
 # If the older of the two times is the newest target time found, then we need to
-# rebuild, but only if our build rule intends to actually make something
+# rebuild, but only if our build rule intends to actually make something.  If it
+# does not intend to make something, drop a functional rule to actually make the
+# target
 $(if $(MAKECMDGOALS),
 $(eval BUILDGOALS := $(filter-out clean scrub purge uninstall,$(MAKECMDGOALS))),
 $(eval BUILDGOALS := all))
-$(if $(and $(BUILDGOALS),$(filter $(OLDER_TIME),$(NEWEST_TRG_TIME))),
-$(eval SHELL_CMD := cd $(dir $(src)) && $($(slang)_C) $($(slang)_FLAGS) $(notdir $(src)))
-$(info SHELL_CMD := cd $(dir $(src)) && $($(slang)_C) $($(slang)_FLAGS) $(notdir $(src)))
-$(info $(SHELL_CMD) $(shell $(SHELL_CMD)))
-)
+$(if $(and $(BUILDGOALS),$(or $(MISSING_TRG), $(filter $(OLDER_TIME),$(NEWEST_TRG_TIME)))),
+$(if $(findstring n,$(MAKEFLAGS)),
+$(SLANG_TRG):
+       $(SHELL_CMD)
+,
+$(info $(SHELL_CMD) $(eval $(shell $(SHELL_CMD)))))
+))
 # Put these targets on the MAKE_TARGETS list to be removed during "clean",
 # regardless of whether or not they were built just now.
-$(eval MAKE_TARGETS+= $(SLANG_TRG))
-))
+$(eval MAKE_TARGETS += $(SLANG_TRG))
+)
+#/PREMAKE_SOURCE_COMPILER########################################################
 endef
 # Compile a source language to a language that compiles to binary, but only if
 # our build rule intends to build some kind of target
@@ -158,13 +174,14 @@ define SRC_LANG_FLAGS_OPT_DEPS =
 $(filter-out \ %:,$(shell $($2_C) $3 $4 -MG $1 2> /dev/null))
 endef
 
+#SRC_LANG_RULE###################################################################
 # Given a source and a language, generate a rule to make the object.  The second
 # invocation of gcc per file lists only its local includes, and filters out
 # anything already caught.  Anything remaining should be considered to be
 # available in the current working directory of the source file(i.e. if you
 # '#include "something.h"' in 'mymodule/horseradish.c', you would expect to
 # include 'mymodule/something.h'.  this check lets that happen), otherwise it is
-# some kind of user error
+# some kind of user error #######################################################
 define SRC_LANG_RULE =
 $(if $($1),,$(eval $1 := t)\
 $(eval MOD  := $(filter $(MODULES),$(firstword $(subst /, ,$(dir $1)))))\
@@ -178,8 +195,16 @@ $(eval MDEPS := $(shell echo $(MDEPS) | sed -e 's@[a-zA-Z0-9\-\+/]*\.\./include@
 $(eval ALLDEPS := $(MDEPS) $(DEPS)),\
 $(error Cannot generate deps for: $1, file not found))\
 $(eval SRC_OBJ    := $(basename $1).$($2_OBJ))\
-$(eval MAKE_TARGETS+= $(SRC_OBJ))\
-
+$(eval MAKE_TARGETS += $(SRC_OBJ))
+# Assume that lost dependencies are in the folder with the source
+$(foreach lost,$(LOST),
+$(eval ALLDEPS := $(subst  $(lost), $(dir $1)$(lost),$(ALLDEPS))))
+
+# Find any deps that aren't built yet, which the compiler has flagged
+# as missing, but which we know the expected location of libs for
+# this language should have their includes in 'LIBINC_DIR'
+$(eval BUILDDEPS := $(filter $($2_LIBS:%=%/%),$(ALLDEPS)))
+$(eval ALLDEPS := $(filter-out $(BUILDDEPS),$(ALLDEPS)) $(BUILDDEPS:%=$(LIBINC_DIR)/%))
 # Object for $1
 $(SRC_OBJ): $(ALLDEPS)
        $($2_C) $$($2_FLAGS) $(FLG) -c -o $$@ $1
@@ -187,12 +212,15 @@ $(if $($2_DBG),\
 $(eval DBG_OBJ    := $(dir $1).$($2_DBG)/$(basename $(notdir $1)).$($2_OBJ))\
 $(if $(findstring $(dir $(DBG_OBJ)),$(MAKE_DIRS)),,\
 $(eval MAKE_DIRS += $(dir $(DBG_OBJ))))
+$(eval MAKE_TARGETS += $(DBG_OBJ))
 # Object for $1 with $($2_DBG) symbols
 $(DBG_OBJ): $(ALLDEPS) | $(dir $(DBG_OBJ))
        $($2_C) $$($2_FLAGS) $(FLG) -Og -g$($2_DBG) -c -o $$@ $1
 ))
+#/SRC_LANG_RULE##################################################################
 endef
 
+#SRC_LANG_DRVRULE################################################################
 # establish a build and link rule given a source driver and language ############
 define SRC_LANG_DRVRULE =
 $(eval DRIVER_NAME  := $(basename $(notdir $1)))
@@ -214,7 +242,9 @@ $(eval DRIVER_MODULES := $(filter-out $(DRIVER_DIR) ..,$(sort $(DRIVER_MODULES))
 # any internal modules, the developer may instead create a file with the same
 # basename as the driver, but with the '.ld' suffix, which contains a space
 # separated list of internal modules to link together during compilation
-$(eval DRIVER_MODULES += $(file <$(1:%.$2=%.ld)))
+$(eval DRIVER_LDVALS  := $(file <$(1:%.$2=%.ld)))
+$(eval DRIVER_LFLAGS  := $(filter -l%,$(DRIVER_LDVALS)))
+$(eval DRIVER_MODULES += $(filter-out -l%,$(DRIVER_LDVALS)))
 
 # List of module archives to link together during compilation
 $(eval DRIVER_ARCHIVES    := $(DRIVER_MODULES:%=%.$($2_AROBJ)))
@@ -243,8 +273,8 @@ $(if $($2_DBG),$(eval MAKE_DIRS += $(DRIVER_TARG_DIR).$($2_DBG)))
 # '_start').  This driver object is then simply linked to its libraries and
 # module archives to create an executable binary in the output folder.
 # ORDER MATTERS HERE, this is for the linker:
-$(eval DRIVER_SRC  := $(DRIVER_DEPS))
-$(eval DRIVER_DBGSRC := $(DRIVER_DBGDEPS))
+$(eval DRIVER_SRC  := $(DRIVER_LFLAGS) $(DRIVER_DEPS))
+$(eval DRIVER_DBGSRC := $(DRIVER_LFLAGS) $(DRIVER_DBGDEPS))
 # Iterate through the list of libraries in our language and stack commands from
 # left to right in the "sources" section of the LD command (or LD section of the
 # commandline for the compiler), to preserve ordering and also ensure that it is
@@ -278,12 +308,13 @@ $(DRIVER_NAME)-run: $(DRIVER_TARG)
        $(DRIVER_TARG)
 $(DRIVER_NAME)-d: $(DRIVER_DBGTARG)
 
-#/SRC_LANG_DRVRULE##############################################################
+#/SRC_LANG_DRVRULE###############################################################
 endef
 
+#MODULE_ARCRULE##################################################################
 # generate rule for turning an entire module's collection of binary objects into
 # a single locally-linked (no external -L libs) object (for simplified linking
-# modules as static libs).
+# modules as static libs).#######################################################
 define MODULE_ARCRULE =
 $(eval ARCDEPS := $(filter $1/%.$(c_OBJ),$(foreach lang,$(LANGS),$($(lang)_MOD_TRG))))\
 $(eval MAKE_TARGETS+= $1.$(c_AROBJ))\
@@ -298,6 +329,7 @@ $(eval MAKE_TARGETS+= .$(c_DBG)/$1.$(c_AROBJ))\
 .$(c_DBG)/$1.$(c_AROBJ): $(DBGARCDEPS) | .$(c_DBG)/
        $(c_AR) cr $$@ $$^
 )
+#/MODULE_ARCRULE#################################################################
 endef
 
 # LANG_LIB_PARENT_BUILDRULE######################################################
@@ -442,7 +474,7 @@ $(eval
 $1_OBJ     := $($($1_C)_OBJ)
 $1_OUT     := $($($1_C)_OUT)
 $1_AROBJ   := $($($1_C)_AROBJ)
-$1_SOURCES := $(subst ./,,$(shell find -name "*.$1"))
+$1_SOURCES := $(subst ./,,$(shell find -name "*.$1" -not -name ".*"))
 $1_DBG     := $($($1_C)_DBG)
 $1_AR      := $($($1_C)_AR)
 )