【问题标题】:Force Makefile to execute script before building targets在构建目标之前强制 Makefile 执行脚本
【发布时间】:2023-03-10 16:42:01
【问题描述】:

我正在使用 Makefile。

但是,我想在执行任何目标之前执行一个命令(zsh 脚本)。 我该怎么做?

谢谢!

【问题讨论】:

    标签: makefile target


    【解决方案1】:

    有几种技术可以在构建目标之前执行代码。你应该选择哪一个在一定程度上取决于你想要做什么,以及你为什么要这样做。 (zsh脚本是做什么的?为什么一定要执行?)

    您可以像@John 建议的那样做;将 zsh 脚本作为第一个依赖项。然后您应该将zsh 目标标记为.PHONY,除非它实际上生成了一个名为zsh 的文件。

    另一个解决方案(至少在 GNU make 中)是调用 $(shell ...) 函数作为变量赋值的一部分:

    ZSH_RESULT:=$(shell zsh myscript.zsh)
    

    这将在解析生成文件后立即执行脚本,并且在执行 任何 目标之前。如果您递归调用 makefile,它也会执行脚本。

    【讨论】:

    • 注意,$(shell ...) 即使在 make 被赋予 -n、--just-print、--dry-run、--recon 选项时也会运行。
    • 不错的答案。有什么方法可以在退出 make 时运行命令?在这里发布了一个问题:stackoverflow.com/questions/20582006/…
    • 我喜欢这种方法。但是,myscript.zsh 的输出不会被打印出来。我处于类似的情况,脚本将在调用sudo 时提示输入用户密码。
    • @Saichovsky 如果您只想打印输出,可以将 stdout 重定向到 stderr >&2。不确定它是否会让sudo 工作,因为你需要标准输入
    【解决方案2】:

    只需将其作为其他目标之一的依赖项

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

    或者,让你的第一个目标依赖它

    goal: zsh foo.exe
    

    【讨论】:

    • 这里第一个解决方案的问题是每次都会强制foo.obj重建,即使foo.c没有更新。第二个问题是现在你不能用多个目标调用你的makefile。
    【解决方案3】:

    使用 MAKECMDGOALS 和双冒号规则在 makefile 中进行预处理和后处理的解决方案。

    MAKECMDGOALS 是命令行中列出的目标。

    第一步是从命令行获取第一个和最后一个目标, 或者如果没有列出目标,请使用默认目标。

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

    双冒号规则允许按顺序执行同一目标的多个配方。您必须将所有命令行目标更改为双冒号规则。

    #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..."
    

    【讨论】:

      【解决方案4】:

      有一个解决方案无需修改您现有的Makefile(与已接受答案的主要区别)。只需创建一个 makefile 包含:

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

      唯一的缺点是前脚本和后脚本将始终运行,即使没有其他事情可做。但是,如果您使用 --dry-run 选项之一调用 make,它们将不会运行(与已接受答案的其他区别)。

      【讨论】:

        猜你喜欢
        • 2014-01-02
        • 2017-06-11
        • 2012-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        • 2019-02-24
        • 2013-01-23
        相关资源
        最近更新 更多