Force Makefile to execute script before building targets

后端 未结 4 1341
予麋鹿
予麋鹿 2020-12-08 10:26

I am using Makefiles.

However, there is a command (zsh script) I want executed before any targets is executed. How do I do this?

Thanks!

相关标签:
4条回答
  • 2020-12-08 10:39

    Just make that a dependancy of one of the other targets

    foo.obj : zsh foo.c 
       rule for compileing foo.c
    
    zsh: 
       rule for running zsh script.
    

    or alternatively, make your first target depend on it

    goal: zsh foo.exe
    
    0 讨论(0)
  • 2020-12-08 10:42

    There is a solution without modifying your existing Makefile (main difference with the accepted answer). Just create a makefile containing:

    .PHONY: all
    
    all:
        pre-script
        @$(MAKE) -f Makefile --no-print-directory $(MAKECMDGOALS) MAKE='$(MAKE) -f Makefile'
        post-script
    
    $(MAKECMDGOALS): all ;
    

    The only drawback is that the pre- and post- scripts will always be run, even if there is nothing else to do. But they will not be run if you invoke make with one of the --dry-run options (other difference with the accepted answer).

    0 讨论(0)
  • 2020-12-08 10:44

    There are several techniques to have code executed before targets are built. Which one you should choose depends a little on exactly what you want to do, and why you want to do it. (What does the zsh script do? Why do you have to execute it?)

    You can either do like @John suggests; placing the zsh script as the first dependency. You should then mark the zsh target as .PHONY unless it actually generates a file named zsh.

    Another solution (in GNU make, at least) is to invoke the $(shell ...) function as part of a variable assignment:

    ZSH_RESULT:=$(shell zsh myscript.zsh)
    

    This will execute the script as soon as the makefile is parsed, and before any targets are executed. It will also execute the script if you invoke the makefile recursively.

    0 讨论(0)
  • 2020-12-08 11:03

    Solution for both preprocessing and postprocessing in makefiles using MAKECMDGOALS and double colon rules.

    MAKECMDGOALS are the targets listed on the command line.

    First step is to get the first and last targets from the command line, or if there are no targets listed, use the default target.

    ifneq ($(MAKECMDGOALS),)
    FIRST_GOAL := $(word 1, $(MAKECMDGOALS))
    LAST_GOAL := $(word $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
    else
    FIRST_GOAL := all
    LAST_GOAL := all
    endif
    

    Double colon rules allow multiple recipes for the same target executed in order. You'll have to change all command line targets to double colon rules.

    #Dummy rule to set the default
    .PHONY: all
    all ::
    
    #Preprocessing
    $(FIRST_GOAL) ::
        echo "Starting make..."
    
    all :: normal_prerequistes
        normal_recipe
    
    other_stuff
    
    #Postprocessing
    $(LAST_GOAL) ::
        echo "All done..."
    
    0 讨论(0)
提交回复
热议问题