8

我在一个 Web 应用程序上工作,其 Makefile 包含以下内容:

dist/index.html: src/templates/index.html
    @bin/insert-scripts $< --output $@

bin/insert-scripts在提供的文件中替换<--scripts-->为以下内容之一:

  • 当 $ENV 为“开发”时,许多脚本标签(用于 jQuery、Underscore 等),或
  • 当 $ENV 为“生产”时,单个脚本标签(指向连接的、缩小的文件)。

问题是,如果一个人在一种模式下构建 dist/index.html(比如“开发”),然后在另一种模式下再次构建它而不触及依赖项,make 会说没有什么可做的。我想做的是使 $ENV 成为 dist/index.html 的依赖项:

dist/index.html: src/templates/index.html $ENV
    @bin/insert-scripts $< --output $@

这当然行不通,所以我考虑有一个名为 ENV 的文件,其中包含“开发”或“生产”。该文件将成为依赖项:

dist/index.html: src/templates/index.html ENV
    @bin/insert-scripts $< --output $@

与其设置环境变量,不如设置 ENV 文件的内容。这看起来有点笨拙,但至少准确地表示了依赖关系树。

处理这种情况的最佳方法是什么?

4

3 回答 3

6

如果您绝对必须为更改的环境强制重新构建,您始终可以为构建环境使用标记文件:

.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

diffing 确保environment始终重新构建(<= 检查),但仅在相关环境变量更改时才被触及。

于 2013-02-12T21:35:06.627 回答
5

因此,您希望make在以下两种情况下运行脚本:

  • src/templates/index.html改变了
  • 自上次生成以来ENV环境变量已更改dist/index.html

这个要求的问题是环境变量没有时间戳。因此,make 无法知道目标是否是最新的。

通常在类似情况下的解决方案是简单地具有单独的目标,例如dist-development/index.htmldist-production/index.html。您甚至可以找到一种方法来使用符号链接或其他东西来有效地将 Web 应用程序指向正确的最新版本index.html。但是使用ENV文件的替代方案也是一种可能。我建议对您的程序进行一些改进:

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

这样,您的 make 将接受$ENV的当前设置并将其保存在具有正确时间戳的文件中。

于 2013-02-12T21:35:17.170 回答
2

当所有相关信息都编码在文件名中时,Make 总是最有效:

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 $@
于 2013-02-12T21:33:02.020 回答