如何在CMake中用file(GLOB_RECURSE)构建时复制含符号链接的目录?
解决CMake增量复制含符号链接目录的问题
要实现支持符号链接的增量复制,核心需要解决两个问题:让CMake追踪符号链接文件,以及复制时保留符号链接而非展开内容。以下是具体实现方案:
关键思路
- 调整
file(GLOB_RECURSE)参数,将符号链接本身纳入文件追踪列表,而非跳过或追踪其指向的目标文件。 - 使用平台兼容的复制命令,确保复制时保留符号链接属性,同时依赖CMake的增量检查机制,仅在源文件(含符号链接)变更时执行复制。
具体实现代码
# 定义源目录和目标目录 set(SOURCE_DIR "${CMAKE_SOURCE_DIR}/path/to/source") set(TARGET_DIR "${CMAKE_BINARY_DIR}/path/to/target") # 获取源目录下所有文件(包括符号链接),排除目录本身 file(GLOB_RECURSE SOURCE_FILES LIST_DIRECTORIES false INCLUDE_SYMLINKS "${SOURCE_DIR}/**" ) # 为每个文件(含符号链接)创建增量复制规则 foreach(SOURCE_FILE IN LISTS SOURCE_FILES) # 计算源文件相对源目录的路径,保持目录结构 file(RELATIVE_PATH REL_PATH "${SOURCE_DIR}" "${SOURCE_FILE}") set(TARGET_FILE "${TARGET_DIR}/${REL_PATH}") # 创建自定义命令:仅当源文件变更时执行复制 add_custom_command( OUTPUT "${TARGET_FILE}" # 先确保目标目录存在 COMMAND ${CMAKE_COMMAND} -E make_directory "$<PATH:GET_DIR_NAME,${TARGET_FILE}>" # 跨平台复制命令:Unix用cp -a保留符号链接,Windows用robocopy COMMAND $<$<PLATFORM_ID:Windows>:robocopy "$<PATH:GET_DIR_NAME,${SOURCE_FILE}>" "$<PATH:GET_DIR_NAME,${TARGET_FILE}>" "$<PATH:GET_FILENAME,${SOURCE_FILE}>" /E /COPYALL /NJH /NJS> COMMAND $<$<NOT:$<PLATFORM_ID:Windows>>:cp -a "${SOURCE_FILE}" "${TARGET_FILE}"> # 将源文件设为主依赖,触发增量检查 MAIN_DEPENDENCY "${SOURCE_FILE}" COMMENT "Copying ${REL_PATH}" ) endforeach() # 创建自定义目标,依赖所有复制后的文件 add_custom_target(copy_with_symlinks ALL DEPENDS ${SOURCE_FILES})
核心细节说明
INCLUDE_SYMLINKS参数:CMake 3.12+引入,确保file(GLOB_RECURSE)将符号链接本身加入文件列表,而非默认跳过。如果使用更低版本CMake,需要手动遍历目录并识别符号链接,建议升级CMake版本简化实现。- 复制命令选择:
- Unix-like系统(macOS/Linux)用
cp -a:参数会保留符号链接、文件权限、修改时间等所有属性,不会展开符号链接指向的内容。 - Windows用
robocopy:/COPYALL参数保留包括符号链接在内的所有文件属性,/E处理子目录,/NJH /NJS屏蔽冗余输出。
- Unix-like系统(macOS/Linux)用
- 增量检查逻辑:每个
add_custom_command以源文件(含符号链接)作为MAIN_DEPENDENCY,CMake会对比源文件与目标文件的修改时间——当符号链接本身的指向变更时,符号链接的修改时间会更新,从而触发复制。 - 目录结构保持:通过
file(RELATIVE_PATH)计算相对路径,确保目标目录与源目录的结构完全一致,比如macOS的Foo.framework/Headers符号链接会被复制到目标目录的对应位置。
针对macOS Framework的验证
对于macOS的.framework目录,其中的标准符号链接(如Headers→Versions/Current/Headers、Foo→Versions/Current/Foo)会被正确复制为符号链接,而非展开成实际文件/目录,完全保留framework的结构。
内容的提问来源于stack exchange,提问作者user3667089
相关产品推荐
相关产品推荐

