Thanks for your reply, (which I’m intentionally answering in reverse order); I wanted to make sure I really knew what I was talking about before posting again.
A friend of mine told me this is the way, and I could swear I found definitive confirmation of that in the official documentation, but I’m not seeing it now. The closest thing I see is this passage in the FetchContent documentation:
Content population details should be defined separately from the command that performs the actual population. This separation ensures that all the dependency details are defined before anything might try to use them to populate content. This is particularly important in more complex project hierarchies where dependencies may be shared between multiple projects.
And I do think this discipline is very hard to maintain with an arrangement like the one I’m describing.
In what way does that not work?
I think it will help to look at an example. Please ignore the somewhat questionable way this file does everything at the top level, and the fact that I used NEVER
instead of OPT_IN
for FETCHCONTENT_TRY_FIND_PACKAGE_MODE
; those are temporary. Here are the problems I see:
- If I want to get the transitive dependency fetching stuff from my dependency before I actually add the subdirectories of any dependencies, there’s this little boilerplate dance I need to do.
- I might be able to encapsulate that in a function, but I have to break up that dance here, because I can’t just call
FetchContent_Populate
unconditionally. UnlikeFetchContent_MakeAvailable
it isn’t resilient to being called multiple times. - To know that I need to populate
SwiftCMakeXCTesting
in thiselse()
clause I have to know that my conditional dependency,GenerateSwiftXCTestMain
will populate it when I fetch its dependencies. That information should be encapsulated. - If I’ve called
FetchContent_Populate
on a dependency, the subsequent call toFetchContent_MakeAvailable
doesn’t actually make it available and I have to explicitlyadd_subdirectory
on it. And whenFetchContent_MakeAvailable
bypassesadd_subdirectory
it also bypasses a bunch of other logic I haven’t analyzed, so who knows what important things I may be missing here? - If any of these dependencies themselves do what I’m doing here in their
XXX_FetchDependencies.cmake
file, they may fetch a shared dependency before all the other dependencies I use have a chance to declare version requirements in theirFIND_PACKAGE_ARGS
. And AFAICT there’s no established way to string together a set of dependency declarations with their version requirements so that the top level can sort them out and decide what to actually fetch.