CMake coloring errors and warnings - c++

Is there a way how to produce a colorful output from gcc which is called from Makefile generated by cmake? It would make debugging application a lot easier.

Do you want colourful output from cmake binary? For that I don't know any solution.
CMake can generate Makefiles that provide verbose (and colourful) information about the build process. This can be enabled in the following way:
SET(CMAKE_COLOR_MAKEFILE ON)
# And optionally
SET(CMAKE_VERBOSE_MAKEFILE ON)
If you want to have the gcc output colourised, then have a look at colorgcc perl script. Having it installed try something like this:
CC=/usr/bin/colorgcc cmake .....
Or use the newer solution proposed in another answer by gfour - the gccfilter

Other tools are not necessary now. GCC and Clang produce color output but hide it when they detect they're being used in a pipeline like CMake Makefiles use. They have flags to force color though.
CMakeLists.txt:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options(-fdiagnostics-color=always)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options(-fcolor-diagnostics)
endif()
If you do pipe the output of make sometimes, you can put this behind a flag.
Color output preview:
Reference:
https://medium.com/#alasher/colored-c-compiler-output-with-ninja-clang-gcc-10bfe7f2b949

Download gccfilter (needs perl, libregexp and libgetopt-argvfile), then run:
gccfilter -c cmake ...
This will colorize the messages from the build process (which I assume are gcc mesages).

Try colout, it is designed to seamlessly color the output of any command, and comes with a g++ AND a cmake theme, which you can use together:
make something 2>&1 | colout -t cmake | colout -t g++
Besides improving the cmake colorscheme, it even applies syntax coloring on the code printed out by g++.

Since CMake v3.24, there is the CMAKE_COLOR_DIAGNOSTICS variable. Follow that link for the most up-to-date version of the docs. Here is a quote from the 3.24.2 docs:
Enable color diagnostics throughout.
This variable uses three states: ON, OFF and not defined.
When not defined:
Makefile Generators initialize the CMAKE_COLOR_MAKEFILE variable to ON. It controls color buildsystem messages.
GNU/Clang compilers are not invoked with any color diagnostics flag.
When ON:
Makefile Generators produce color buildsystem messages by default. CMAKE_COLOR_MAKEFILE is not initialized, but may be explicitly set to OFF to disable color buildsystem messages.
GNU/Clang compilers are invoked with a flag enabling color diagnostics (-fcolor-diagnostics).
When OFF:
Makefile Generators do not produce color buildsystem messages by default. CMAKE_COLOR_MAKEFILE is not initialized, but may be explicitly set to ON to enable color buildsystem messages.
GNU/Clang compilers are invoked with a flag disabling color diagnostics (-fno-color-diagnostics).
If the CMAKE_COLOR_DIAGNOSTICS environment variable is set, its value is used. Otherwise, CMAKE_COLOR_DIAGNOSTICS is not defined by default.

Based on this discussion I've created an alias in ~/.bashrc for make:
alias make="make VERBOSE=1 2>&1 | sed -e 's%^.*: error: .*$%\x1b[37;41m&\x1b[m%' -e 's%^.*: warning: .*$%\x1b[30;43m&\x1b[m%'"
it's not really nice solution, but it does the job.

Related

In CMake, how do you change default compiler flags for a build type on a per-user basis? [duplicate]

This question already has answers here:
Change default value of CMAKE_CXX_FLAGS_DEBUG and friends in CMake
(2 answers)
Closed 5 years ago.
In cmake, the default release compiler flags for gcc are -O2 -DNDEBUG. I want them to be -Ofast -NDEBUG. And I want that to be true for every project I do things with in cmake without imposing that choice on any other consumers of my project.
How do I do that?
I could edit them into that project's CMakeLists.txt file. But then I'm forcing other people to agree with my choice. Also, I have to be really careful about how I do it to make sure that I only affect compilers for which that is a valid set of flags to use.
I could use ccmake on every project every time I check out a new tree or create a new build environment. But that's a huge hassle when I want to set the flags to the same thing every time.
Is there a way to set it up so that for me, personally, the default compiler flags for clang and gcc for the various build types are what I want them to be?
Similarly, it's noticing I have ccache and gcc. And that's fine. But it might be nice to force a different default choice for compiler as well, but just for me personally, not for anybody else who chooses to use my project.
Is this possible?
I normally set compiler flags in cmakelists.txt by adding an environment variable into my build script, then referencing that in cmakelists.txt.
#build.sh
export MY_CXXFLAGS="-std=gnu++11 -Ofast -NDEBUG -Wall -Wno-unused-function -Wno-unknown-pragmas"
cmake `pwd` -Dtest=ON
make -j9
Then in my CMakeLists.txt, I'll have the following line:
SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{MY_CXXFLAGS}")
It's simple then to pass arguments to build.sh, which is just a bash script, to change the content of MY_CXXFLAGS, based on the users needs. (E.g. build.sh -b DEVELOP|DEBUG|RELEASE etc).
My current answer to this question is to create a global ~/.config/Kitware/default.cmake file that contains initial cache settings and to use cmake -C <path to default.cmake> ... remainder of cmake options ... to run cmake.
In the process of figuring this out I initally named the file ~/.config/Kitware/CMakeCache.txt and found something quite odd that appears to be a bug in cmake. I posted this question about it: Why does this cmake initial cache file result in such strange errors?

