Makefile variable as prerequisite

后端 未结 8 607
清歌不尽
清歌不尽 2020-12-07 09:45

In a Makefile, a deploy recipe needs a environment variable ENV to be set to properly execute itself, whereas others don\'t care, e.g.:



        
相关标签:
8条回答
  • 2020-12-07 10:14

    Inline variant

    In my makefiles, I normally use an expression like:

    deploy:
        test -n "$(ENV)"  # $$ENV
        rsync . $(ENV).example.com:/var/www/myapp/
    

    The reasons:

    • it's a simple one-liner
    • it's compact
    • it's located close to the commands which use the variable

    Don't forget the comment which is important for debugging:

    test -n ""
    Makefile:3: recipe for target 'deploy' failed
    make: *** [deploy] Error 1
    

    ... forces you to lookup the Makefile while ...

    test -n ""  # $ENV
    Makefile:3: recipe for target 'deploy' failed
    make: *** [deploy] Error 1
    

    ... explains directly what's wrong

    Global variant (for completeness, but not asked)

    On top of your Makefile, you could also write:

    ifeq ($(ENV),)
      $(error ENV is not set)
    endif
    

    Warnings:

    • don't use tab in that block
    • use with care: even the clean target will fail if ENV is not set. Otherwise see Hudon's answer which is more complex
    0 讨论(0)
  • 2020-12-07 10:15

    One possible problem with the given answers so far is that dependency order in make is not defined. For example, running:

    make -j target
    

    when target has a few dependencies does not guarantee that these will run in any given order.

    The solution for this (to guarantee that ENV will be checked before recipes are chosen) is to check ENV during make's first pass, outside of any recipe:

    ## Are any of the user's goals dependent on ENV?
    ifneq ($(filter deploy other-thing-that-needs-ENV,$(MAKECMDGOALS)),$())
    ifndef ENV 
    $(error ENV not defined)
    endif
    endif
    
    .PHONY: deploy
    
    deploy: foo bar
        ...
    
    other-thing-that-needs-ENV: bar baz bono
        ...
    

    You can read about the different functions/variables used here and $() is just a way to explicitly state that we're comparing against "nothing".

    0 讨论(0)
提交回复
热议问题