如何在 GNU make 中使用来自 HTTP 的文件作为先决条件?

pip*_*ipe 11 remote timestamps http gnu-make

我想在我的 makefile 中使用来自万维网的文件作为先决条件:

local.dat: http://example.org/example.gz
    curl -s $< | gzip -d | transmogrify >$@
Run Code Online (Sandbox Code Playgroud)

如果远程文件比本地文件新,我只想“transmogrify”,就像make正常操作一样。

希望保留的高速缓存副本example.gz -文件都很大,而且我不需要原始数据。最好我想完全避免下载文件。目标是使用-jmake 标志并行处理其中的一些。

什么是解决这个问题的干净方法?我可以想到几种方法:

  • 保留一个空的虚拟文件,每次重新创建目标时都会更新
  • 一些使用 GNU make 的新插件系统插件(我对此一无所知)
  • 在本地文件系统中挂载 HTTP 服务器的 make-agnostic 方式

在进一步挖掘之前,我需要一些建议,最好是具体的例子!

cas*_*cas 15

在你的 Makefile 中尝试这样的事情:

.PHONY: local.dat

local.dat:
    [ -e example.gz ] || touch -d '00:00' example.gz
    curl -z example.gz -s http://example.org/example.gz -o example.gz
    [ -e $@ ] || touch -d 'yesterday 00:00' $@
    if [     "$(shell stat --printf '%Y' example.gz)" \
         -gt "$(shell stat --printf '%Y' $@)"         ] ; then \
      zcat example.gz | transmogrify >$@ ; \
    fi
    truncate -s 0 example.gz
    touch -r $@ example.gz
Run Code Online (Sandbox Code Playgroud)

(注意:这是一个 Makefile,所以缩进是制表符,而不是空格。当然。\在续行之后没有空格也很重要- 或者去掉反斜杠转义符并使其变长,几乎不可读的行)

这个 GNUmake配方首先检查一个名为的文件是否example.gz存在(因为我们将使用它-zin curl),touch如果不存在则创建它。触摸创建它的时间戳为 00:00(当天上午 12 点)。

然后它使用curl's -z( --time-cond) 选项仅example.gz在自上次下载以来已被修改的情况下进行下载。 -z可以给出一个实际的日期表达式,或一个文件名。如果给定文件名,它将使用文件的修改时间作为时间条件。

之后,如果local.dat不存在,它会创建它touch,使用保证是一个时间戳年长比的example.gz。这是必要的,因为local.dat下一个命令必须存在stat以获取其 mtime 时间戳。

然后,如果example.gz时间戳比 新local.dat,它会通过管道example.gz输入transmogrify并将输出重定向到local.dat

最后,它进行簿记和清理工作:

  • 它会截断example.gz(因为您只需要保留时间戳,而不是整个文件)
  • touchesexample.gz以便它具有相同的时间戳local.dat

.PHONY 目标确保local.dat始终执行目标,即使该名称的文件已经存在。

感谢@Toby Speight 在评论中指出我的原始版本不起作用,以及为什么。

或者,如果您想直接通过管道将文件导入transmogrify而不先将其下载到文件系统:

.PHONY: local.dat

local.dat:
    [ -e example.gz ] || touch -d '00:00' example.gz
    [ -e $@ ] || touch -d 'yesterday 00:00' $@
    if [     "$(shell stat --printf '%Y' example.gz)" \
         -gt "$(shell stat --printf '%Y' $@)"         ] ; then \
      curl -z example.gz -s http://example.org/example.gz | transmogrify >$@ ; \
    fi
    touch -r $@ example.gz
Run Code Online (Sandbox Code Playgroud)

注意:这大部分未经测试,因此可能需要进行一些小的更改才能使语法完全正确。这里重要的是方法,而不是复制粘贴货物崇拜的解决方案。

几十年来,我一直在使用这种方法的变体(即touch-ing 时间戳文件)make。它有效,并且通常允许我避免在 sh 中编写自己的依赖项解析代码(尽管我不得不在stat --printf %Y这里做类似的事情)。

每个人都知道这make是一个很好的编译软件的工具...... IMO 它也是一个非常被低估的系统管理和脚本任务工具。