How to add preprocessor definitions on CMake's command line? [duplicate]

I try to set a preprocessor macro in the command line of CMake. I've tried:
set generator="Visual Studio 8 2005"
set params=-D MY_MACRO=1
cmake.exe -G %generator% %params% ..\some_project
but it's neither defined when I compile nor can I find the name MY_MACRO in the files generated by CMake at all, except for CMakeCache.txt where it's present in the form:
MY_MACRO:UNINITIALIZED=1
How can I do it?
A good alternative would be to define a cmake option:
OPTION(DEFINE_MACRO "Option description" ON) # Enabled by default
Followed by a condition:
IF(DEFINE_MACRO)
ADD_DEFINITIONS(-DMACRO)
ENDIF(DEFINE_MACRO)
Then you can turn that option ON/OFF via command line with cmake using the -D flag. Example:
cmake -DDEFINE_MACRO=OFF ..
To make sure the compiler is receiving the definition right, you can call make in verbose mode and check for the macro being defined or not:
make VERBOSE=1
This is a good solution also because make will recompile your code when any of cmake options changes.
Try this: -D CMAKE_CXX_FLAGS=/DMY_MACRO=1
The motivation behind the question was to batch build 3rd party libraries, which is why I wanted to avoid modifying CMakeLists. So years later, even though I don't need that anymore, I figured out that it's easily achievable by means external to CMake:
Invoke CMake as usual, no special flags.
Then:
With MSVC: The compiler reads the CL environment variable to get extra command line arguments. So
set CL=/DMY_MACRO=1 %CL%
then invoke MSBuild to do its job.
With Makefiles: The generated makefiles use the CFLAGS and CXX_FLAGS variables as makefiles are expected to do. So the build can be started by
make CXX_FLAGS=-DMY_MACRO=1
or by setting the corresponding environment variables.
Unless you have a good reason not to, you should use ADD_DEFINITIONS(<name>=<value>[, ...]).
Just add the following line to your CMakeLists.txt:
ADD_DEFINITIONS("MY_MACRO=1")
CMake will take care of the syntax of the switches (be it -D<name>=<value>, or /D<name>=<value>).

Which variable for compiler flags of CMake's ADD_LIBRARY function?

