CMake --build verbosity - cmake

I run cmake to generate a VS2019 project:
> cmake -B Debug -S . --log-level=TRACE -G "Visual Studio 16 2019" -A Win32
I build it with:
> cmake --build Debug
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Checking Build System
<snip>
I'd like to see the exact command line CMake is executing to actually start the build engine.
using cmake --build Debug -v outputs more information but still doesn't show how the Build Engine was launched.
I have also tried this, which failed:
>cmake --debug-output --trace --build Debug
Running with debug output on.
Running with trace output on.
CMake Error: Unknown argument --build
CMake Error: Run 'cmake --help' for all supported options.
putting --debug-output and --trace after --build also fails:
>cmake --build Debug --debug-output --trace
Unknown argument --debug-output
Usage: cmake --build <dir> [options] [-- [native-options]]
cmake --build --preset <preset> [options] [-- [native-options]]
Options:
<snip>
How can I get cmake --build to output the exact command (exe & arguments) that is being used for building? And how do I affect it?

For Visual Studio generator CMake uses MSBuild (or whatever the generator is configured for, actually, i think it's kind of "implementation-defined" feature, which is not supposed to be exposed to the users).
You can find full list of MSBuild command-line options here. In order to provide the build tool with the said options use <build-tool-options> of CMake's --build command. E.g. here is (quite verbose) logging:
cmake --build Debug -- -v:d
How can I get cmake --build to output the exact command (exe &
arguments) that is using for building?
As I proposed originally you better just live with the abstractions provided by CMake, but one trick that you may find handy (and it kind of works independently from the build tool) is to try to specify some garbarge options for the tool, so it triggers error and exposes some details:
cmake --build Debug -- garbarge
In this case MSBuild actually prints exactly the command which failed (with original + garbarge arguments):
MSBUILD : error MSB1008: Only one project can be specified.
Full command line: '"C:/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/amd64/MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration=Debug /p:Platform=x64 /p:VisualStudioVersion=17.0 /v:m garbarge'

Related

Can cmake --build use msbuild instead of devenv

I'm using CMake 3.23 with Visual Studio 2022. From everything I found about cmake --build command it should be running msbuild, but evidently it's running devenv instead. Is there some setting I'm not aware of? How do I get it to run msbuild so I can pass options to it?
This is my generator command:
cmake -G "Visual Studio 17" -A x64 -T v143 ..
And then cmake --build is running devenv instead of msbuild:
cmake --build . --config Release -- /verbosity:detailed
Microsoft Visual Studio 2022 Version 17.2.3.
Copyright (C) Microsoft Corp. All rights reserved.
Invalid Command Line. Unknown Switch : verbosity:detailed.
Use:
devenv [solutionfile | projectfile | folder | anyfile.ext] [switches]
CMake by default is using MSBuild and falls back to devenv if you either requested it deliberately (with CMAKE_MAKE_PROGRAM) or you have an Intel Fortran project in which case it has to use devenv.
You can check if it found MSBuild by checking the CMAKE_VS_MSBUILD_COMMAND variable. And you can force CMake to use MSBuild by setting CMAKE_MAKE_PROGRAM to the MSBuild path (although I don't know how it will behave if you have a Fortran project).

How to perform verbose builds of a CMake project with Visual Studio 2019 generator

I am using Clion to work on a CMake project which needs to be built with a Visual Studio 16 2019 generator. When I run a build, Clion performs the following command:
$ cmake.exe --build C:\<PATH_TO_PROJECT>\cmake-build-release --target FooTarget --config Release
With this workflow now I would like to get verbose builds in order to troubleshoot which commands and command line arguments are being used by each build.
Is it possible to get cmake to run verbose builds while using a Visual Studio 2019 generator?
CMake supports passing generator-specific compiler flags as build tool options.
If you're using a Visual Studio generator, you can pass MsBuild command line options such as -verbosity:level with a command like:
cmake.exe --build C:\<PROJECTDIR>\cmake-build-debug --target <BUILDTARGET> --config Debug -- -verbosity:diagnostic
In Clion, just open the project's CMake settings and add -- -verbosity:diagnostic to the "build options" line edit.

What happened to CMake's --target argument?

With CMake version 3.19.2 I can use --target argument to build specific targets, instead of all.
For example --target tests to build tests.
However, with CMake 3.22.1 I'm getting an error like this:
CMake Error: Unknown argument --target
CMake Error: Run 'cmake --help' for all supported options.
You can see the manual of CMake here:
https://cmake.org/cmake/help/latest/manual/cmake.1.html
(There is a drop-down list for version selection)
It describes the --target argument, and It doesn't seem any different from what it was earlier. Nonetheless, after switching from 3.19.2 to 3.22.1 it doesn't let me use --target.
#EDIT thank you for your feedback, here's what I use:
cmake -G Ninja -DCROSS_COMPILER_PREFIX=<some_prefix> -Dsomeothervariables=1 --target tests $directory_with_cmake_project
It works with 3.19.2, but executing the same thing with cmake 3.22.1 causes the error.
I expect that the order of providing -G Ninja, variables, target directory and --target matters, but I haven't managed to get it to work in any order I could think of.
CMake is composed of stages - first you configure the project, then you build it:
configuration stage cmake <sourcedir> ... https://cmake.org/cmake/help/v3.22/manual/cmake.1.html#generate-a-project-buildsystem
build stage cmake --build <builddir> ... https://cmake.org/cmake/help/v3.22/manual/cmake.1.html#build-a-project
--target argument if for the build stage, and it is invalid for configuration stage, hence your error.
CMake prints this message, if you haven't specified a directory to build by passing --build <some dir> first. (The --target option only if mentioned in this usage version of the cmake command line tool, see the documentation.)
Wrong
cmake --target foo
CMake Error: Unknown argument --target
CMake Error: Run 'cmake --help' for all supported options.
Correct
(assuming in the subdirectory build of the current working directory contains a configured cmake project with a target foo).
cmake --build build --target foo

CMake build types make no difference

I've worked in c++ for many years but I am new to CMake.
I build my app with
cmake --build build_dir --config Debug --target all -- -j 1
This works fine and builds the Debug version.
If I change the --config to anything else, for example Release with the following command:
cmake --build build_dir --config Release --target all -- -j 1
ninja says "no work to do" and exits. Running the compiled app it is clearly not optimised. There are two other options in this Cmake Project, RelWithDebug and MinSizeRel, and they act the same.
In CmakeLists.txt there is:
set(CMAKE_CONFIGURATION_TYPES "Release;Debug;MinSizeRel;RelWithDebInfo")
There are a lot of other mentions of the various types, but it's all slightly greek to me at this time.
What can I do to work out where the issue is?
I'm going to give you the full in depth answer. Just in case someone else has this confusion.
What is a generator?
Essentially a generator is the build system CMake creates. CMake doesn't directly build your project. Because CMake is a meta-build system. IE CMake is a build system that 'generates' your true build system. That's why it is called a 'generator'.
"Visual Studio 16 2019" was designed to handles multiple configurations in 1 build.
Which is why when you open a Visual Studio project created by CMake you can easily change between Debug, Release, etc.
Where as "Unix Makefiles" and "Ninja" can only handle 1 config type at a time.
This difference in build system abilities leads to slightly different CLI when running CMake.
Visual Studio 16 2019 (Multi-Config)
As mentioned before Visual Studio supports multiple config types in the build.
cmake -S . -B build/vs -G "Visual Studio 16 2019"
cmake --build build/vs --config Debug
cmake --build build/vs --config Release
In the first command you are creating the Visual Studio 2019 project.
In the second command you are actually building the binaries. And since Visual Studio projects are multi-config you don't need a different build folder for each type. Since Visual Studio handles it for you!
Ninja (Single Config)
cmake -S . -B build/ninja/ -G "Ninja" -D CMAKE_BUILD_TYPE=Debug
cmake --build build/ninja/
# Now I've updated the project to make Release binaries
cmake -S . -B build/ninja/ -D CMAKE_BUILD_TYPE=Release
cmake --build build/ninja/
In the example above you create a Ninja project for a debug build. Then you build it.
Then you create a Ninja project for a release build. Then you build it.
Notice how you have to manually specify 2 build folders for each type yourself.
Ninja Multi-Config (new in CMake 3.17)
Thanks to advances in Ninja and CMake you can create avoid the hassle of specifying the build type at project creation time. So now it's just like Visual Studio.
So now you can create a "Ninja Multi-Config" project instead of just a "Ninja" project.
cmake -S . -B build/nin -G "Ninja Multi-Config"
cmake --build build/nin --config Debug
cmake --build build/nin --config Release
Further Elaboration
Single Config Vs Multi-Config
How can you tell if your generator is Multi vs Single?
Read the docs. Or if you need to in your scripts you can check it programmatically.
You can query the global property GENERATOR_IS_MULTI_CONFIG
CMAKE_BUILD_TYPE
A minor thing to mention is that CMAKE_BUILD_TYPE doesn't do anything on multi-config generators. So avoid using it in your CMake code.
See this answer: CMAKE_BUILD_TYPE is not being used in CMakeLists.txt

the option "--build" of cmake

I want to use the cmake --build command to build my project.
This command has a --config option. I don't know how many different parameters I can assign to. And I found cmake doesn't check if the parameter of --config is correct or not
You can call cmake --build like this:
cmake --build . --target MyExe --config Debug
This would be run from your build root, since the directory is passed as ., and would build the target MyExe in Debug mode.
If your build tool is a multi-configuration one (like devenv on Windows), the --config argument matters. If you pass an invalid parameter as the config type here, the build tool should give an error.
If the build tool isn't multi-config (like gcc), then the --config argument is ignored. Instead the build type is set via the CMAKE_BUILD_TYPE CMake variable; i.e. it's set when running CMake, not when running the build tool.
You can pass further options to the build tool by adding them at the end after a --, e.g to pass -j4 if using gcc:
cmake --build . --target MyExe -- -j4