Changes necessary and proper to get mgear to build rsync:
[mgear/mgear.git] / mgear.mk
index d456fd5..cccdbc2 100644 (file)
--- a/mgear.mk
+++ b/mgear.mk
@@ -10,11 +10,16 @@ mg-orig-default-goal:=$(.DEFAULT_GOAL)
 # instead of trying to anticipate which prerequisites it will need in advance.
 .SECONDEXPANSION:
 
+# Deletion of intermediate files messes everything up.
+# TODO: See if we can relax this requirement.
+.SECONDARY:
+
 
 # TEXT UTILITIES
 empty:=
 bs:=\$(empty)
 hash:=\#
+comma:=,
 pct:=%
 define nl
 
@@ -25,6 +30,9 @@ sq='$(subst ','\'',$1)'
 # Make-quote: a$\nb => a$$$(nl)b
 # This is enough to assign the value, *but not to use it as an argument!*
 mqas=$(subst $(hash),$$(hash),$(subst $(nl),$$(nl),$(subst $$,$$$$,$1)))
+# Make the value safe to use as an argument without doubling $.
+# *The implementation is incomplete*; I will improve it as needed.
+msarg=$(subst $(comma),$$(comma),$1)
 # Return nonempty if the strings are equal, empty otherwise.
 # If the strings have only nice characters, you can do $(filter x$1,x$2).
 streq=$(findstring x$1,$(findstring x$2,x$1))
@@ -105,20 +113,21 @@ $(opfx)%: $$(empty) $$($$(oid)@opr)
 # prerequisite change, etc. and acts accordingly.
 #
 # Target metadata variables for bar: (* means stored in bar.g)
+# Now some variables are reused instead of remembered for every target.
+#
+# @name:=bar
+#     Name of the target to which @cmd, @warnings, @deps refer.
 #
-# bar@cmd:=cat foo >bar.tmp
+# @cmd:=cat foo >bar.tmp
 #     Generation command as given to the shell.*
 #
-# bar@warnings:=$(empty)yikes!
+# @warnings:=$(empty)yikes!
 #     Data that the command printed to stdout or stderr, presumably warnings.*
 #
-# bar@deps:=included@x oops@
+# @deps:=included@x oops@
 #     If dependency-logging, list of filename@revision used.  Revision is x for
 #     exists and empty for doesn't exist.  Later perhaps x will be the mtime.*
 #
-# bar@gloaded:=1
-#     Set if mgear has loaded bar.g and hasn't changed it since then.
-#
 # bar@gdeps:=foo
 #     Static dependencies of bar, for checking by bar.g.
 #
@@ -145,28 +154,33 @@ $(opfx)%: $$(empty) $$($$(oid)@opr)
 # - Vpath
 
 # $(call gload,foo.o)
-# Make sure foo.o's genfile, if any, has been loaded.
+# Load foo.o's genfile, if any, into $(@cmd), etc.
 define gload