Does exist a variable which contains the compiler flags used in some call to CMake's ADD_LIBRARY function, for example the ones used when we add a module:
ADD_LIBRARY(mylib MODULE mysrc.cpp)
Or, is there a way of getting such flags?
Turning my comments into an answer
There is not a single CMake variable to get the all compiler flags. The problem is that the CMake generator will finally put together the compiler flags (from various CMake variables and properties incl. from depending targets). So you don't have all the flags during configuration step.
I see the following possible problem/solution pairs:
CMake is a cross-platform wrapper around your compiler (that's actually what the C stands for), so no need to extract the compiler flags into an external script
If you just want to add sort of a filter to what is called by CMake you can user set "launcher" variables/properties accordingly e.g. CMAKE_CXX_COMPILER_LAUNCHER or RULE_LAUNCH_LINK
If you want the compiler calls in a machine readable JSON format you could export those by setting CMAKE_EXPORT_COMPILE_COMMANDS
If you just want to see the compiler calls incl. all the flags you could set CMAKE_VERBOSE_MAKEFILE
If you really just need the compiler flags on the output and you don't want CMake to actually compile anything, you could - at least for CMake's Makefile generators - modify CMAKE_CXX_COMPILE_OBJECT and CMAKE_CXX_CREATE_SHARED_MODULE like this:
set(CMAKE_DEPFILE_FLAGS_CXX "")
set(
CMAKE_CXX_COMPILE_OBJECT
"<CMAKE_COMMAND> -E echo <FLAGS>"
)
set(
CMAKE_CXX_CREATE_SHARED_MODULE
"<CMAKE_COMMAND> -E echo <CMAKE_SHARED_MODULE_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS>"
)
file(WRITE mysrc.cpp "")
add_library(mylib MODULE mysrc.cpp)
References
Is Cmake set variable recursive?
What does the "c" in cmake stand for?
How to use CMAKE_EXPORT_COMPILE_COMMANDS?
Using CMake with GNU Make: How can I see the exact commands?
Retrieve all link flags in CMake

Using compiler prefix command(s) with CMake (distcc, ccache)

There are utilities which use an existing compiler by adding a command as a prefix (so instead of calling cc -c file.c you could call distcc cc -c file.c).
When using CMake the compiler command can be changed, however I ran into problems trying to use distcc, though this would likely apply to any command prefix to the compiler (ccache too).
CMake expects the compiler to be an absolute path,so setting CMAKE_C_COMPILER to /usr/bin/distcc /usr/bin/cc, gives an error:
/usr/bin/distcc /usr/bin/cc
is not a full path to an existing compiler tool.
Setting the compiler to /usr/bin/distcc andCMAKE_C_COMPILER_ARG1 or CMAKE_C_FLAGS to begin with /usr/bin/cc works in some cases, but fails with CHECK_C_SOURCE_COMPILES(checked if there was some way to support this, even prefixing CMAKE_REQUIRED_FLAGS didn't work).
The only way I found to do this is to wrap the commands in a shell script.
#!/bin/sh
exec /usr/bin/distcc /usr/bin/cc "$#"
While this works, It would be nice to be able to use compiler helpers with CMake, without having to go though shell scripts (giving some small overhead when the build system could just use a command prefix).
So my question is:
Can CMake use compiler prefix commands (such as distcc) directly?, without shell script wrappers?
Since CMake 3.4.0 there has been a CMAKE_<LANG>_COMPILER_LAUNCHER variable and corresponding target property <LANG>_COMPILER_LAUNCHER. So if your project is C-only you would do something like:
cmake -DCMAKE_C_COMPILER_LAUNCHER=ccache /path/to/source
CCACHE_PREFIX=distcc make -j`distcc -j`
If you have a C++ project, use -DCMAKE_CXX_COMPILER_LAUNCHER=ccache.
Or, make your CMakeLists.txt smart and use ccache automatically if it can be found:
#-----------------------------------------------------------------------------
# Enable ccache if not already enabled by symlink masquerading and if no other
# CMake compiler launchers are already defined
#-----------------------------------------------------------------------------
find_program(CCACHE_EXECUTABLE ccache)
mark_as_advanced(CCACHE_EXECUTABLE)
if(CCACHE_EXECUTABLE)
foreach(LANG C CXX)
if(NOT DEFINED CMAKE_${LANG}_COMPILER_LAUNCHER AND NOT CMAKE_${LANG}_COMPILER MATCHES ".*/ccache")
message(STATUS "Enabling ccache for ${LANG}")
set(CMAKE_${LANG}_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE} CACHE STRING "")
endif()
endforeach()
endif()
Just as a hint: never use <LANG>_COMPILER_LAUNCHER to cross compile. If <LANG>_COMPILER_LAUNCHER is used together with distcc the absolute compiler path is sent to distcc and the host is not using the cross comping toolchain!
Instead you should use the old school method, just overwrite the compiler path:
export PATH=/usr/lib/distcc:$PATH
It took me hours to find out...

How to Use CCache with CMake?

I would like to do the following: If CCache is present in PATH, use "ccache g++" for compilation, else use g++. I tried writing a small my-cmake script containing
CC="ccache gcc" CXX="ccache g++" cmake $*
but it does not seem to work (running make still does not use ccache; I checked this using CMAKE_VERBOSE_MAKEFILE on).
Update:
As per this link I tried changing my script to
cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*
but cmake bails out complaining that a test failed on using the compiler ccache (which can be expected).
As of CMAKE 3.4 you can do:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
It is now possible to specify ccache as a launcher for compile commands and link commands (since cmake 2.8.0). That works for Makefile and Ninja generator. To do this, just set the following properties :
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) # Less useful to do it for linking, see edit2
endif(CCACHE_FOUND)
It is also possible to set these properties only for specific directories or targets.
For Ninja, this is possible since version 3.4.
For XCode, Craig Scott gives a workaround in his answer.
Edit : Thanks to uprego and Lekensteyn's comment, I edited the answer to check if ccache is available before using it as launcher and for which generators is it possible to use a compile launcher.
Edit2: #Emilio Cobos recommended to avoid doing that for the linking part as ccache doesn't improve linking speed and can mess with other types of cache like sccache
I personally have /usr/lib/ccache in my $PATH. This directory contains loads of symlinks for every possible name the compiler could be called from (like gcc and gcc-4.3), all pointing to ccache.
And I didn't even create the symlinks. That directory comes pre-filled when I install ccache on Debian.
From CMake 3.1, it is possible to use ccache with the Xcode generator and Ninja is supported from CMake 3.4 onwards. Ninja will honour RULE_LAUNCH_COMPILE just like the Unix Makefiles generator (so #Babcool's answer gets you there for Ninja too), but getting ccache working for the Xcode generator takes a little more work. The following article explains the method in detail, focussing on a general implementation which works for all three CMake generators and making no assumptions about setting up ccache symlinks or the underlying compiler used (it still lets CMake decide the compiler):
https://crascit.com/2016/04/09/using-ccache-with-cmake/
The general gist of the article is as follows. The start of your CMakeLists.txt file should be set up something like this:
cmake_minimum_required(VERSION 2.8)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
endif()
project(SomeProject)
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE AND CMAKE_GENERATOR STREQUAL "Xcode")
# Set up wrapper scripts
configure_file(launch-c.in launch-c)
configure_file(launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
The two script template files launch-c.in and launch-cxx.in look like this (they should be in the same directory as the CMakeLists.txt file):
launch-c.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$#"
launch-cxx.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_CXX_COMPILER}" "$#"
The above uses RULE_LAUNCH_COMPILE alone for Unix Makefiles and Ninja, but for the Xcode generator it relies on help from CMake's CMAKE_XCODE_ATTRIBUTE_... variables support. The setting of the CC and CXX user-defined Xcode attributes to control the compiler command and LD and LDPLUSPLUS for the linker command is not, as far as I can tell, a documented feature of Xcode projects, but it does seem to work. If anyone can confirm it is officially supported by Apple, I'll update the linked article and this answer accordingly.
I didn't like to set a symlink from g++ to ccache. And CXX="ccache g++" didn't work for me as some cmake test case wanted to have just the compiler program without attributes.
So I used a small bash script instead:
#!/bin/bash
ccache g++ "$#"
and saved it as an executable in /usr/bin/ccache-g++.
Then C configured cmake to use /usr/bin/ccache-g++ as C++ compiler.
This way it passes the cmake test cases and I feel more comfortable than having symlinks that I might forget about in 2 or 3 weeks and then maybe wonder if something doesn't work...
I verified the following works (source: this link):
CC="gcc" CXX="g++" cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*
Update: I later realized that even this does not work. Strangely it works every alternate time (the other times cmake complains).
Let me add one important item that was not mentioned here before.
While bootstrapping a minimalistic build system from the ubuntu:18.04 docker image, I've found that order of installation makes a difference.
In my case ccache worked fine when calling gcc, but failed to catch invocations of the same compiler by the other names: cc and c++.
To fully install ccache, you need to make sure all compilers are installed first, or add a call to update-ccache symlinks to be safe.
sudo /usr/sbin/update-ccache-symlinks
export PATH="/usr/lib/ccache/:$PATH"```
... and then (due to updated symlinks) also calls to cc and c++ get caught!
In my opinion the best way is to symlink gcc,g++ to ccache, but if you would like to use within cmake, try this:
export CC="ccache gcc" CXX="ccache g++" cmake ...
Here are 2 methods I think are clean/robust, and also don't pollute your CMake code.
1.) Set environment variables
This method is nice since you don't have to individually set it up for each CMake project. The con is you may not want ccache for each CMake project.
# Requires CMake 3.17 (https://cmake.org/cmake/help/latest/envvar/CMAKE_LANG_COMPILER_LAUNCHER.html)
export CMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache
export CMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache
2.) Pass in cache variables during project configuration
Con a bit annoying to do for each project. This can be negated by your IDE though.
# Requires CMake 3.4
$ cmake ... -D CMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache \
-D CMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache
NOTE: It isn't really necessary to specify the full path.
If ccache is in your path you can just specify ccache instead.
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
export CMAKE_C_COMPILER_LAUNCHER=ccache
It is extending #Nicolas answer.
Add following line to your cmake file:
list(PREPEND CMAKE_PROGRAM_PATH /usr/lib/ccache)
Or add it as argument to cmake configuration step:
cmake -DCMAKE_PROGRAM_PATH=/usr/lib/ccache