如何使CMake的'FILE'命令依赖于目标或输出?

6

我在CMake构建中使用了一些add_custom_command(),用于在构建elf文件目标后执行某些操作:将其转换为srec格式,使用0xFF填充各种区域并创建二进制图像,生成CRC并获取图像的大小。 add_custom_command()可以有DEPENDS,这使得它仅在重新生成elf文件时运行,这很棒。

我还想使用FILE()创建一个新文件,其中包含二进制文件名、crc和大小(可能以简单的JSON格式),但文档暗示我不能在上述操作之后进行该文件活动。

# This command creates the FF-filled binary file.  It uses objcopy to create the srec
# file to operate on.
add_custom_command(
    OUTPUT ThreadingApp.bin filled.srec
    MAIN_DEPENDENCY ThreadingApp.elf
    COMMAND ${CMAKE_OBJCOPY} ARGS -O srec ThreadingApp.elf ThreadingApp.srec
    COMMAND srec_cat.exe ThreadingApp.srec -offset - -minimum-addr ThreadingApp.srec
            −fill 0xFF -over ThreadingApp.srec -o filled.srec
    COMMAND srec_cat.exe filled.srec -o ThreadingApp.bin -binary
    )

# This command creates the CRC
add_custom_command(
    OUTPUT crc.out size.out
    MAIN_DEPENDENCY filled.srec
    COMMAND srec_cat.exe filled.srec -crc32-b-e 0x08100000 -crop 0x08100000 0x08100004 -o - -hex-dump > crc.out
    COMMAND srec_info.exe filled.srec > size.out
    )

file(
    WRITE ThreadingApp.json

    )

看了一下“FILE”的简介,我不知道如何在我的自定义命令运行之后才实现它。你有没有关于如何在CMake中实现这一点的建议?我的备选方案是编写一个单独的Python脚本,在add_custom_command中执行以创建json文件。

Reading
  file(READ <filename> <out-var> [...])
  file(STRINGS <filename> <out-var> [...])
  file(<HASH> <filename> <out-var>)
  file(TIMESTAMP <filename> <out-var> [...])

Writing
  file({WRITE | APPEND} <filename> <content>...)
  file({TOUCH | TOUCH_NOCREATE} [<file>...])
  file(GENERATE OUTPUT <output-file> [...])

Filesystem
  file({GLOB | GLOB_RECURSE} <out-var> [...] [<globbing-expr>...])
  file(RENAME <oldname> <newname>)
  file({REMOVE | REMOVE_RECURSE } [<files>...])
  file(MAKE_DIRECTORY [<dir>...])
  file({COPY | INSTALL} <file>... DESTINATION <dir> [...])
  file(SIZE <filename> <out-var>)
  file(READ_SYMLINK <linkname> <out-var>)
  file(CREATE_LINK <original> <linkname> [...])

Path Conversion
  file(RELATIVE_PATH <out-var> <directory> <file>)
  file({TO_CMAKE_PATH | TO_NATIVE_PATH} <path> <out-var>)

Transfer
  file(DOWNLOAD <url> <file> [...])
  file(UPLOAD <file> <url> [...])

Locking
  file(LOCK <path> [...])
1个回答

8
add_custom_command 不同,FILE() 在处理 CMakeLists.txt 时会立即执行,即在 配置 阶段执行,而不是在 构建 阶段执行。但是您可以将 FILE() 调用放入单独的 CMake 脚本中,并使用 add_custom_command 运行该脚本。采用这种方法,带有 FILE() 的脚本将在项目的 构建 阶段执行,您可以使用 OUTPUT 或 TARGET 选项:
# File: my_script.cmake
file(...)

# File: CMakeLists.txt:
add_custom_command(OUTPUT | TARGET ...
    COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/my_script.cmake"
    )

除了已经展示的CMake 脚本模式cmake -P)外,还有一个命令行模式cmake -E),可以执行基本操作而无需编写脚本
# File: CMakeLists.txt:
add_custom_command(OUTPUT | TARGET ...
    COMMAND ${CMAKE_COMMAND} -E echo "<content-of-the-file>" > "</path/to/file>"
    )

另外还可以查看关于在add_custom_command中重定向输出的问题:如何将CMake自定义命令的输出重定向到文件?


1
这真的是唯一实现它的方式吗?感觉这样做很愚蠢。 - Ben Farmer
2
CMake不是一个构建工具。在配置阶段完成后,CMake会为实际的构建工具(如Makefile、Visual Studio等)创建文件。因此,在构建阶段,CMake语言不被直接支持。 - Tsyvarev
Make本身不能创建和写入文件,它应该执行外部工具来完成这个任务。CMake的脚本模式(cmake -P <...>)就是其中之一,而且在各种平台上都非常便携。我不明白为什么你反对这种方法。此外,CMake还有一个命令行模式,可以执行简单的操作而无需编写脚本。 - Tsyvarev
1
我并不反对它,只是感觉它过于复杂了。我并不是说一定有更好的方法,只是感觉应该有更简单的方式。不过命令行模式确实很有帮助,可以避免需要另外编写一个完整的cmake脚本来创建文件。 - Ben Farmer
1
好的,你的第一条评论是提示“更努力地搜索”,它似乎达到了目标:我已经更新了我的答案,关于使用CMake命令行模式。这种方式实际上看起来更好,甚至适合原始作者的意图。不确定为什么我在最初写答案时忘记了这种方式。感谢你提醒我! - Tsyvarev
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接