我有一个目录树,其中某些已知类型的文件(例如.in)位于该树的各个文件夹中。任务是调用每个已知类型的文件一次的已知自定义程序(例如 process_it ),并将此文件作为参数传递:
process_it a/b/c/file.in
,它将产生a/b/c/file.out
。
我们已经将cmake用于该项目的常规C ++构建。是否有可能,以及如何扩展CMakeLists.txt并获得这种处理?
我目前只编写了一个python脚本来迭代文件夹并调用处理程序。可以将此脚本作为自定义命令添加到CMakeLists.txt中,并且效果很好,可以在$ {OUTPUT}文件夹中生成文件,最初缺少该文件:
add_custom_command(OUTPUT ${OUTPUT}
COMMAND python ARGS scan_current_dir_and_do_naive_processing.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} )
但是该脚本需要很长时间才能运行,因为它是单线程的,并且不关心输入不变时重用现有输出的情况。
答案 0 :(得分:2)
您可以使用file(GLOB_RECURSE)
收集要处理的文件列表:
file(GLOB_RECURSE
# Result variable
list_in_files
# Return paths relative current source directory
RELATIVE ${CMAKE_CURRENT_SOURCE_DIRECTORY}
# Collect all ".in" files in the current source directory
"${CMAKE_CURRENT_SOURCE_DIRECTORY}/*.in"
)
然后为找到的每个文件创建一个具有适当OUTPUT和DEPENDS的自定义命令:
for(in_file ${list_in_files})
# Obtain relative path of the output file.
string(REGEX REPLACE "in$" "out" out_file ${in_file})
# Create custom command which generates {out_file} from the {in_file}
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${out_file}
COMMAND <process-file> <...arguments...>
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${in_file}
)
endfor()
请注意,您需要具有一些目标来“消费”这些自定义命令中的OUTPUT文件。 (否则,为什么需要这些文件?)。如果出于某种原因只想拥有它们,则可以创建以下自定义目标:
add_custom_target(generate_all_files
# build this target by default (on `make all` or `make`)
ALL
DEPENDS ${list_out_files}
)
这假设您添加了行
# add absolute path of the output file to the list
list(APPEND list_out_files "${CMAKE_CURRENT_BINARY_DIR}/${out_file}")
到上一个for循环。
如果您希望CMake自动发现新的.in
文件(和已删除的文件),则可以对CONFIGURE_DEPENDS
使用附加的file(GLOB_RECURSE)
。从CMake 3.12开始支持。
请注意,此功能可能不适用于某些生成器,并且每次构建项目时都会消耗时间来扫描目录。