Make organization++
[henge/webcc.git] / make / lib / premake.mk
1 #PREMAKE_SOURCE_COMPILER#########################################################
2 # Compile any source-to-source languages before executing the majority of make ##
3 #################################################################################
4 define PREMAKE_SOURCE_COMPILER =
5 # Find the sources for each source-to-source language
6 $(foreach slang,$(SLANGS),
7 $(eval SLANG_SRC := $(shell find $(SRC_DIR) -name "*.$(slang)" -not -name ".*"))
8 # Foreach target type in the source-to-source language, add this source's
9 # targets to the list of the current source-to-source language targets
10 $(eval undefine SLANG_TRG)
11 $(foreach trg,$($(slang)_TRG),
12 $(eval SLANG_TRG += $(SLANG_SRC:%.$(slang)=%.$(if $($(slang)_STEM),$($(slang)_STEM).)$(trg))))
13 # Stat the source file's last-modified time to the var SRC_TIME
14 $(foreach src,$(SLANG_SRC),
15 # Establish a command to run for compiling this file
16 $(eval SHELL_CMD := cd $(dir $(src)) && $($(slang)_C) $($(slang)_FLAGS) $(notdir $(src)))
17 # Evaluate missing targets
18 $(eval FOUND_TRG := $(shell find $(dir $(src)) -name "$(basename $(notdir $(src))).*" -not -name ".*"))
19 $(eval MISSING_TRG := $(filter-out $(FOUND_TRG), $(SLANG_TRG)))
20 # Check timings of existing files
21 $(eval SRC_TIME := $(shell stat -c %Y $(src)))
22 # For each of the targets created by this source language, evaluate the
23 # last-modified times of each potential target. If the file does not exist, set
24 # the time to '0', otherwise set it to the -c %Y result from statting the file.
25 $(foreach srctrg,$(filter $(basename $(src))%, $(SLANG_TRG)),
26 $(eval TRG_TIMES += $(if $(wildcard $(srctrg)),$(shell stat -c %Y $(srctrg)),0)==$(srctrg)))
27 # Sort TRG_TIMES, which will produce a list of oldest-first files and timestamps
28 # of the form [last-modified-deltatime]==[filename]
29 $(eval TRG_TIMES := $(shell echo $(sort $(TRG_TIMES)) | $(call AWK_REVERSE_SQUASH)))
30 # Evaluate the newest time from our ordered list by splitting the word up by its
31 # '==' connectors and looking at the first word
32 $(eval NEWEST_TRG_TIME := $(word 1,$(subst ==, ,$(TRG_TIMES))))
33 # Find the older of the two times (between SRC_TIME and NEWEST_TRG_TIME)
34 $(eval OLDER_TIME := $(firstword $(sort $(NEWEST_TRG_TIME) $(SRC_TIME))))
35 # If the older of the two times is the newest target time found, then we need to
36 # rebuild, but only if our build rule intends to actually make something. If it
37 # instead does not intend to actually make a target, drop a functional rule that
38 # could hypothetically make the target for debugging and analysis purposes
39 $(if $(MAKECMDGOALS),
40 $(eval BUILDGOALS := $(filter-out clean scrub purge uninstall,$(MAKECMDGOALS))),
41 $(eval BUILDGOALS := all))
42 $(if $(and $(BUILDGOALS),$(or $(MISSING_TRG), $(filter $(OLDER_TIME),$(NEWEST_TRG_TIME)))),
43 $(if $(findstring n,$(MAKEFLAGS)),
44 $(SLANG_TRG):
45 $(SHELL_CMD)
46 ,
47 $(info $(SHELL_CMD) $(eval $(shell $(SHELL_CMD)))))
48 ))
49 # Put these targets on the MAKE_TARGETS list to be removed during "clean",
50 # regardless of whether or not they were built just now.
51 $(eval MAKE_TARGETS += $(SLANG_TRG))
52 )
53 #/PREMAKE_SOURCE_COMPILER########################################################
54 endef
55