Posted By: Anonymous
.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
Invoking two rules at once:
make gitbranch-foo gitbranch-bar branch=something/blah/blah -rRd
As you can see ‘foo’ repo switches successfully but ‘bar’ repo is not even being processed by make. Why?
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?
The debugging output of ‘make’ looks like so:
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'.
Can’t make heads or tails out of it though. Any insight as to why ‘make’ behaves this way is appreciated.
Note: I’m aware I can refactor the makefile a bit like below to get it to do my bidding – I just want to understand why the original approach didn’t work as intended
.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
The answer is strictly due to
make‘s rules and has nothing to do with any of the other tags here (I’ll remove all the others). The makefile that doesn’t work says:
- to build
gitbranch-foo, we must build
- to build
gitbranch-bar, we must build
(plus of course the code for building
git-spawn-branch itself and the other associated stuff, but let’s stop here).
You then run make, telling it to build both
Make picks one of these to buildâ€”
gitbranch-foo, in this caseâ€”and begins building. Oh hey, says make to itself, this needs
git-spawn-branch to be built, and we have not done that yet. Off goes make, which builds
git-spawn-branch according to the rules. Now it’s built! Make can go back to building
gitbranch-foo. This executes the remaining recipe, which is empty.
If parallel builds are allowed,
make can also now begin building
gitbranch-foo builds. If not, we wait for
gitbranch-foo to be fully built at this point. Either way we very quickly get around to buildling
gitbranch-bar. Hm, says make to itself, this needs
git-spawn-branch to be built … but fortunately, I have done that already! Onward! Let’s make the rest of
gitbranch-bar now! That requires executing the empty recipe, which goes very quickly.
Make is now done. It has built everything required.
(The makefile that works uses
$call sensibly, directly from each rule, so that the commands that
$call expands to are required to be run for each target, rather than hidden away in a third target that can be built just once and never needs to be run any further.)
(Note that the gmake documentation mentions that a
.PHONY rule is run every time. This means once per invocation of
make, not once per invocation of the rule.)