Run cmake within cmake to initialize dependencies?

I want to initialize my project’s dependencies.

I know there’s FetchContent which will download the dependency and then add it as a subdirectory for my build. Some dependencies don’t play nice with this though since they generate some source files and put them in the bin dir. I’ll use zlib as my example since that’s the one that’s been relevant to me. zlib generates a header file and puts it in the binary dir. Other dependencies in the build tree that try to find zlib via find_package are unable to find it, and even if it could, zlib’s source files are now spread across multiple directories.

It was recommended to me that I use ExternalProject, but I’m not a fan of the confusion and complexities of having the dependencies installed and built when the code itself is built, rather than at configure time.

I figure I could have an external script that individually calls cmake and builds each dependency and puts the installed files somewhere, then my project (and all of its dependencies) can use the find_package module without issue. The problem is deciding what scripting language to use for that. Bash scripts or shell scrips are not cross platform without a bit of up elbow grease. I could write such a config script in something like python or powershell, but that adds another dependency to my project’s build pipeline.

My thought process then took me back to cmake. What if my main cmake script makes calls to execute_process to call git to download the dependencies, and then another call to execute_process to call cmake itself to build each dependency? I don’t see why this wouldn’t work, but my gut tells me it’s more of a hack than an actual solution.

Maybe there’s a better way to accomplish what I’m trying to do?

At the end of the day, I have a long chain of dependencies. A depends on B, B depends on C, C depends on D, A also depends on D, etc etc. I’d prefer to have D in my build once, instead of both A and C pulling in their own version of D.

Thanks for any help!

If FetchContent isn’t working, the “normal” route is to make a “superbuild” which is nothing but ExternalProject bits to build the dependencies in order. We do this here for ParaView using the paraview-superbuild. Though using that as a direct example will likely be a bit complicated, I’d recommend keeping ExternalProject-using CMake project separate from an add_library-using CMake project and instead have those communicate over find_package or something.

First of all, putting stuff in binary directory is normal (and much better than putting stuff in source directory). The project expects to be installed, which is also normal.
FetchContent is very good if you are consumer of the fetched project. As soon as you have inter-dependencies between various fetched projects it’d require perfectly-written projects to make it work. Basically the providing project must define alias targets consistent with what find_package generates, and the consuming project must check for existing target before calling find_package.

Typically this does not work and you’re just spending your energy on a futile attempts to force it to work. Maybe sometime you’ll success but it’ll cost you everything ™ :wink:

Do a superbuild, use ExternalProject. Your life will be easier.