# FetchContent / CMAKE\_MAKE\_PROGRAM issue

**URL:** https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522
**Category:** Usage
**Created:** [January 12, 2021, 5:48pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522 "2021-01-12T17:48:21Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ymba9g8j9cjp0wloqf5y/32/1244_2.png) [@YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/u/YMba9g8j9CJp0wLoQf5y)
#### Post date: [January 12, 2021, 5:48pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/1 "2021-01-12T17:48:21Z")

</div>

I’ve created a GitHub repo to show a minimal reproducible example as requested by @craig.scott in the other thread:

> [@CMAKE\_MAKE\_PROGRAM 3.19 issue?](https://discourse.cmake.org/t/cmake-make-program-3-19-issue/2213/14):
>
> After looking into this more. I’m not sure it was good to have made the changes you guys did for me. Essentially the problem was me setting CMAKE\_MAKE\_PROGRAM in the toolchain. The simple fix for this was to simply just add Ninja to the path. And that doesn’t require much effort on the developer. Also a very similar issue occurs with FetchContent anyway. So we have to fix the toolchain code to not do that anyway, since the plan in the future is to grab the toolchain via FetchContent. Ove…

Basically the intent is to have a way to be in control of the version of Ninja my developers on my team use.  
And ideally not have them have to download/set Ninja themselves. I want the experience as seemless as possible. Currently this type of workflow works fine since we just have our cmake modules inside our project. The problem arises in separating the cmake code in it’s own GitHub and downloading it using fetchcontent.

The module in question:

```cmake
# example.cmake
include(GLOBAL)

function(set_ninja_version)
    set(CMAKE_MAKE_PROGRAM ${CMAKE_CURRENT_LIST_DIR}/ninja.exe)
endfunction()

```

Here is how I try and grab it:

```cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.19)

include(FetchContent)

FetchContent_Declare(ninja_issue
    GIT_REPOSITORY "https://github.com/personWhoWritesCmakeExamples/ninja_fetch_content_issue"
    GIT_TAG "main"
)

FetchContent_MakeAvailable(ninja_issue)
list(APPEND CMAKE_MODULE_PATH "${ninja_issue_SOURCE_DIR}/")
include(example)

set_ninja_version()

project(FOOBAR
    LANGUAGES "CXX"
)

```

However this fails with the following output.

```auto
C:\coolguy> cmake -S . -B build_ninja -G "Ninja"
CMake Error: CMake was unable to find a build program corresponding to "Ninja". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
-- Configuring incomplete, errors occurred!
See also "C:/coolguy/build_ninja/_deps/ninja_issue-subbuild/CMakeFiles/CMakeOutput.log".

CMake Error at C:/Program Files/CMake/share/cmake-3.19/Modules/FetchContent.cmake:977 (message):
  CMake step for ninja_issue failed: 1
Call Stack (most recent call first):
  C:/Program Files/CMake/share/cmake-3.19/Modules/FetchContent.cmake:1111:EVAL:2 (__FetchContent_directPopulate)
  C:/Program Files/CMake/share/cmake-3.19/Modules/FetchContent.cmake:1111 (cmake_language)
  C:/Program Files/CMake/share/cmake-3.19/Modules/FetchContent.cmake:1154 (FetchContent_Populate)
  CMakeLists.txt:13 (FetchContent_MakeAvailable)

-- Configuring incomplete, errors occurred!
C:\coolguy>

```

EDIT:

Link to the github: [https://github.com/personWhoWritesCmakeExamples/ninja\_fetch\_content\_issue](https://github.com/personWhoWritesCmakeExamples/ninja_fetch_content_issue)

---

<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: [January 12, 2021, 7:02pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/2 "2021-01-12T19:02:08Z")

</div>

So `FetchContent` is doing its own logic that requires `ninja`. I don’t know it well enough to say whether that loop can be broken, but it would seem kind of fundamental.

---

<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: [January 12, 2021, 7:03pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/3 "2021-01-12T19:03:21Z")

</div>

This comment indicates that what you want to do is probably just not possible without a bootstrap build tool:

> [@](#):
>
> If using `FetchContent_Populate()` within CMake’s script mode, be aware  
> that the implementation sets up a sub-build which therefore requires a CMake  
> generator and build tool to be available. If these cannot be found by  
> default, then the :variable:`CMAKE_GENERATOR` and/or  
> :variable:`CMAKE_MAKE_PROGRAM` variables will need to be set appropriately  
> on the command line invoking the script.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [January 12, 2021, 9:48pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/4 "2021-01-12T21:48:23Z")

</div>

`FetchContent` needs whatever `CMAKE_MAKE_PROGRAM` points at to exist, since it uses that tool to do the content population. It seems like in your case you already have a version of Ninja installed, you just want to download a more recent one and use that. This is quite an unusual case and not typically an arrangement I’d recommend. On Windows, I imagine you’d run into problems if you tried to replace the existing tool that is being used to run the sub-build. Saving the updated binary somewhere else and trying to switch the main project to this new location after the configuration processing has already started seems risky.

Maybe the simpler solution is to just have some kind of separate script your devs can run to go and grab the latest Ninja. They should run that script outside of any project processing.

---

<div class="post-metadata">

### Author: ![YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ymba9g8j9cjp0wloqf5y/32/1244_2.png) [@YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/u/YMba9g8j9CJp0wLoQf5y)
#### Post date: [January 13, 2021, 8:04pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/5 "2021-01-13T20:04:58Z")

</div>

> [@craig.scott](#):
>
> It seems like in your case you already have a version of Ninja installed, you just want to download a more recent one and use that.

I’m not trying to do that.

The workflow I’m trying to create in this example is ideally developers never have to leave CMake.

- Developer joins team
- cmake -S . -B build -G “Ninja”
- They just get Ninja downloaded for them. With the exact version I want them to have.

Why I want this.

- Knowing what version of Ninja developers are using.
- All they need is one build command to start contributing to the project.

But based off of everything I understand FetchContent isn’t the tool I should be using for this.

---

<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: [January 13, 2021, 8:36pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/6 "2021-01-13T20:36:33Z")

</div>

I think writing a CMake script which downloads ninja an places it somewhere would be best. See [how CMake does it for CI](https://gitlab.kitware.com/cmake/cmake/blob/master/.gitlab/ci/ninja.ps1) (in powershell, but CMake code is just less verbose). You can then do:

```cmake
cmake_minimum_required(VERSION X.Y)
if (NOT EXISTS "${CMAKE_SOURCE_DIR}/.build-tools/ninja.exe")
  execute_process(COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/.build-tools/get-ninja.cmake")
endif ()
if (NOT CMAKE_MAKE_COMMAND AND CMAKE_GENERATOR MATCHES "Ninja")
  set(CMAKE_MAKE_COMMAND "${CMAKE_SOURCE_DIR}/.build-tools/ninja.exe" CACHE FILEPATH "")
endif ()
project(myproject)

```

Some error checking may be warranted.

---

<div class="post-metadata">

### Author: ![YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ymba9g8j9cjp0wloqf5y/32/1244_2.png) [@YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/u/YMba9g8j9CJp0wLoQf5y)
#### Post date: [January 13, 2021, 11:11pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/7 "2021-01-13T23:11:17Z")

</div>

Your are very much getting to the heart of my desires here 😃

The problem is this works fine now for 1 project.

The problem is how do I share that code you wrote with multiple projects at my company.

Because ideally we are trying to standardize the build process for our software.

Ideally I’d have that shared code you wrote in a cmake module repo.

And ideally I’d fetch that cmake module repo using fetchcontent.

But that’s how this whole problem kinda started.

---

<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: [January 13, 2021, 11:26pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/8 "2021-01-13T23:26:17Z")

</div>

I’d just stuff it in a submodule if you really want the hassle of a submodule for a single CMake script and 8 lines of boilerplate. If you already have modules, sounds fine to me 🙂 .

Basically: bootstrapping is hard; everything needs to start somewhere. You’re digging close to the bottom of this well 🙂 .

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [February 21, 2023, 10:10pm UTC](https://discourse.cmake.org/t/fetchcontent-cmake-make-program-issue/2522/9 "2023-02-21T22:10:56Z")

</div>

Not trying to resurrect an old thread, but leaving the below comment after ending up here while following links of a [recent discussion](https://discourse.cmake.org/t/built-in-package-manager-for-cmake-modules/7513).

> [@craig.scott](#):
>
> `FetchContent` needs whatever `CMAKE_MAKE_PROGRAM` points at to exist, since it uses that tool to do the content population.

There was [work I did for FetchContent](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5749) which avoided using a sub-build, but I had to [revert it](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5898) after it broke some existing behavior. I still harbour a desire to bring that change back in a form that avoids the previous problems. The performance gains on Windows especially make that highly desirable. As a nice side benefit, it would remove the above-mentioned problem and allow the original pattern discussed in this post to work (download the Ninja build tool via FetchContent before the first `project()` call).

I don’t know if or when I’ll get a chance to revisit that work for FetchContent, but it is still very much on my radar.