-$(if $($1@gloaded),,$(eval 
-$1@cmd:=
-$1@warnings:=
-$1@deps:=
+$(if $(filter $(@name),$1),,$(eval 
+# TODO: Store and check the version of mgear that wrote the genfile. 
+#@mgear-version:=
+@cmd:=
+@warnings:=
+@deps:=
 -include $1.g
-$1@gloaded:=1
+@name:=$1
 ))
 endef
+@name:=
 
 # bar.g: scout bar and its dependencies and store $?.  When implicit rules
 # compete for bar, we depend on the rule make uses being the last one it
 # second-expands so that $(bar@gdeps) is still correct.
 mg-genfile-oid:=$(newoid)
 mg-scout-oid:=$(newoid)
-$(mg-genfile-oid)@opr=$($(otgt:.g=)@gdeps) $(if $(wildcard $(otgt:.g=)),$(mg-scout-oid)$(aname)$(otgt:.g=),)
-$(mg-genfile-oid)@ocmd=$(eval $(otgt:.g=)@gq:=$?)
+$(mg-genfile-oid)@opr=$($(otgt:.g=)@gdeps) $(if $(wildcard $(otgt:.g=)),$(mg-scout-oid)$(aname)$(otgt:.g=),) MG-FORCE
+$(mg-genfile-oid)@ocmd=$(eval $(otgt:.g=)@gq:=$(filter-out MG-%,$?))
+$(mg-scout-oid)@opr:=
+$(mg-scout-oid)@ocmd:=
 
 # Mgear-ized automatic variables.
-# $@: needs no translation
-# NOTE: $(mg@) is *eventual* target.  Commands must write to temp file, $t .
+# For now, if you really want the eventual target, write $$(@).
+mg@ = $@.tmp
 # $%: haven't thought about it much, but probably needs no translation
 mg< = $(firstword $(mg^))
 mg? = $(filter-out $(opfx)%,$($@@gq))
@@ -175,11 +189,11 @@ mg+ = $(filter-out MG-% $(opfx)%,$+)
 # $|: needs no translation
 # $*: needs no translation
 
-# $(call mg-translate-cmd,cat $$< >$$t)
+# $(call mg-translate-cmd,cat $$< >$$@)
 # Replaces references to automatic variables with references to their mgear-ized
 # counterparts.  There might be false matches, e.g., $$@ => $$(mg@) ;
 # to prevent that, write $$$(empty)@ instead.  (c.f. autoconf empty quadrigraph)
-mg-translate-cmd=$(subst $$t,$$@.tmp,$(subst $$?,$$(mg?),$(subst $$<,$$(mg<),$(subst $$^,$$(mg^),$(subst $$+,$$(mg+),$1)))))
+mg-translate-cmd=$(subst $$@,$$(mg@),$(subst $$?,$$(mg?),$(subst $$<,$$(mg<),$(subst $$^,$$(mg^),$(subst $$+,$$(mg+),$1)))))
 
 # $(call mg-prereq-predict,target,prerequisites)
 # Expands to code that does the following at second-expansion time:
@@ -198,9 +212,10 @@ mg-prereq-predict=$$$$(call mg-set-gdeps,$$$$+ $(if $(findstring /,$1),$$$$(subs
 MG-FORCE:
 .PHONY: MG-FORCE
 
-# $(call mg-define-rule,target,prerequisites,cmd)
-# Defines a rule.  cmd is expanded again when it is run, at which time
-# Mgear-ized automatic variables are available.
+# $(call mg-define-rule,target,prerequisites,cmdvar)
+# Defines a rule.  cmdvar is *the name of a variable* containing the command.  
+# The variable is read immediately with $(value) and then expanded in the scope
+# of mgear-ized automatic variables each time the rule is run.
 #
 # I eradicated the target-specific variables because they fail when there are
 # multiple implicit rules with the same target pattern.
@@ -210,7 +225,7 @@ MG-FORCE:
 # $(bar@gq).
 define mg-define-rule
 $(eval $1: $(call mg-prereq-predict,$1,$2) $2 MG-FORCE $(mg-genfile-oid)$(aname)$$$$@.g
-       $$(call mg-rule-cmd,$(call mg-translate-cmd,$3)))
+       $$(call mg-rule-cmd,$(call msarg,$(call mg-translate-cmd,$(value $3)))))
 endef
 
 # TODO Provide a way to define static pattern rules.
@@ -249,18 +264,20 @@ define mg-rule-cmd
                $(mg-assign-cmd) >&3 &&\
                $(mg-maybe-move-target) &&\
                mv -f $@.g.tmp $@.g\
-       ,$(if $($@@warnings),\
-               $(info $($@@cmd) # mgear warning replay$(nl)$($@@warnings))\
+       ,$(if $(@warnings),\
+               $(info $1 # mgear warning replay$(nl)$(@warnings))\
        )))
 endef
 
 # If the command changed, we must regenerate.
-mg-check-cmd=$(if $(call streq,$1,$($@@cmd)),,COMMAND-CHANGED)
+# HMMM What if the working directory changes?  Most likely, the command will
+# also change and mgear will do the right thing. 
+mg-check-cmd=$(if $(call streq,$1,$(@cmd)),,COMMAND-CHANGED)
 
 # Pieces of mg-generate that I factored out to make mg-generate more readable.
-mg-assign-cmd=echo $(call sq,$(call fmt-make-assignment,$@@cmd,$1))
+mg-assign-cmd=echo $(call sq,$(call fmt-make-assignment,@cmd,$1))
 mg-run-cmd={ ($1) 2>&1 && { [ -r $@.tmp ] || { echo 'mgear: error: Command for $@ succeeded without creating it!'; false; }; }; }
-mg-wrap-warnings=sed -re '1s/^/$@@warnings:=$$(empty)/; 1!s/^/$@@warnings+=$$(nl)/'
+mg-wrap-warnings=sed -re '1s/^/@warnings:=$$(empty)/; 1!s/^/@warnings+=$$(nl)/'
 # Drat bash's lack of precedence between || and &&.  Extra braces necessary.
 mg-maybe-move-target={ cmp -s $@ $@.tmp || { echo >$@.g && mv -f $@.tmp $@; }; }