I did some digging into this example with Ninja, and from what I can tell, the crux of the problem is that the executable targets end up with an order-only dependency on the linker.ld-target
custom target. I think that explains why the first build works (no targets are up to date yet), but the second build after modifying ex2.cpp doesn’t cause ex1 to be relinked. That’s a bit of a guess on my part, but I couldn’t see any else immediately obvious which may explain the behavior.
This is getting a bit beyond my understanding of the nitty gritty details of the way dependencies are defined. We may need input from @brad.king on this one. I would have expected your example to work, but maybe there’s some subtle aspect of this I’m overlooking.