在"配置"步骤完成之前,在CMake中执行命令或宏作为最后一步

MKr*_*ert 8 cmake

在配置阶段结束之前,CMake(版本> = 2.8.7)以某种方式执行宏或命令作为最后一步吗?

应在屏幕上打印以下行之前执行该功能:

-- Configuring done
-- Generating done
Run Code Online (Sandbox Code Playgroud)

到现在为止我没能找到这可以作为一个依赖与实现这个目标的CMake add_custom_command add_custom_targetadd_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)
Run Code Online (Sandbox Code Playgroud)

示例顶级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
Run Code Online (Sandbox Code Playgroud)

如果没有其他选项,我们将不得不要求每个用户在其CMakeLists.txt文件末尾调用一个特殊的宏.

Joh*_*man 7

如果您使用的 CMake >=3.18,则可以使用cmake_language(DEFER)将调用推迟到当前目录或另一个目录(例如CMAKE_SOURCE_DIR.

例子:

## Things to be done at the very end of configure phase
## as if they would be at bottom of CMakelists.txt
cmake_language(DEFER DIRECTORY ${CMAKE_SOURCE_DIR} CALL _my_hook_end_of_configure())
function(_my_hook_end_of_configure)
    message("Hello end of configure!")
endfunction(_my_hook_end_of_configure)
Run Code Online (Sandbox Code Playgroud)


Fra*_*ser 6

好的 - 这个答案感觉有点脆弱,因为它利用了未记录的 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()
Run Code Online (Sandbox Code Playgroud)

要在任何 CMakeLists 文件中使用它,只需调用文件中的任何SetupEOFHook()位置。

这有点冒险;如果变量也在 CMakeLists.txt 的其他地方被读取,例如通过

message(${CMAKE_BACKWARDS_COMPATIBILITY})
Run Code Online (Sandbox Code Playgroud)

然后它将在EOFHook这里最后触发该功能。您可以通过添加一个计数器并检查它是否只被调用一次或发出一个message(FATAL_ERROR ...)

  • CMAKE_PARENT_LIST_FILE 和 CMAKE_CURRENT_LIST_DIR 似乎更可靠,它们的值在最后一个文件的末尾设置为空。 (3认同)