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?

+3


source to share


3 answers


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 generateddist/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.

+2


source


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.

+6


source


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 $@

      

+1


source







All Articles