Here's a better version. The major miss in the first was not to use $(value) to get the value of a variable, which causes syntax errors for non-simple variable values. Also this uses the .EXTRA_PREREQS to make everything automagically depend on the serialization file and make files. Depending on the make files catches variable changes in those files, so this fragment can now go at the top of the Makefile where it does somewhat better at catching changes due to weird variable use (case where a value is passed in, trigger ifdef, then gets reset).
# For putting newlines in strings: define nl endef OSMVF = .old_serialized_make_vars NSMVF = .new_serialized_make_vars # Store serialization of all variable flavor/name/value $(file \ >$(NSMVF), \ $(foreach v,$(.VARIABLES),$(flavor $(v)) var $(v) is $(value $(v))$(nl))) # Create or update $(OSMVF) if necessary $(shell \ ( \ [ -a $(OSMVF) ] \ && \ (diff $(OSMVF) $(NSMVF) >/dev/null) \ ) \ || \ cp $(NSMVF) $(OSMVF) \ ; \ rm $(NSMVF) ) # Build Rule Inputs. This is supposed to list everything that sets the build # rules themselves. FIXXME: this won't work right when generated dependency # files with .mk extensions are used (so use a different extension :) BRI = Makefile $(shell find . -name "*.mk" -print) $(OSMVF) # Means all targets should depend on $(BRI) .EXTRA_PREREQS = $(BRI) # Demo target bar: foo # Fake build for demo: cp $< $@ clean: rm -f $(OSMVF) On Wed, Jun 9, 2021 at 6:14 PM Britton Kerin <britton.ke...@gmail.com> wrote: > > The rebuild-the-world-if-anything-changed approach turned out to be > pretty simple I think. Opinions welcome on the below solution, I > haven't used it much yet. It can be tricked by pathological stuff > like ifdef SOME_VAR ... endif SOME_VAR=constant_val (without any > effects on other variables in ...) earlier in the Makefile but is it > otherwise ok? > > # For putting newlines in strings: > define nl > > > endef > > # Roots of the DAG should all depend on smv (Serialized Make Variables) > bar: foo smv > # Fake build for demo: > cp $< $@ > > clean: > rm -f smv > > # This should be at the end of the Makefile (or after all var declarations): > $(file \ > >nsmv, \ > $(foreach v,$(.VARIABLES),$(flavor $(v)) var $(v) has value $($(v))$(nl))) > # Note: not removing nsmv would be tiny bit more mess but might be nice to > # be able to see what's going on. > $(shell (([ -a smv ] && (diff smv nsmv >/dev/null)) || cp nsmv smv); rm nsmv)