Подтвердить что ты не робот

Как получить цветной вывод с cmake?

Я хочу иметь функцию сообщения в CMakeLists.txt, которая выводит раскрашенный текст. Может быть, escape-последовательность. Например

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

4b9b3361

Ответ 1

Чтобы увеличить @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 \"colour\", not \"color\".")
message(FATAL_ERROR "And there no \"z\" in \"colourise\" either.")

Я не могу сказать, что рекомендую переопределить встроенную функцию message таким образом, но, сказав это, я также не нашел серьезных проблем с этим.

Ответ 2

Более простым решением, вероятно, является просто использование встроенной возможности 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}. Вы можете написать удобную функцию для этого.

UPDATE: использование 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})

Ответ 3

В то время как утомительно, вы можете определить переменную, содержащую escape-символ, и использовать ее в строках сообщения

string(ASCII 27 ESCAPE)
message("${ESCAPE}[34mblue${ESCAPE}[0m")