运行 以修改后的文件作为参数的自定义命令

Run custom command with modified files as arguments

例如,我有 N 个文件和一个从它们生成输出文件的命令。然后我说,更改 file32file51。是否可以通过CMake的方式使命令执行如下:

my-command file32 file51

或至少

my-command file32 && my-command file51

作为生成器,我可以使用 Ninja 或 Make

您可以使用响应文件解决此问题:

cmake_minimum_required(VERSION 3.22)
project(test LANGUAGES NONE)

# Add a command for deleting the global response file
set(rsp "${CMAKE_CURRENT_BINARY_DIR}/my-command.rsp")
add_custom_target(delete-rsp COMMAND "${CMAKE_COMMAND}" -E rm -f "${rsp}")

# Update timestamps for each file, adding it to the initially-empty RSP
set(stamps "")
foreach (i RANGE 1 100)
  list(APPEND stamps "${CMAKE_CURRENT_BINARY_DIR}/stamp_${i}.out")
  add_custom_command(
    OUTPUT "stamp_${i}.out"
    COMMAND "${CMAKE_COMMAND}" -E echo "${CMAKE_CURRENT_SOURCE_DIR}/file${i}" >> "${rsp}"
    COMMAND "${CMAKE_COMMAND}" -E touch "stamp_${i}.out"
    DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/file${i}"
  )
endforeach ()

add_custom_target(update-stamps DEPENDS ${stamps})
add_dependencies(update-stamps delete-rsp)

# Now run the actual command
add_custom_command(
  OUTPUT "changed-list"
  COMMAND "${CMAKE_COMMAND}" -E cat "${rsp}" | tee changed-list
  DEPENDS "${stamps}"
)

add_custom_target(run-my-command ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/changed-list")
add_dependencies(run-my-command update-stamps)

这使用一系列空戳记文件来跟踪单独更新了哪些文件。这些附加到管理 运行 两个命令的自定义目标 update-stamps

  1. 更新图章文件
  2. 将更改后的文件名添加到“响应文件”

这个自定义目标依赖于另一个总是在构建开始时删除响应文件的目标。因此,在 update-stamps 目标完成后,响应文件包含已更改文件的确切列表。

最后,run-my-command 简单地打印出该列表以供演示。


这是我在终端看到的(删节):

$ ls
CMakeLists.txt
$ touch file{1..100}
$ ls
CMakeLists.txt  file13  file19 ...
...
$ cmake -G Ninja -S . -B build
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/build
$ cmake --build build --verbose
[1/102] cd /path/to/build && /usr/bin/cmake -E rm -f /path/to/build/my-command.rsp
[2/102] cd /path/to/build && /usr/bin/cmake -E echo /path/to/file16 >> /path/to/build/my-command.rsp && /usr/bin/cmake -E touch stamp_16.out
...
[102/102] cd /path/to/build && /usr/bin/cmake -E cat /path/to/build/my-command.rsp | tee changed-list
/path/to/file1
/path/to/file16
/path/to/file13
...
/path/to/file99
$ touch file32 file51
$ cmake --build build --verbose
[1/4] cd /path/to/build && /usr/bin/cmake -E rm -f /path/to/build/my-command.rsp
[2/4] cd /path/to/build && /usr/bin/cmake -E echo /path/to/file32 >> /path/to/build/my-command.rsp && /usr/bin/cmake -E touch stamp_32.out
[3/4] cd /path/to/build && /usr/bin/cmake -E echo /path/to/file51 >> /path/to/build/my-command.rsp && /usr/bin/cmake -E touch stamp_51.out
[4/4] cd /path/to/build && /usr/bin/cmake -E cat /path/to/build/my-command.rsp | tee changed-list
/path/to/file32
/path/to/file51