CMake cannot find ninja when run in QtCreator - cmake

I have a call to find_program in my CMakeLists.txt file to find the path to Ninja. This returns the right value when I run ninja via the command line but fails when I run it within QtCreator:
find_program(
CMAKE_MAKE_PROGRAM
NAME ninja
PATHS /opt/local/bin
)
message(${CMAKE_MAKE_PROGRAM})
In ninja this returns:
/opt/local/bin/ninja
In QtCreator this returns:
/usr/bin/make
Why would CMake not find something that is present in the $PATH?

From the documentation of find_program():
A cache entry named by VAR is created to store the result of this command. If the program is found the result is stored in the variable and the search will not be repeated unless the variable is cleared.
In your case CMAKE_MAKE_PROGRAM happens to be cached as /usr/bin/make (probably, it was at some point set by QtCreator), so find_program() does nothing.
A proper way to switch between make and ninja would be to use CMake generators.

The variable CMAKE_MAKE_PROGRAM is cached by the CMake generator. find_program does not update a cached variable unless it contains *-NOTFOUND.
You need to use other variable in find_program call, and then update CMAKE_MAKE_PROGRAM variable with set(CACHE ... FORCE):
set(CMAKE_MAKE_PROGRAM <new-value> CACHE FILEPATH "" FORCE)
Note, that switching CMAKE_MAKE_PROGRAM from make to ninja is not a right way for change CMake generator. You need to pass a proper CMake generator via -G option to cmake itself.

Related

How do I make makefile generatedby cmake output the last command when error occur? [duplicate]

I use CMake with GNU Make and would like to see all commands exactly (for example how the compiler is executed, all the flags etc.).
GNU make has --debug, but it does not seem to be that helpful are there any other options? Does CMake provide additional flags in the generated Makefile for debugging purpose?
When you run make, add VERBOSE=1 to see the full command output. For example:
cmake .
make VERBOSE=1
Or you can add -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON to the cmake command for permanent verbose command output from the generated Makefiles.
cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON .
make
To reduce some possibly less-interesting output you might like to use the following options. The option CMAKE_RULE_MESSAGES=OFF removes lines like [ 33%] Building C object..., while --no-print-directory tells make to not print out the current directory filtering out lines like make[1]: Entering directory and make[1]: Leaving directory.
cmake -DCMAKE_RULE_MESSAGES:BOOL=OFF -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON .
make --no-print-directory
It is convenient to set the option in the CMakeLists.txt file as:
set(CMAKE_VERBOSE_MAKEFILE ON)
Or simply export VERBOSE environment variable on the shell like this:
export VERBOSE=1
cmake --build . --verbose
On Linux and with Makefile generation, this is likely just calling make VERBOSE=1 under the hood, but cmake --build can be more portable for your build system, e.g. working across OSes or if you decide to do e.g. Ninja builds later on:
mkdir build
cd build
cmake ..
cmake --build . --verbose
Its documentation also suggests that it is equivalent to VERBOSE=1:
--verbose, -v
Enable verbose output - if supported - including the build commands to be executed.
This option can be omitted if VERBOSE environment variable or CMAKE_VERBOSE_MAKEFILE cached variable is set.
Tested on Cmake 3.22.1, Ubuntu 22.04.
If you use the CMake GUI then swap to the advanced view and then the option is called CMAKE_VERBOSE_MAKEFILE.
I was trying something similar to ensure the -ggdb flag was present.
Call make in a clean directory and grep the flag you are looking for. Looking for debug rather than ggdb I would just write.
make VERBOSE=1 | grep debug
The -ggdb flag was obscure enough that only the compile commands popped up.
CMake 3.14+
CMake now has --verbose to specify verbose build output. This works regardless of your generator.
cd project
cmake -B build/
cmake --build build --verbose
It's worth noting however Xcode may not work with --verbose
Some generators such as Xcode don't support this option currently.
Another option it to use the VERBOSE environment variable.
New in version 3.14.
Activates verbose output from CMake and your build tools of choice when you start to actually build your project.
Note that any given value is ignored. It's just checked for existence.
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE will generate a file with all compilation commands.
This file is required by some LSP to know how to compile a source file out of the box, but it could also help for debugging compilation problems.
The output file is named ${CMAKE_BINARY_DIR}/compile_commands.json.

Get CMake's Ninja test command

I'm trying to make Ninja work with CMake on FreeBSD 10.3:
cmake -GNinja ..
-- Configuring done
CMake Error:
The detected version of Ninja () is less than the version of Ninja required
by CMake (1.3).
-- Build files have been written to: /home/me/pj/_build
I have put a locally compiled (from Git tag v1.8.2) Ninja in ~/bin/ninja (which is in my $PATH).
$ cmake -version
cmake version 3.4.1
$ ninja --version
1.8.2
I also tried to add -DCMAKE_MAKE_PROGRAM=ninja and -DCMAKE_MAKE_PROGRAM=~/bin/ninja without effect.
I also tried to see if Ninja was really called (by putting a script writing a new file), and it looks like it's never called.
Is there a way to see which commands are used to to check the Ninja version?
By inspecting the generated CMakeCache.txt file, you should be able to tell which Ninja version is picked by CMake.
In CMakeCache.txt you should have something similar to:
// Path to a program.
CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/ninja
which could tell which Ninja version is picked by default and whether -DCMAKE_MAKE_PROGRAM is respected or from some reason ignored.
Also, it is worth looking into the generated CMakeOutput.log and CMakeError.log files.
I would also suggest adding ninja to your PATH, hoping CMake would pick it from there.
I came across this question while getting the same error message. What I forgot to do was delete the CMakeCache.txt file before I ran cmake with the -GNinja or -DCMAKE_GENERATOR=Ninja options. So cmake was pulling the cached variable.
You can also get this error message when forgetting to call project(my_project) before calling add_library or add_executable.

