如何使用CMake的configure_file命令递归复制指定目录文件?
使用configure_file递归复制目录的正确方式
你遇到的问题其实是因为configure_file的核心设计就是处理单个文件,它不支持用通配符*来匹配多个文件,所以直接写${CMAKE_CURRENT_SOURCE_DIR}/res/*会触发报错。
如果一定要用configure_file来实现递归复制,得先把目标目录下的所有文件遍历出来,再逐个调用configure_file处理,具体步骤如下:
- 先递归获取源目录下的所有文件:
file(GLOB_RECURSE RES_FILES "${CMAKE_CURRENT_SOURCE_DIR}/res/*")
这里GLOB_RECURSE会遍历res目录下的所有文件(包括子目录里的文件),把所有文件路径存入RES_FILES变量中。
- 遍历每个文件,计算相对路径并完成复制:
foreach(RES_FILE ${RES_FILES}) # 计算当前文件相对于源res目录的路径,保证复制后目录结构不变 file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/res" "${RES_FILE}") # 拼接目标文件的完整路径 set(DEST_FILE "${CMAKE_CURRENT_BINARY_DIR}/res/${REL_PATH}") # 先创建目标文件所在的目录,避免因目录不存在导致复制失败 get_filename_component(DEST_DIR "${DEST_FILE}" DIRECTORY) file(MAKE_DIRECTORY "${DEST_DIR}") # 用configure_file的COPYONLY模式复制单个文件 configure_file("${RES_FILE}" "${DEST_FILE}" COPYONLY) endforeach()
不过说实话,这种方式有点舍近求远——CMake专门提供了file(COPY)命令来处理递归复制目录的场景,写法简洁得多:
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/res/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/res")
毕竟configure_file的本职工作是处理模板文件(替换里面的CMake变量),COPYONLY只是它的一个附加小功能,用来复制不需要变量替换的单个文件。递归复制目录这种场景,用file(COPY)才是更符合CMake设计意图的做法,代码更少也更不容易出错。
内容的提问来源于stack exchange,提问作者H.M
相关产品推荐
相关产品推荐

