强制 GNU-make 使用符号链接目标的修改时间,而不是源的修改时间

Tab*_*hka 4 unix symlink makefile gnu-make

我在 GNU make 3.81 中遇到修改时间问题。

我的 Makefile 使用从远程服务器安装的数据,由于某种我不知道的原因,该服务器已将文件的修改时间设置为遥远的未来(进入下个世纪)。

Makefile 首先在本地目录中“从未来”创建到远程文件的符号链接,然后基于此文件运行多个脚本,这些脚本都会生成一些输出文件。

现在,当我想在中断后重新运行“make all”以获取所有输出文件时,它不会使用它生成的最新输出文件重新启动(假设从脚本编号 3 开始),而是重新生成所有内容从一开始,因为它注意到第一个文件(我“从未来”符号链接该文件的文件)是较新的。

是否有一个选项可以告诉 make 采用符号链接本身的修改时间,而不是符号链接目标的修改时间?

例子

这是一个重新生成问题的最小工作示例:

设置文件夹和文件:

mkdir symlinkmake
cd symlinkmake
echo $PWD > futurefile.txt
# set file modification time to the future
touch -t 212111111111 futurefile.txt
Run Code Online (Sandbox Code Playgroud)

生成文件的内容:

all: symlink.txt first_output.txt second_output.txt

symlink.txt:
    ln -s futurefile.txt symlink.txt

first_output.txt: symlink.txt
    cut -f1 -d"/" symlink.txt > first_output.txt

second_output.txt: first_output.txt
    wc first_output.txt > second_output.txt
Run Code Online (Sandbox Code Playgroud)

现在运行make all并删除第二个输出文件。然后重新运行 make。由于第一个输出文件已经存在,因此只需要生成第二个文件。但由于futurefile.txt比任何其他文件都新,因此也会生成第一个输出文件:

make all
rm second_output.txt
make all
Run Code Online (Sandbox Code Playgroud)

在我的机器上,输出如下所示:

$ ls
Makefile        futurefile.txt  symlink.txt
$ make all
make: Warning: File `symlink.txt' has modification time 3.3e+09 s in the future
cut -f1 -d"/" symlink.txt > first_output.txt
wc first_output.txt > second_output.txt
make: warning:  Clock skew detected.  Your build may be incomplete.
$ rm second_output.txt
$ make all
make: Warning: File `symlink.txt' has modification time 3.3e+09 s in the future
cut -f1 -d"/" symlink.txt > first_output.txt
wc first_output.txt > second_output.txt
make: warning:  Clock skew detected.  Your build may be incomplete.
Run Code Online (Sandbox Code Playgroud)

Ren*_*let 5

--check-symlink-timesmake 选项,但是:

在支持符号链接的系统上,此选项使 make 除了考虑这些链接所引用的文件上的时间戳之外,还考虑任何符号链接上的时间戳。当提供此选项时,文件和符号链接中最近的时间戳被视为该目标文件的修改时间。

这不是您想要的,即仅考虑链接的时间戳。由于您无法解决日期/时间问题,我只能想象两种解决方案之一

  1. 仅订单先决条件(OOP):

    .PHONY: all
    
    all: first_output.txt second_output.txt | symlink.txt
    
    symlink.txt:
        ln -s futurefile.txt $@
    
    first_output.txt: | symlink.txt
        cut -f1 -d"/" $| > $@
    
    second_output.txt: first_output.txt
        wc $< > $@
    
    Run Code Online (Sandbox Code Playgroud)

    symlink.txt作为 OOP make 只会考虑它的存在,而不考虑它的时间戳。换句话说,make 将构建它,并(重新)构建依赖于它的所有目标(仅当它丢失时)。

    注意:我还在所有可能的地方使用了自动变量。它们很方便,不易出错,并且经常允许分解规则。

    缺点:这更像是一种快速而肮脏的黑客行为,而不是真正的解决方案。事实上,如果链接引用的文件发生变化,您的其他目标将不会重建:

    $ ls -al
    Sep 14 14:55 Makefile
    Dec  1  2018 futurefile.txt
    $ make
    ln -s futurefile.txt symlink.txt
    cut -f1 -d"/" symlink.txt > first_output.txt
    wc first_output.txt > second_output.txt
    $ ls -al
    Sep 14 14:55 Makefile
    Sep 14 15:05 first_output.txt
    Dec  1  2018 futurefile.txt
    Sep 14 15:05 second_output.txt
    Sep 14 15:05 symlink.txt -> futurefile.txt
    $ make
    make: Warning: File 'symlink.txt' has modification time 6688452 s in the future
    make: Nothing to be done for 'all'.
    make: warning:  Clock skew detected.  Your build may be incomplete.
    $ touch --date=2018-12-02 futurefile.txt
    $ ls -al futurefile.txt
    $ make
    make: Warning: File 'symlink.txt' has modification time 6774852 s in the future
    make: Nothing to be done for 'all'.
    make: warning:  Clock skew detected.  Your build may be incomplete.
    
    Run Code Online (Sandbox Code Playgroud)
  2. 为了减轻第一个解决方案的缺点,在构建目标时,您将用远程服务器的日期/时间替换本地主机的日期/时间。偶然,该touch命令有一个很好的--reference选项,可以强制一个文件的时间戳为另一个文件的时间戳:

    .PHONY: all
    
    all: first_output.txt second_output.txt
    
    first_output.txt: futurefile.txt
        cut -f1 -d"/" $< > $@
        touch --reference=$< $@
    
    second_output.txt: first_output.txt
       wc $< > $@
       touch --reference=$< $@
    
    Run Code Online (Sandbox Code Playgroud)

    缺点:随着时间的推移,您将拥有两个文件(first_output.txt和),而不是一个符号链接:second_output.txt

    $ ls -al
    Sep 14 14:55 Makefile
    Dec  1  2018 futurefile.txt
    $ make
    make: Warning: File 'futurefile.txt' has modification time 6688320 s in the future
    cut -f1 -d"/" futurefile.txt > first_output.txt
    touch --reference=futurefile.txt first_output.txt
    wc first_output.txt > second_output.txt
    touch --reference=first_output.txt second_output.txt
    make: warning:  Clock skew detected.  Your build may be incomplete.
    $ ls -al
    Sep 14 14:55 Makefile
    Dec  1  2018 first_output.txt
    Dec  1  2018 futurefile.txt
    Dec  1  2018 second_output.txt
    $ make
    make: Warning: File 'first_output.txt' has modification time 6688320 s in the future
    make: Nothing to be done for 'all'.
    make: warning:  Clock skew detected.  Your build may be incomplete.
    $ touch --date=2018-12-02 futurefile.txt
    $ ls -al futurefile.txt
    $ make
    make: Warning: File 'first_output.txt' has modification time 6688320 s in the future
    cut -f1 -d"/" futurefile.txt > first_output.txt
    touch --reference=futurefile.txt first_output.txt
    wc first_output.txt > second_output.txt
    touch --reference=first_output.txt second_output.txt
    make: warning:  Clock skew detected.  Your build may be incomplete.
    
    Run Code Online (Sandbox Code Playgroud)