Makefile:(GNU)make 可以内部报告目标是否需要更新吗?

发布于 2024-10-09 18:34:28 字数 1775 浏览 3 评论 0原文

这是我的问题:我可以通过两种方式之一构建二进制文件,并且每种方式都可以对其进行检查(在它们自己的 make 目标下);我想要一个 check 目标来运行适当的目标,具体取决于在之前的 make 调用下运行的构建目标:这可以在不接触文件或某些内容的情况下在内部完成吗?记录运行哪个构建目标的其他“外部”方式?

一个例子可能会有所帮助:

.PHONY: all modified
all: $(obj)
    $(CXX) ... -o $(BIN)

modified: $(obj) $(extra_objs)
    $(CXX) ... -o $(BIN)


.PHONY: check check_all check_modified
check_all: all
    ...

check_modified: modified
    ...

check:
    # ??? Some makefile variable I don't know about?

这样我就可以向 shell 询问:

make X       # <-- X = {all, modified}
...          # <-- this is important: this is not a question of target dependency
make check   # <-- have `check' run `check_X' target

我认为特定 make 调用了解之前运行过哪个目标的唯一方法是确定它是否需要更新。 Id est,如果 all 是最新的,则运行 check_all,如果 modified 是最新的,则运行 check_modified,默认为check_all

那么,我可以在“内部”询问 make 如果我要求运行目标 X 是否会更新? “内部”意味着不调用 $(MAKE) -n,或者不 touch Y 然后询问 shell if [ -f Y ] ...< /代码>。

正如您所看到的,这不完全是依赖关系的问题,因为很明显,当我想做的只是检查它之前是否已运行过时,就会构建依赖关系。那么,有什么想法或(替代建议)吗?

更新:

好的,我想答案是:不。我能做的最好的可能是这样:

.PHONY: check
check: $(if $(wildcard $(firstword $(extra_objs))),check_modified,check_all)

显然,这种方法在功能上与创建目标之一然后检查它时创建文件相同,但在这种情况下我正在检查的文件无论如何都会被创建,并且对于创建它的目标来说是唯一的,我认为这使它稍微不那么难看。

(注意:我遇到了这样的问题:

.PHONY: check
check:
    $(MAKE) -q modified && $(MAKE) check_modified || $(MAKE) check_all

不适用于我上面的代码,因为 allmodified 都是假的,因此总是需要更新make 很重要,所以这种规则就出来了!但是,这是一种简单而简洁的方法来解决以他们创建的文件命名的目标的问题,所以我将提及它以供参考。 .)

This is my problem: I can build a binary in one of two ways and each has checks that can be done on them (under their own make targets); I would like a check target to run whichever target is appropriate dependent on which build target was run under a previous call of make: can this be done internally without touching files or some other "external" way of recording which build target was run?

An illustration may help:

.PHONY: all modified
all: $(obj)
    $(CXX) ... -o $(BIN)

modified: $(obj) $(extra_objs)
    $(CXX) ... -o $(BIN)


.PHONY: check check_all check_modified
check_all: all
    ...

check_modified: modified
    ...

check:
    # ??? Some makefile variable I don't know about?

so that I can ask this of the shell:

make X       # <-- X = {all, modified}
...          # <-- this is important: this is not a question of target dependency
make check   # <-- have `check' run `check_X' target

I figure that the only way for a particular make call to know which target was run before is by determining if it needs updating or not. Id est, if all is up-to-date, then run check_all, if modified is up-to-date then run check_modified, and default to check_all.

So, can I ask make "internally" whether target X would be updated if I asked to run it? "Internal" meaning no calling of $(MAKE) -n, or no touch Y and then asking the shell if [ -f Y ] ....

As you can see, it's not quite a question of dependency because that, clearly, will build the dependency when all I want to do is check to see whether it has been run before. So, any ideas or (alternative suggestions)?

UPDATE:

OK, I guess the answer is: No. The best I can probably do is this:

.PHONY: check
check: $(if $(wildcard $(firstword $(extra_objs))),check_modified,check_all)

Obviously, this method is functionally the same as creating a file when creating one of the targets and then checking for that, but in this case the file I'm checking for is created anyway and unique to the target that creates it, which I suppose makes it slightly less ugly.

(Note: I ran into the problem that:

.PHONY: check
check:
    $(MAKE) -q modified && $(MAKE) check_modified || $(MAKE) check_all

won't exactly work for the code I had above because all and modified are phony and so will always need updating as far as make is concerned, so that kind of rules that one out! But, it's a simple and concise way of solving the problem for targets named after the file they'd create so I'll mention it for reference.)

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

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

发布评论

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

评论(3

违心° 2024-10-16 18:34:28

也许使用 -q 标志在内部生成另一个 make 有帮助吗?

用法:make [选项] [目标] ...

选项:

[...]

-q, --question 运行否
命令;退出状态表示如果达到
日期。

Maybe spawning another make internally with the -q flag helps?

Usage: make [options] [target] ...

Options:

[...]

-q, --question Run no
commands; exit status says if up to
date.

懵少女 2024-10-16 18:34:28

您可以将构建类型记录在文件中,并稍后读回以选择正确的“检查”目标,如下所示:

all: $(obj)
    $(CXX) ... -o $(BIN)
    echo $@ > $(BIN)-kind

modified: $(obj) $(extra_objs)
    $(CXX) ... -o $(BIN)
    echo $@ > $(BIN)-kind

check: $(if $(wildcard $(BIN)-kind),check_$(shell cat $(BIN)-kind))

You could record the build type in a file and read that back later to pick the right "check" target like so:

all: $(obj)
    $(CXX) ... -o $(BIN)
    echo $@ > $(BIN)-kind

modified: $(obj) $(extra_objs)
    $(CXX) ... -o $(BIN)
    echo $@ > $(BIN)-kind

check: $(if $(wildcard $(BIN)-kind),check_$(shell cat $(BIN)-kind))
叹梦 2024-10-16 18:34:28

要回答问题的标题,请参阅双冒号规则。引用手册:

双冒号规则有些晦涩难懂,而且通常不是很有用;它们为用于更新目标的方法根据导致更新的必备文件而不同的情况提供了一种机制,但这种情况很少见。

听起来(几乎)正是您所追求的。

To answer the title of your question, see double colon rules. Quoting the manual:

Double-colon rules are somewhat obscure and not often very useful; they provide a mechanism for cases in which the method used to update a target differs depending on which prerequisite files caused the update, and such cases are rare.

Sounds (almost) just what you are after.

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