Make a target that depends on an environment variable
I am working on a web application whose Makefile contains the following:
dist/index.html: src/templates/index.html
@bin/insert-scripts $< --output $@
bin / insert-scripts replaces <--scripts-->
one of the following in the provided file:
- the number of script tags (for jQuery, Underscore, etc.) when $ ENV is "development" or
- a single script tag (pointing to a merged, abbreviated file) when $ ENV is "production".
The problem is that if you create dist / index.html in one mode (eg "development") and then re-create it in another mode without touching the dependency, make will say nothing will be done. What I would like to do is make $ ENV dependent on dist / index.html:
dist/index.html: src/templates/index.html $ENV
@bin/insert-scripts $< --output $@
This won't work of course, so I decided to have a file named ENV that contains either "development" or "production". This file will become dependent:
dist/index.html: src/templates/index.html ENV
@bin/insert-scripts $< --output $@
Instead of setting an environment variable, the contents of the ENV file could be set. It seems a little awkward, but at least it accurately represents the dependency tree.
What is the best way to handle this situation?
source to share
So, you want to make
run scripts in the following two cases:
-
src/templates/index.html
changed - ENV the environment variable has changed since the generated
dist/index.html
The problem with this requirement is that environment variables are not timestamped. Therefore, make cannot know if the target is current.
Usually the solution in situations like this is to just have separate goals, for example. dist-development/index.html
and dist-production/index.html
. You may even find a way to use symbolic links or something to effectively direct the web application to the latest version of index.html you want . But the alternative to using an ENV file is also a possibility. I would suggest clarifying your procedure a bit:
.PHONY: ENV
ifneq "$(ENV)" "$(shell cat ENV)"
dist/index.html: ENV src/templates/index.html
@bin/insert-scripts $< --output $@
else
dist/index.html: src/templates/index.html
@bin/insert-scripts $< --output $@
endif
ENV:
echo $(ENV) >$@
This way your make will take the current $ ENV parameter and store it in a file with the correct timestamp.
source to share
If you absolutely need to provide a rebuild for changed environments, you can always use a tag file for the build environment:
.PHONY: always-rebuild
environment : always-rebuild
echo $ENV > $@.tmp
diff --quiet $@ $@.tmp || cp $@.tmp $@
rm -f $@.tmp
dist/index.html : src/templates/index.html environment
diff
ing ensures that it is environment
always rebuilt (<= checked), but is only affected when the corresponding environment variables change.
source to share
It is always best to do this when all the necessary information is encoded in the filename:
all : dist-${ENV}/index.html dist-development/index.html : src/templates/index.html ENV=development bin/insert-scripts $< --output $@ dist-production/index.html : src/templates/index.html ENV=production bin/insert-scripts $< --output $@
source to share