Как получить цветной вывод с помощью cmake?
Я хочу иметь функцию сообщения в CMakeLists.txt, которая выводит цветной текст. Возможно избежать последовательности. Например
message("\x1b[31m;This text must be in red")
Это не работает я получил
Синтаксическая ошибка в коде cmake на
/home/taurus/cmakecolor/CMakeLists.txt:1
при разборе строки
\x1b[31m;This text must be in red
Неверная escape-последовательность \x
4 ответа
Чтобы расширить правильный ответ @ Grim, вы можете сделать вещи немного более удобными, настроив переменные для обработки различных цветов:
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}")
Если вы действительно хотите вытолкнуть лодку, вы можете заменить встроенный message
Функция с вашим собственным, который окрашивает вывод в зависимости от типа сообщения:
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.")
Не могу сказать, что рекомендую переопределить встроенный message
функционировать таким образом, но, сказав это, я не нашел никаких серьезных проблем с этим.
Более простое решение, вероятно, состоит в том, чтобы просто использовать встроенную возможность CMake для вывода цветного вывода, то есть эти команды
Разные цвета
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
Из CMake вы можете использовать execute_process()
команда для вызова ${CMAKE_COMMAND}
, Вы можете написать удобную функцию для этого.
ОБНОВЛЕНИЕ: Использование cmake_echo_color
с execute_process()
Как указано @sjm324 работает
execute_process(COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red --bold hello)
не работает. Глядя на реализацию https://github.com/Kitware/CMake/blob/10371cd6dcfc1bf601fa3e715734dbe66199e2e4/Source/kwsys/Terminal.c#L160
я предполагаю, что стандартный вывод не подключен к терминалу и, следовательно, когда CMake внутренне вызывает isatty()
это терпит неудачу.
У меня есть два хака, которые обходят это, но на самом деле, если вы заботитесь об этом, вы должны связаться с разработчиками CMake для менее хрупкого решения
HACK 1: установить CLICOLOR_FORCE=1
переменная окружения.
execute_process(COMMAND
${CMAKE_COMMAND} -E env CLICOLOR_FORCE=1
${CMAKE_COMMAND} -E cmake_echo_color --red --bold hello
)
Это не очень хорошая идея. Если вы зарегистрируете вывод вашей сборки в файл, в нем будут escape-последовательности, потому что вы заставляете их всегда генерироваться.
HACK 2: установите OUTPUT_FILE в качестве TTY
Не делай этого. HACK 1, вероятно, более переносимый.
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})
Хотя это утомительно, вы можете определить переменную, содержащую escape-символ, и использовать ее в строках вашего сообщения.
string(ASCII 27 ESCAPE)
message("${ESCAPE}[34mblue${ESCAPE}[0m")
Запустите execute_process и назначьте вывод VARIBALE, затем используйте сообщение для печати.
Нет взлома
macro ( print_color NAME )
print ( COLOR ${NAME} " ${NAME}" )
endmacro ()
function ( text )
cmake_parse_arguments ( PARSE_ARGV 0 "_TEXT" "BOLD" "COLOR" "" )
set ( _TEXT_OPTIONS -E cmake_echo_color --no-newline )
if ( _TEXT_COLOR )
string ( TOLOWER "${_TEXT_COLOR}" _TEXT_COLOR_LOWER )
if ( NOT ${_TEXT_COLOR_LOWER} MATCHES "^normal|black|red|green|yellow|blue|magenta|cyan|white" )
print ( "Only these colours are supported:" )
print_color ( NORMAL )
print_color ( BLACK )
print_color ( RED )
print_color ( GREEN )
print_color ( YELLOW )
print_color ( BLUE )
print_color ( MAGENTA )
print_color ( CYAN )
print_color ( WHITE )
TEXT ( WARING "Color ${_TEXT_COLOR} is not support." )
else ()
list ( APPEND _TEXT_OPTIONS --${_TEXT_COLOR_LOWER} )
endif ()
endif ()
if ( _TEXT_BOLD )
list ( APPEND _TEXT_OPTIONS --bold )
endif ()
execute_process ( COMMAND ${CMAKE_COMMAND} -E env CLICOLOR_FORCE=1 ${CMAKE_COMMAND} ${_TEXT_OPTIONS} ${_TEXT_UNPARSED_ARGUMENTS}
OUTPUT_VARIABLE _TEXT_RESULT
ECHO_ERROR_VARIABLE
)
set ( TEXT_RESULT ${_TEXT_RESULT} PARENT_SCOPE )
endfunction ()
unset ( print_color )
function ( print )
text ( ${ARGN} )
message ( ${TEXT_RESULT} )
endfunction ()
print ( COLOR NORMAL TEST_NORMAL )
print ( BOLD COLOR NORMAL TEST_NORMAL_BOLD )
print ( COLOR BLACK TEST_BLACK )
print ( BOLD COLOR BLACK TEST_BLACK_BOLD )
print ( COLOR RED TEST_RED )
print ( BOLD COLOR RED TEST_RED_BOLD )
print ( COLOR GREEN TEST_GREEN )
print ( BOLD COLOR GREEN TEST_GREEN_BOLD )
print ( COLOR YELLOW TEST_YELLOW )
print ( BOLD COLOR YELLOW TEST_YELLOW_BOLD )
print ( COLOR BLUE TEST_BLUE )
print ( BOLD COLOR BLUE TEST_BLUE_BOLD )
print ( COLOR MAGENTA TEST_MAGENTA )
print ( BOLD COLOR MAGENTA TEST_MAGENTA_BOLD )
print ( COLOR CYAN TEST_CYAN )
print ( BOLD COLOR CYAN TEST_CYAN_BOLD )
print ( COLOR WHITE TEST_WHITE )
print ( BOLD COLOR WHITE TEST_WHITE_BOLD )