# Run cmake within cmake to initialize dependencies?

**URL:** <https://discourse.cmake.org/t/run-cmake-within-cmake-to-initialize-dependencies/4674>\
**Category:** Code\
**Created:** [December 15, 2021, 6:00pm UTC](https://discourse.cmake.org/t/run-cmake-within-cmake-to-initialize-dependencies/4674 "2021-12-15T18:00:54Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![MrZoraman](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mrzoraman/32/2033_2.png) [@MrZoraman](https://discourse.cmake.org/u/MrZoraman)\
**Post date:** [December 15, 2021, 6:00pm UTC](https://discourse.cmake.org/t/run-cmake-within-cmake-to-initialize-dependencies/4674/1 "2021-12-15T18:00:54Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)\
**Post date:** [December 15, 2021, 6:38pm UTC](https://discourse.cmake.org/t/run-cmake-within-cmake-to-initialize-dependencies/4674/2 "2021-12-15T18:38:50Z")

</div>

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`](https://gitlab.kitware.com/paraview/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.

---

<div class="post-metadata">

**Author:** ![fenrir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fenrir/32/734_2.png) [@fenrir](https://discourse.cmake.org/u/fenrir)\
**Post date:** [December 15, 2021, 6:41pm UTC](https://discourse.cmake.org/t/run-cmake-within-cmake-to-initialize-dependencies/4674/3 "2021-12-15T18:41:37Z")

</div>

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 ™ 😉

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