Reputation: 11
I'm looking for a way for me to convince gnumake to build 'all' targets of a rule as a unit AND to require that they get re-built if there is any reason that ANY one of the targets is missing or out-of-date.
Consider this simple Makefile:
b.foo :
touch b.foo
b.bar1 b.bar2 : b.foo
touch b.bar1
touch b.bar2
b.zoo1 : b.bar1
touch b.zoo1
b.zoo2 : b.bar2
touch b.zoo2
# Building b.zoo1 works as expected
> make4 b.zoo1
touch b.foo
touch b.bar1
touch b.bar2
touch b.zoo1
> make b.zoo1
make: 'b.zoo1' is up to date.
# Building b.zoo2 also works as expected
> make b.zoo2
touch b.zoo2
> make b.zoo2
make: 'b.zoo2' is up to date.
# Now I remove one of the peers built with the 2nd rule
> rm b.bar2
# I see that b.zoo1 stays up-to-date because its dependency still exists.
# However, this is NOT the behavior that I'm looking for. With b.bar2
# now missing, I want b.zoo1 AND b.zoo2 to be out-of-date.
> make b.zoo1
make: 'b.zoo1' is up to date.
# But it's not. Worse yet, building b.zoo2 does force b.bar1 and b.bar2 to be rebuilt
> make b.zoo2
touch b.bar1
touch b.bar2
touch b.zoo2
# which now makes b.zoo1 out-of-date
> make b.zoo1
touch b.zoo1
So, is there any way to code up a rule that builds multiple targets to behave as I wish? Or is there a way to use the gnumake standard library to accomplish this?
Upvotes: 0
Views: 1094
Reputation: 15483
Yep, writing many targets in a rule is just shorthand for writing them out individually.
b.bar1 b.bar2 : b.foo
touch b.bar1
touch b.bar2
is exactly the same as
b.bar1: b.foo
touch b.bar1
touch b.bar2
b.bar2: b.foo
touch b.bar1
touch b.bar2
Clearly wrong. You could write
b.foo:
touch b.foo
b.bar1: b.foo
touch b.bar1
b.bar2: b.foo
touch b.bar2
b.zoo1: b.bar1 b.bar2
touch b.zoo1
b.zoo2: b.bar1 b.bar2
touch b.zoo2
Tidy this up by using $@
in a recipe as the target name
b.foo:
touch $@
b.bar1: b.foo
touch $@
b.bar2: b.foo
touch $@
b.zoo1: b.bar1 b.bar2
touch $@
b.zoo2: b.bar1 b.bar2
touch $@
Now you see the utility of many-targets-in-a-rule-is-the-same-as-writing-the-rules-out-individually. We can write this as
b.foo:
touch $@
b.bar1 b.bar2: b.foo
touch $@
b.zoo1 b.zoo2: b.bar1 b.bar2
touch $@
Nice. This fixes your original problem.
(I suspect though that this may not fix your actual problem. Is both b.bar1
and b.bar2
created by just a single run of some utility?)
Upvotes: 0
Reputation: 80931
b.bar1 b.bar2 : b.foo
this rule tells make that there are two targets b.bar1
and b.bar2
both of which have a dependency on b.foo
and both of which can be built by the listed rule. It does not tell make that they are related targets that get built by the same rule invocation. With GNU make you can tell make about the latter information by using a pattern rule like %.bar1 %.bar2: %.foo
.
I don't know that I fully understand the problem as you've explained it but I think this information (and the pattern rule) might be of use here.
Upvotes: 1