Error with cmake and jsonCPP static library target "jsoncpp_lib_static"

When I try to use cmake on the jsonCPP i get the following error
CMake Error at lib_json/CMakeLists.txt:73 (INSTALL):
install TARGETS given no ARCHIVE DESTINATION for static library target
"jsoncpp_lib_static"
I use the command from readme:
cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_STATIC=ON -DJSONCPP_LIB_BUILD_SHARED=OFF -G "Unix Makefiles" ../..
From the error, it looks as though you're pointing CMake to the CMakeLists.txt inside "/jsoncpp/src" rather than the root one at "/jsoncpp".
The root CMakeLists.txt defines the variable ARCHIVE_INSTALL_DIR at this point and it's used in the "/jsoncpp/src/lib_json/CMakeLists.txt" at this point to define the target's ARCHIVE DESTINATION.
Since you're skipping the root CMakeLists.txt, this variable never gets set.
The error message mentions the path lib_json/CMakeLists.txt:73, and this is relative to the "main" CMakeLists.txt - i.e. the one you pointed CMake to when you first executed it. So CMake thinks the root is "/jsoncpp/src" instead of the real root.
Basically, to fix your error, clean out your build folder then rerun CMake to point to the "/jsoncpp" folder.
By the way, although the docs don't specifically mention it, I think the CMAKE_BUILD_TYPE is case-sensitive. You should be doing -DCMAKE_BUILD_TYPE=Debug.

How to have cmake unpack my compiler

In order to ensure that my Linux builds are identical regardless of the distribution the build host uses, I have packaged up my compiler and the sysroot files into a relocatable tar file and checked that into source control.
So the first step in any build (or at least, a step that must be invoked before any compile step) must be to extract this tar file.
If I was using a makefile, this would be simple to do. However, the project is using cmake and I can't figure out any way to do it with cmake. It might even be that I need this extract step invoked before cmake starts to detect the compiler: I can hard-code the compiler name but if cmake fails if it can't find the compiler then I need the unpack to happen before that test.
Is this possible with cmake?
You can use execute_process to invoke cmake's cross-platform command mode (cmake -E tar). The command would be something like:
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf MyCompiler.bz2)
The command which causes CMake to check for a valid compiler is project, so as long as you have your execute_process call before the project call, the unpacking will be done before the compiler check.

cmake: Selecting a generator within CMakeLists.txt

I would like to force CMake to use the "Unix Makefiles" generator from within CMakeLists.txt.
This is the command I use now.
cmake -G "Unix Makefiles" .
I would like it to be this.
cmake .
When running on windows with VC installed and a custom tool-chain.
I would expect to be-able to set the generator in the CMakeLists.txt file.
Maybe something like this.
set(CMAKE_GENERATOR "Unix Makefiles")
Here is what worked for me - create a file called PreLoad.cmake in your project dir containing this:
set (CMAKE_GENERATOR "Unix Makefiles" CACHE INTERNAL "" FORCE)
It seems to me that the variable CMAKE_GENERATOR is set too late if set in the CMakeLists.txt. If you use (even at the beginning of CMakeLists.txt)
set(CMAKE_GENERATOR "Ninja")
message("generator is set to ${CMAKE_GENERATOR}")
you can see in the output something like
% cmake ../source
-- The C compiler identification is GNU 4.9.2
...
-- Detecting CXX compile features - done
generator is set to Ninja
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/build
So the variable is only set at the very end of the generation procedure. If you use something like
set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "" FORCE)
in CMakeLists.txt, then in the very first run of cmake ../source (without -G) the default generator is used. The variable CMAKE_GENERATOR is stored in the cache, though. So if you rerun cmake ../source afterwards, it will use the generator as specified in the CMAKE_GENERATOR variable in the cache.
This is surely not the most elegant solution, though ;-) Maybe use a batch file that will actually execute the cmake -G generator for the user...
This is not what I get, when I run the same command, cmake will look for a gcc compiler / make utility. If the PATH is not set up correctly it will fail with something like:
D:\Development\build>cmake -G "Unix Makefiles" ..\source
CMake Error: CMake was unable to find a build program corresponding to "Unix Makefiles". CMAKE_MAKE_PROGRAM is not set.
You probably need to select a different build tool.
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_C_COMPILER_ENV_VAR
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_C_COMPILER
CMake Error: Could not find cmake module file:D:/Development/build/CMakeFiles/CMakeCCompiler.cmake
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_CXX_COMPILER_ENV_VAR
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_CXX_COMPILER
CMake Error: Could not find cmake module file:D:/Development/build/CMakeFiles/CMakeCXXCompiler.cmake
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!
when gcc / mingw is in the path then everything works fine. So could you provide more information as to your PATH variable or CMAKE version?
You need to set the generator at the Generate stage so it is written into the cache.
You only need to run this command once for the first configuration
cmake .. -DCMAKE_GENERATOR:INTERNAL=Ninja
This will configure Ninja as the default generator.
Later you can simply run
cmake ..
And it would use the Ninja generator as default
You can read more about it under Running CMake from the command line
When running cmake from the command line, it is possible to specify command line options to cmake that will set values in the cache. This is done with a -DVARIABLE:TYPE=VALUE syntax on the command line. This is useful for non-interactive nightly test builds.
CMake 3.19 introduces a new feature - presets. So, to select proper generator automatically, you can specify it name in CMakePresets.json.
Full description for these files available here: https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html