gnu make reloads 包含但不更新目标

发布于 2024-09-25 13:50:08 字数 731 浏览 2 评论 0原文

我正在尝试创建一个 Makefile,它将下载并处理文件以生成目标,这是一个简化版本:

default: all
.PHONY: all clean filelist.d
clean:
    @rm -fv *.date *.d

#The actual list comes from a FTP file, but let's simplify things a bit
filelist.d:
    @echo "Getting updated filelist..."
    @echo "LIST=$(shell date +\%M)1.date $(shell date +\%M)2.date" > $@
    @echo 'all: $$(LIST)' >> $@

%.date:
    touch $@

-include filelist.d

不幸的是,目标在第一次运行时没有正确更新,需要再次运行才能获得文件。这是我从中得到的输出:

 $ make
Getting updated filelist...
make: Nothing to be done for `default'.
 $ make
Getting updated filelist...
touch 141.date
touch 142.date
touch 143.date

我正在使用 GNU Make 3.81,其文档指出,如果包含的文件发生更改,它会重新加载整个内容。出了什么问题?

I'm trying to create a Makefile that will download and process file a file to generate targets, this is a simplified version:

default: all
.PHONY: all clean filelist.d
clean:
    @rm -fv *.date *.d

#The actual list comes from a FTP file, but let's simplify things a bit
filelist.d:
    @echo "Getting updated filelist..."
    @echo "LIST=$(shell date +\%M)1.date $(shell date +\%M)2.date" > $@
    @echo 'all: $(LIST)' >> $@

%.date:
    touch $@

-include filelist.d

Unfortunately the target all doesn't get updated properly on the first run, it needs to be run again to get the files. This is the output I get from it:

 $ make
Getting updated filelist...
make: Nothing to be done for `default'.
 $ make
Getting updated filelist...
touch 141.date
touch 142.date
touch 143.date

I'm using GNU Make 3.81 whose documentation states that it reloads the whole thing if the included files get changed. What is going wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

删除→记忆 2024-10-02 13:50:08

您已将 filelist.d 指定为 .PHONY 目标,因此 make 认为创建该目标实际上不会更新指定的文件。然而,它确实如此,并且新内容将在下次运行时使用。对于第一次运行,丢失的文件不是错误,因为 include 带有破折号前缀。

从 .PHONY 中删除 filelist.d。但是,请记住,在删除它之前它不会再次重新生成(因为它不依赖于任何东西)。

出于同样的原因,您应该在 .PHONY 中包含“default”。


我编写了一个 shell 脚本,而不是将所有这些都集中在 makefile 中:

#!/bin/bash
# Check whether file $1 is less than $2 days old.

[ $# -eq 2 ] || {
  echo "Usage: $0 FILE DAYS" >&2
  exit 2
}

FILE="$1"
DAYS="$2"

[ -f "$FILE" ] || exit 1  # doesn't exist or not a file

TODAY=$(date +%s)
TARGET=$(($TODAY - ($DAYS * 24 * 60 * 60)))
MODIFIED=$(date -r "$FILE" +%s)

(($TARGET < $MODIFIED))

将 X 替换为再次下载 filelist.d 之前可以经过的最大天数:

filelist.d: force-make
        ./less-than-days $@ X || command-to-update
.PHONY: force-make
force-make:

现在 filelist.d 依赖于 .PHONY 目标,而不是假冒的目标。这意味着 filelist.d 始终是过时的(虚假目标始终是“新的”),但其配方仅定期更新文件。

不幸的是,这需要您将更新命令编写为单个命令,如果命令太长,空间可能会成为问题。在这种情况下,我也会把它放在一个单独的脚本中。

You have specified filelist.d as a .PHONY target, so make believes making that target doesn't actually update the specified file. However, it does, and the new contents are used on the next run. For the first run, the missing file isn't an error because include is prefixed with the dash.

Remove filelist.d from .PHONY. However, remember it won't be regenerated again until you delete it (as it doesn't depend on anything).

By the same token, you should include "default" in .PHONY.


I wrote a shell script rather than lump all this in the makefile:

#!/bin/bash
# Check whether file $1 is less than $2 days old.

[ $# -eq 2 ] || {
  echo "Usage: $0 FILE DAYS" >&2
  exit 2
}

FILE="$1"
DAYS="$2"

[ -f "$FILE" ] || exit 1  # doesn't exist or not a file

TODAY=$(date +%s)
TARGET=$(($TODAY - ($DAYS * 24 * 60 * 60)))
MODIFIED=$(date -r "$FILE" +%s)

(($TARGET < $MODIFIED))

Replace X with the max number of days that can pass before filelist.d is downloaded again:

filelist.d: force-make
        ./less-than-days $@ X || command-to-update
.PHONY: force-make
force-make:

Now filelist.d depends on a .PHONY target, without being a phony itself. This means filelist.d is always out of date (phony targets are always "new"), but its recipe only updates the file periodically.

Unfortunately, this requires you to write the update command as a single command, and space may be a problem if it is long. In that case, I would put it in a separate script as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文