Выполните команду или макрос в CMake как последний шаг перед завершением шага 'configure'

Возможно ли каким-то образом с CMake (версия>= 2.8.7) выполнить макрос или команду как последний шаг перед завершением фазы конфигурации?

Функциональность должна быть выполнена до того, как на экране будут напечатаны следующие строки:

-- Configuring done
-- Generating done

До сих пор мне не удавалось найти цель CMake, которую можно было бы использовать как зависимость для достижения этой цели с помощью add_custom_commandadd_custom_target или же add_dependencies,

РЕДАКТИРОВАТЬ: у нас есть библиотека, экспортирующая несколько макросов CMake, и некоторые из этих макросов должны выполняться в конце каждого CMakeLists.txt файл после всех других команд CMake. В идеале желаемое поведение может быть достигнуто путем включения файла macros.cmake в CMakeLists.txt файл без необходимости добавлять дополнительную команду в конце этого CMakeLists.txt файл.

Этого также можно было бы достичь, собрав все функции в одном макросе, который необходимо явно вызывать в конце CMakeLists.txt, Тем не менее, уже существует несколько зависимых библиотек, которые необходимо адаптировать, и решение этой проблемы исключило бы эту дополнительную работу. Кроме того, добавление макроса может быть забыто или требование о том, что он является самым последним оператором, может быть легко нарушено.

пример macros.cmake:

macro(FINAL_MACRO)
    message(STATUS "Last step before finishing Configure phase")
endmacro()

# HERE: something like add_custom_target(final_steps)
# followed by something like add_dependencies(final_steps cmake_configure_finished)

Пример toplevel CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.7)
include(macros.cmake)

add_subdirectory(source)
add_subdirectory(interfaces)

# Here FINAL_MACRO should get executed without explicitly writing it down

Если нет другого выбора, мы должны будем требовать от каждого пользователя вызывать специальный макрос в конце их CMakeLists.txt файл.

4 ответа

Решение

ОК. Этот ответ кажется немного хрупким, поскольку он использует недокументированное поведение CMake. Тем не менее, это похоже на работу.

В конце процесса настройки после обработки всех команд в файле CMakeLists.txt CMake проверяет значение CMAKE_BACKWARDS_COMPATIBILITY, Если эта переменная отслеживается через variable_watch команда, то это будет срабатывать здесь.

Таким образом, вы можете обернуть эту функцию в несколько функций:

function(EOFHook Variable Access)
  if(${Variable} STREQUAL CMAKE_BACKWARDS_COMPATIBILITY AND
     (${Access} STREQUAL UNKNOWN_READ_ACCESS OR ${Access} STREQUAL READ_ACCESS))
    execute_process(COMMAND ${CMAKE_COMMAND} -E echo "In EOF hook command")
    ... do whatever else is required ...
  endif()
endfunction()

function(SetupEOFHook)
  variable_watch(CMAKE_BACKWARDS_COMPATIBILITY EOFHook)
endfunction()

Чтобы использовать это в любом файле CMakeLists, просто вызовите SetupEOFHook() в любом месте файла.

Это немного рискованно; если переменная также читается в другом месте в CMakeLists.txt, например, через

message(${CMAKE_BACKWARDS_COMPATIBILITY})

тогда это вызовет EOFHook функционировать здесь и в конце. Вы можете добавить усложнение к функции, добавив счетчик и проверив, что она вызывается только один раз, или выдает message(FATAL_ERROR ...)

Если вы используете CMake >=3.18, вы можете использовать cmake_language(DEFER) для отсрочки вызова до конца текущего каталога или другого каталога, напримерCMAKE_SOURCE_DIR.

Команда CMake execute_process будет выполняться во время фазы настройки, а не фазы сборки, поэтому, если вы поместите это в конец файла CMakeLists.txt, он будет выполнен последним.

Ничего из того, что я знаю (и я усердно искал). Хотелось бы, чтобы меня ошиблись.

Другие вопросы по тегам