I want to have message function in CMakeLists.txt
which output colorized text. Maybe an escape sequence.
For example:
message("\x1b[31m;This text must be in red")
It don't work. I got:
Syntax error in cmake code at /home/taurus/cmakecolor/CMakeLists.txt:1 when parsing string \x1b[31m;This text must be in red Invalid escape sequence \x
To extend @grim's correct answer, you can make things a bit more convenient by setting up variables to handle the various colours:
if(NOT WIN32) string(ASCII 27 Esc) set(ColourReset "${Esc}[m") set(ColourBold "${Esc}[1m") set(Red "${Esc}[31m") set(Green "${Esc}[32m") set(Yellow "${Esc}[33m") set(Blue "${Esc}[34m") set(Magenta "${Esc}[35m") set(Cyan "${Esc}[36m") set(White "${Esc}[37m") set(BoldRed "${Esc}[1;31m") set(BoldGreen "${Esc}[1;32m") set(BoldYellow "${Esc}[1;33m") set(BoldBlue "${Esc}[1;34m") set(BoldMagenta "${Esc}[1;35m") set(BoldCyan "${Esc}[1;36m") set(BoldWhite "${Esc}[1;37m") endif() message("This is normal") message("${Red}This is Red${ColourReset}") message("${Green}This is Green${ColourReset}") message("${Yellow}This is Yellow${ColourReset}") message("${Blue}This is Blue${ColourReset}") message("${Magenta}This is Magenta${ColourReset}") message("${Cyan}This is Cyan${ColourReset}") message("${White}This is White${ColourReset}") message("${BoldRed}This is BoldRed${ColourReset}") message("${BoldGreen}This is BoldGreen${ColourReset}") message("${BoldYellow}This is BoldYellow${ColourReset}") message("${BoldBlue}This is BoldBlue${ColourReset}") message("${BoldMagenta}This is BoldMagenta${ColourReset}") message("${BoldCyan}This is BoldCyan${ColourReset}") message("${BoldWhite}This is BoldWhite\n\n${ColourReset}")
If you really fancy pushing the boat out, you can replace the built-in message
function with your own which colourises the output depending on the message type:
function(message) list(GET ARGV 0 MessageType) if(MessageType STREQUAL FATAL_ERROR OR MessageType STREQUAL SEND_ERROR) list(REMOVE_AT ARGV 0) _message(${MessageType} "${BoldRed}${ARGV}${ColourReset}") elseif(MessageType STREQUAL WARNING) list(REMOVE_AT ARGV 0) _message(${MessageType} "${BoldYellow}${ARGV}${ColourReset}") elseif(MessageType STREQUAL AUTHOR_WARNING) list(REMOVE_AT ARGV 0) _message(${MessageType} "${BoldCyan}${ARGV}${ColourReset}") elseif(MessageType STREQUAL STATUS) list(REMOVE_AT ARGV 0) _message(${MessageType} "${Green}${ARGV}${ColourReset}") else() _message("${ARGV}") endif() endfunction() message("No colour at all.") message(STATUS "\"Colour\" is spelled correctly.") message(AUTHOR_WARNING "\"Color\" is misspelled.") message(WARNING "Final warning: spell \"color\" correctly.") message(SEND_ERROR "Game over. It's \"colour\", not \"color\".") message(FATAL_ERROR "And there's no \"z\" in \"colourise\" either.")
I can't say that I recommend overriding the built-in message
function in this way, but having said that, I've not found any major problems with doing this either.
A simpler solution is probably just to use CMake's built-in capability for emitting coloured output, i.e. these commands
cmake -E cmake_echo_color --normal hello cmake -E cmake_echo_color --black hello cmake -E cmake_echo_color --red hello cmake -E cmake_echo_color --green hello cmake -E cmake_echo_color --yellow hello cmake -E cmake_echo_color --blue hello cmake -E cmake_echo_color --magenta hello cmake -E cmake_echo_color --cyan hello cmake -E cmake_echo_color --white hello
cmake -E cmake_echo_color --red --bold hello
cmake -E cmake_echo_color --red --no-newline hello
From CMake you can use the execute_process()
command to invoke ${CMAKE_COMMAND}
. You could write a convenient function for doing this.
cmake_echo_color
with execute_process()
As pointed out by @sjm324 running
execute_process(COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red --bold hello)
does not work. Looking at the implementation https://github.com/Kitware/CMake/blob/10371cd6dcfc1bf601fa3e715734dbe66199e2e4/Source/kwsys/Terminal.c#L160
my guess is that standard output is not attached to the terminal and thus when CMake internally calls isatty()
this fails.
I have two hacks that workaround this but really if you care about this you should contact the CMake devs for a less fragile solution
CLICOLOR_FORCE=1
environment variable.execute_process(COMMAND ${CMAKE_COMMAND} -E env CLICOLOR_FORCE=1 ${CMAKE_COMMAND} -E cmake_echo_color --red --bold hello )
This isn't a great idea. If you log the output of your build to a file it will have escape sequences in it because you're forcing them to be emitted always.
Don't do this. HACK 1 is likely more portable.
execute_process(COMMAND /usr/bin/tty OUTPUT_VARIABLE TTY_NAME OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red --bold hello OUTPUT_FILE ${TTY_NAME})
While tedious, you can define a variable that contains an escape character and use it in your message strings
string(ASCII 27 ESCAPE)
message("${ESCAPE}[34mblue${ESCAPE}[0m")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With