I’m having an issue with Ninja and FetchContent.
I’m trying to create a shared cmake code repository at my company.
And I would like to use FetchContent to grab this shared cmake code.
So I have the following
FetchContent_Declare(generic_cmake_modules
GIT_REPOSITORY "...."
GIT_TAG "main"
)
FetchContent_MakeAvailable(generic_cmake_modules)
However this results in this error message:
“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.”
This is because I set CMAKE_MAKE_PROGRAM (IE Ninja) in a toolchain which is inside the generic_cmake_modules repo.
Which results in this workaround where I set CMAKE_MAKE_PROGRAM before the FetchContent_Declare call.
# Explanation of why this is necessary and what is happening.
# FetchContent tries to configure the cmake modules and fails as a result of CMAKE_MAKE_PROGRAM not being defined.
# Because we define CMAKE_MAKE_PROGRAM in our toolchain, which is inside the content we are fetching. Catch22.
#
# This works around the issue
if ( CMAKE_GENERATOR MATCHES "Ninja" )
# This will get overriden by a later toolchain
set(CMAKE_MAKE_PROGRAM "C:/......./ninja/1.10.0/ninja.exe" CACHE FILEPATH "")
endif()
However this isn’t optimal since I need to be in control of the version of Ninja the client uses.
The clients shouldn’t care about the Ninja version.
What should I do?
ben.boeckel
(Ben Boeckel (Kitware))
January 4, 2021, 8:04pm
2
During the project()
call at the top-level of the project, CMake runs some initial compilations using try_compile
machinery to inspect the compiler. This requires the build tool (here, ninja
) to be available at that point. You might be able to try initializing generic_cmake_modules
before that point, but it’s not going to be easy as if that project does a project()
call, you’ll have the same problem there.
This is all happening before the project() call takes place.
The goal of this module is to set the toolchain. Which contains CMAKE_MAKE_PROGRAM.
Roughly the logic goes
FetchContent generic_cmake_modules
include(Generic)
generic_set_toolchain() <- This sets CMAKE_TOOLCHAIN_FILE which sets CMAKE_MAKE_PROGRAM
project(foobar)
ben.boeckel
(Ben Boeckel (Kitware))
January 4, 2021, 8:41pm
4
Hmm. What’s the backtrace on the code that expects CMAKE_MAKE_PROGRAM
to be set then within that rough outline?
Cmake version 3.15
D:…\cmake-3.15.1-win64-x64\share\cmake-3.15\Modules\FetchContent.cmake
execute_process(
COMMAND ${CMAKE_COMMAND} ${generatorOpts} .
RESULT_VARIABLE result
${outputOptions}
WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}"
)
if(result)
if(capturedOutput)
message("${capturedOutput}")
endif()
message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}") # <- Fails here
endif()
Running --trace-expand on the above execute_process gives me this:
Running with expanded trace output on.
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeLists.txt(4): cmake_minimum_required(VERSION 3.15.1 )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeLists.txt(10): project(foobar_cmake_modules-populate NONE )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(34): if(CMAKE_HOST_UNIX )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(74): else()
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(75): if(CMAKE_HOST_WIN32 )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(76): if(DEFINED ENV{PROCESSOR_ARCHITEW6432} )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(78): else()
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(79): set(CMAKE_HOST_SYSTEM_PROCESSOR foobar64 )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(88): if(CMAKE_TOOLCHAIN_FILE )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(108): if(CMAKE_SYSTEM_NAME )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(113): elseif(CMAKE_VS_WINCE_VERSION )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(119): else()
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(120): set(CMAKE_SYSTEM_NAME Windows )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(121): if(NOT DEFINED CMAKE_SYSTEM_VERSION )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(122): set(CMAKE_SYSTEM_VERSION 10.0.18363 )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(124): set(CMAKE_SYSTEM_PROCESSOR foobar64 )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(125): set(CMAKE_CROSSCOMPILING FALSE )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(126): set(PRESET_CMAKE_SYSTEM_NAME FALSE )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(129): include(Platform/Windows-Determine OPTIONAL )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(131): macro(ADJUST_CMAKE_SYSTEM_VARIABLES _PREFIX )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(160): ADJUST_CMAKE_SYSTEM_VARIABLES(CMAKE_SYSTEM )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(132): if(NOT CMAKE_SYSTEM_NAME )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(137): if(CMAKE_SYSTEM_NAME MATCHES BSD.OS )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(142): if(CMAKE_SYSTEM_NAME MATCHES kFreeBSD )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(147): if(CMAKE_SYSTEM_NAME MATCHES CYGWIN )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(152): set(CMAKE_SYSTEM Windows )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(154): if(CMAKE_SYSTEM_VERSION )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(155): set(CMAKE_SYSTEM Windows-10.0.18363 )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(161): ADJUST_CMAKE_SYSTEM_VARIABLES(CMAKE_HOST_SYSTEM )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(132): if(NOT CMAKE_HOST_SYSTEM_NAME )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(137): if(CMAKE_HOST_SYSTEM_NAME MATCHES BSD.OS )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(142): if(CMAKE_HOST_SYSTEM_NAME MATCHES kFreeBSD )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(147): if(CMAKE_HOST_SYSTEM_NAME MATCHES CYGWIN )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(152): set(CMAKE_HOST_SYSTEM Windows )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(154): if(CMAKE_HOST_SYSTEM_VERSION )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(155): set(CMAKE_HOST_SYSTEM Windows-10.0.18363 )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(165): if(CMAKE_BINARY_DIR )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(167): if(PRESET_CMAKE_SYSTEM_NAME )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(172): else()
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(173): file(APPEND D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/CMakeOutput.log The system is: Windows - 10.0.18363 - foobar64
)
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(179): set(INCLUDE_CMAKE_TOOLCHAIN_FILE_IF_REQUIRED )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(180): if(CMAKE_TOOLCHAIN_FILE )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeDetermineSystem.cmake(185): configure_file(D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeSystem.cmake.in D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake @ONLY )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(1): set(CMAKE_HOST_SYSTEM Windows-10.0.18363 )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(2): set(CMAKE_HOST_SYSTEM_NAME Windows )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(3): set(CMAKE_HOST_SYSTEM_VERSION 10.0.18363 )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(4): set(CMAKE_HOST_SYSTEM_PROCESSOR foobar64 )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(8): set(CMAKE_SYSTEM Windows-10.0.18363 )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(9): set(CMAKE_SYSTEM_NAME Windows )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(10): set(CMAKE_SYSTEM_VERSION 10.0.18363 )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(11): set(CMAKE_SYSTEM_PROCESSOR foobar64 )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(13): set(CMAKE_CROSSCOMPILING FALSE )
D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/3.15.1/CMakeSystem.cmake(15): set(CMAKE_SYSTEM_LOADED 1 )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeNinjaFindMake.cmake(5): find_program(CMAKE_MAKE_PROGRAM NAMES ninja-build ninja samu DOC Program used to build from build.ninja files. )
D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/CMakeNinjaFindMake.cmake(8): mark_as_advanced(CMAKE_MAKE_PROGRAM )
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 "D:/foobar_github/foobar_cmake_modules/tests/build/0/Debug/_deps/foobar_cmake_modules-subbuild/CMakeFiles/CMakeOutput.log".
CMake Error at D:/.../cmake-3.15.1-win64-x64/share/cmake-3.15/Modules/FetchContent.cmake:903 (message):
CMake step for foobar_cmake_modules failed: 1
ben.boeckel
(Ben Boeckel (Kitware))
January 4, 2021, 9:38pm
7
As I suspected, this is due to a project()
call. You’ll need to do all of this before any project()
call within the CMake codepath.
So basically the cmake workflow I want to create is just illegal. Because I’m trying to define CMAKE_MAKE_PROGRAM far too late.
ben.boeckel
(Ben Boeckel (Kitware))
January 4, 2021, 9:54pm
9
Yes. I would suggest possibly bootstrapping it with a script to download a ninja at least before launching your build. Users are going to need to make a Visual Studio (or other compiler) environment available beforehand anyways, so I don’t think adding a script execution is too much to add, but that’s me.
Gotcha. I kinda figured this was the case.