I think the fundamental issue boils down to aggregation. Normally, aggregation is a good thing, a variant of the divide and conquer technique which we were all taught in kindergarten you can never go wrong with. But in build systems aggregation leads to the loss of precision (rebuilding more than necessary) or accuracy (not rebuilding when necessary, rebuilding things in the wrong order), and usually both. This is the fundamental reason why "recursive make is considered harmful": we split one big graph that has the total, accurate view of all the dependencies into a number of aggregate sub-graphs. And the same happens with meta build systems where we do some part of the build (configuration, pre-build steps where we generate source code, etc) in the meta build system and the rest in the underlying build system, essentially splitting the graph into two.
P.S. And, yes, `build2` supports both dynamic prerequisites/dependencies[1] and dynamic targets[2].