Make:"nothing to be done for target" 同时调用两个假目标时
Make: "nothing to be done for target" when invoking two phony targets at once
简单的 makefile:
.PHONY:\
gitbranch-foo
gitbranch-foo: dir=./foo
gitbranch-foo: git-spawn-branch
.PHONY:\
gitbranch-bar
gitbranch-bar: dir=./bar
gitbranch-bar: git-spawn-branch
.PHONY:\
git-spawn-branch
git-spawn-branch:
@$(call git_branch,$(dir),$(branch))
@echo > /dev/null
define git_branch
cd $(1); \
git checkout -b $(2) || true; \
git push -u origin $(2) || true;
endef
同时调用两条规则:
make gitbranch-foo gitbranch-bar branch=something/blah/blah -rRd
如您所见,'foo' 仓库切换成功,但 'bar' 仓库甚至没有被 make 处理。为什么?
Switched to a new branch 'something/blah/blah' <-- 'foo' switches successfully
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: Create pull request for something/blah/blah:
remote: ....
remote:
To xyz.net:foo
* [new branch] master -> something/blah/blah
Branch 'something/blah/blah' set up to track remote branch 'something/blah/blah' from 'origin'.
make: Nothing to be done for 'gitbranch-bar'. <-------- 'bar' is not even processed why?
'make' 的调试输出如下所示:
Branch 'something/blah/blah' set up to track remote branch 'something/blah/blah' from 'origin'.
Everything up-to-date
Reaping winning child 0x563e010f42d0 PID 2092
Live child 0x563e010f42d0 (git-spawn-branch) PID 2096
Reaping winning child 0x563e010f42d0 PID 2096
Removing child 0x563e010f42d0 PID 2096 from chain.
Successfully remade target file 'git-spawn-branch'.
Finished prerequisites of target file 'gitbranch-foo'.
Must remake target 'gitbranch-foo'.
Successfully remade target file 'gitbranch-foo'.
Considering target file 'gitbranch-bar'.
File 'gitbranch-bar' does not exist.
Pruning file 'git-spawn-branch'.
Finished prerequisites of target file 'gitbranch-bar'.
Must remake target 'gitbranch-bar'.
Successfully remade target file 'gitbranch-bar'.
make: Nothing to be done for 'gitbranch-bar'.
虽然不能从中得出正面或反面。任何关于 'make' 为何以这种方式行事的见解都值得赞赏。
注意:我知道我可以像下面那样重构 makefile 以让它执行我的命令 - 我只是想了解为什么原来的方法没有按预期工作
.PHONY:\
gitbranch-foo
gitbranch-foo:
@$(call git_branch,./foo,$(branch))
@echo > /dev/null
.PHONY:\
gitbranch-bar
gitbranch-bar:
@$(call git_branch,./bar,$(branch))
@echo > /dev/null
define git_branch
cd $(1); \
git checkout -b $(2) || true; \
git push -u origin $(2) || true;
endef
答案严格遵守make
的规则,与此处的任何其他标签无关(我将删除所有其他标签)。不起作用的 makefile 说:
- 要构建
gitbranch-foo
,我们必须构建 git-spawn-branch
- 要构建
gitbranch-bar
,我们必须构建 git-spawn-branch
(当然还有构建 git-spawn-branch
本身和其他相关内容的代码,但让我们到此为止)。
然后您 运行 make,告诉它同时构建 gitbranch-foo
和 gitbranch-bar
。
Make 选择其中之一进行建造——gitbranch-foo
,在这种情况下——并开始建造。 哦嘿,对自己说,这需要 git-spawn-branch
来构建,我们还没有这样做 。关闭 make,根据规则构建 git-spawn-branch
。现在已经建成了! Make 可以回去建造gitbranch-foo
。这将执行剩余的配方,它是空的。
如果允许并行构建,make
现在也可以在 gitbranch-foo
构建的同时开始构建 gitbranch-bar
。如果没有,我们等待 gitbranch-foo
此时完全构建。无论哪种方式,我们都可以很快开始构建 gitbranch-bar
。 嗯, 对自己说,这需要 git-spawn-branch
来构建...但幸运的是,我已经完成了!向前!让我们现在开始 gitbranch-bar
的剩余部分吧! 这需要执行空配方,速度非常快。
制作完成。它已经构建了所需的一切。
(有效的 makefile 明智地使用 $call
,直接来自每个规则,因此 $call
扩展到的命令对于每个目标都需要是 运行,而不是隐藏在第三个目标中,该目标只需构建一次,再也不需要 运行。)
(请注意,gmake 文档提到 .PHONY
规则每次都是 运行。这意味着 每次调用 make
, 而不是 每次调用规则 一次。)
简单的 makefile:
.PHONY:\
gitbranch-foo
gitbranch-foo: dir=./foo
gitbranch-foo: git-spawn-branch
.PHONY:\
gitbranch-bar
gitbranch-bar: dir=./bar
gitbranch-bar: git-spawn-branch
.PHONY:\
git-spawn-branch
git-spawn-branch:
@$(call git_branch,$(dir),$(branch))
@echo > /dev/null
define git_branch
cd $(1); \
git checkout -b $(2) || true; \
git push -u origin $(2) || true;
endef
同时调用两条规则:
make gitbranch-foo gitbranch-bar branch=something/blah/blah -rRd
如您所见,'foo' 仓库切换成功,但 'bar' 仓库甚至没有被 make 处理。为什么?
Switched to a new branch 'something/blah/blah' <-- 'foo' switches successfully
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: Create pull request for something/blah/blah:
remote: ....
remote:
To xyz.net:foo
* [new branch] master -> something/blah/blah
Branch 'something/blah/blah' set up to track remote branch 'something/blah/blah' from 'origin'.
make: Nothing to be done for 'gitbranch-bar'. <-------- 'bar' is not even processed why?
'make' 的调试输出如下所示:
Branch 'something/blah/blah' set up to track remote branch 'something/blah/blah' from 'origin'.
Everything up-to-date
Reaping winning child 0x563e010f42d0 PID 2092
Live child 0x563e010f42d0 (git-spawn-branch) PID 2096
Reaping winning child 0x563e010f42d0 PID 2096
Removing child 0x563e010f42d0 PID 2096 from chain.
Successfully remade target file 'git-spawn-branch'.
Finished prerequisites of target file 'gitbranch-foo'.
Must remake target 'gitbranch-foo'.
Successfully remade target file 'gitbranch-foo'.
Considering target file 'gitbranch-bar'.
File 'gitbranch-bar' does not exist.
Pruning file 'git-spawn-branch'.
Finished prerequisites of target file 'gitbranch-bar'.
Must remake target 'gitbranch-bar'.
Successfully remade target file 'gitbranch-bar'.
make: Nothing to be done for 'gitbranch-bar'.
虽然不能从中得出正面或反面。任何关于 'make' 为何以这种方式行事的见解都值得赞赏。
注意:我知道我可以像下面那样重构 makefile 以让它执行我的命令 - 我只是想了解为什么原来的方法没有按预期工作
.PHONY:\
gitbranch-foo
gitbranch-foo:
@$(call git_branch,./foo,$(branch))
@echo > /dev/null
.PHONY:\
gitbranch-bar
gitbranch-bar:
@$(call git_branch,./bar,$(branch))
@echo > /dev/null
define git_branch
cd $(1); \
git checkout -b $(2) || true; \
git push -u origin $(2) || true;
endef
答案严格遵守make
的规则,与此处的任何其他标签无关(我将删除所有其他标签)。不起作用的 makefile 说:
- 要构建
gitbranch-foo
,我们必须构建git-spawn-branch
- 要构建
gitbranch-bar
,我们必须构建git-spawn-branch
(当然还有构建 git-spawn-branch
本身和其他相关内容的代码,但让我们到此为止)。
然后您 运行 make,告诉它同时构建 gitbranch-foo
和 gitbranch-bar
。
Make 选择其中之一进行建造——gitbranch-foo
,在这种情况下——并开始建造。 哦嘿,对自己说,这需要 git-spawn-branch
来构建,我们还没有这样做 。关闭 make,根据规则构建 git-spawn-branch
。现在已经建成了! Make 可以回去建造gitbranch-foo
。这将执行剩余的配方,它是空的。
如果允许并行构建,make
现在也可以在 gitbranch-foo
构建的同时开始构建 gitbranch-bar
。如果没有,我们等待 gitbranch-foo
此时完全构建。无论哪种方式,我们都可以很快开始构建 gitbranch-bar
。 嗯, 对自己说,这需要 git-spawn-branch
来构建...但幸运的是,我已经完成了!向前!让我们现在开始 gitbranch-bar
的剩余部分吧! 这需要执行空配方,速度非常快。
制作完成。它已经构建了所需的一切。
(有效的 makefile 明智地使用 $call
,直接来自每个规则,因此 $call
扩展到的命令对于每个目标都需要是 运行,而不是隐藏在第三个目标中,该目标只需构建一次,再也不需要 运行。)
(请注意,gmake 文档提到 .PHONY
规则每次都是 运行。这意味着 每次调用 make
, 而不是 每次调用规则 一次。)