I'll ask again: do you have any reference to those statements? The official cmake docs seem to disagree about this specific case.
The cmake docs are updated on a git pull request basis by volunteers as and when someone feels they need to be updated. They are, in general, woefully out of date. And as I mentioned here before, Stephen never finished the cmake3 documentation effort he began due to changes in personal circumstance (returning home to Ireland).
Why should the root cmake be responsible for configuring a specific sub module. This is asking for cluttering everything into one single entity in a (almost) totally unrelated place. Why not keep it local to where it should be used.
I'll repeat myself yet again, but to be honest it'll be for the last time as I really don't care about this enough to spend more time repeating myself. I have other stuff to be doing than repeating myself (specifically, Outcome v2). In the cmake I mocked up we are separating concerns: "how to build this library" from "how to configure this library". It is like the intended difference between the SConstruct and SConscript files in scons: one file says what needs to be built and how they relate declaratively, the other file sets flags, optimisation, settings according to the target system etc imperatively. In exactly the same way as with scons, the non-root CMakeLists are the declarative structure describing a build graph. The rootmost CMakeLists are the imperative commands transforming some subset of that build graph into a build according to local conditions. That's the way you ought to be ideally speaking writing your cmake3. I don't know what else I can explain here. As Peter mentioned, this is 101 elementary build system theory here. It's nothing cmake specific, though because of how variable scopes usually begin with CMakeLists.txt, it does strongly encourage the imperative logic to go into the rootmost layer rather than somewhere more logically placed. But it is what it is.
One concrete example: I have networking layer which supports different transports, say tcp, libfabric, MPI and infiniband verbs. The user of my library doesn't really care about which one is used, so ideally, I would give him a compiled version of my library with the internal settings I believe are best for him. In that case, my network layer module would be configured with one of those options. Naturally, I would think, those options are defined within this very sub project. The root project really doesn't care, nor do I want that this implementation detail leaks into the users CMakeLists.txt.
Would you consider that bad practice to begin with? How would you solve this?
It depends on if you ever expect unknown third parties to want to do custom builds of your codebase. If you don't, your approach is fine, and it's easier. If you do, then you need to separate the declarative stuff from the imperative stuff. Then unknown third parties can reuse your declarative stuff, and skip or ignore your imperative stuff as they are doing a custom build.
There are tons of other use cases very similar to that. Having everything clobbering up in the root Cmakelists.txt doesn't sound appealing to me.
You obviously don't place ALL your imperative logic in the very rootmost CMakeLists. There are natural root points where build config markedly changes when you go up a directory level. That's where you locate the imperative logic. If higher level cmake wants to ignore your imperative logic, it skips over the directory with the CMakeLists with the imperative logic and adds the subdirectories of the inner directories directly, thus bringing in only the declarative parts only. So you "reach in" two directory levels to skip the imperative logic. Does this make more sense now? Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/