如何用CMake复制可执行文件及依赖时排除自动生成的CMake文件?
CMake复制文件时排除冗余内容并添加外部依赖的解决办法
问题背景
用CMake构建共享库my_library和可执行文件executable,要求二者最终放在同一特定目录下。需要复制可执行文件及其依赖(包括非目标关联的外部共享库)到该目录,但要排除CMake生成的cmake_install.cmake和CMakeFiles/这类冗余文件/目录。当前配置用copy_directory会把整个输出目录都复制过来,包含了不需要的内容,需要调整实现方式。
可行解决方案
1. 用CMake 3.21+的copy_directory排除功能
从CMake 3.21开始,copy_directory支持--exclude参数,直接指定要排除的内容,修改executable/CMakeLists.txt里的自定义命令:
add_custom_command( TARGET executable POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory --exclude "cmake_install.cmake" --exclude "CMakeFiles/" $<TARGET_FILE_DIR:executable> $<TARGET_FILE_DIR:my_library>/bin/${PLATFORM_NAME}${PROCESSOR_ARCH} )
这样复制时会自动跳过指定的文件和目录,简单直接。
2. 手动复制所需文件(兼容旧版CMake)
如果用的是3.21之前的CMake版本,没法用--exclude,就精准复制需要的文件类型,避免带进来冗余内容:
add_custom_command( TARGET executable POST_BUILD # 复制可执行文件本身 COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:executable> $<TARGET_FILE_DIR:my_library>/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}/$<TARGET_FILE_NAME:executable> # 复制可执行文件的依赖库(自动适配平台:Windows是dll,Linux是so,macOS是dylib) COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:executable> $<TARGET_FILE_DIR:my_library>/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}/ )
这种方式只复制必要的文件,完全不会包含CMake生成的冗余内容。
3. 复制非目标关联的外部共享库
对于不属于executable目标依赖的外部库,单独添加复制命令即可,比如:
# 假设外部库路径是EXTERNAL_LIB_PATH,文件名根据平台调整(如external_lib.dll/libexternal_lib.so/libexternal_lib.dylib) add_custom_command( TARGET executable POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXTERNAL_LIB_PATH}/external_lib.dll $<TARGET_FILE_DIR:my_library>/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}/ )
多个外部库的话,重复添加COMMAND行或者用循环处理都可以。
4. 优化:直接设置统一输出目录(更省心)
其实可以一开始就把共享库和可执行文件的输出目录设为目标目录,避免后续复制操作:
在根目录的CMakeLists.txt里添加:
# 设置统一的输出目录,直接生成到目标路径 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH})
这样my_library和executable会直接生成到指定目录,不需要额外复制,之后只需要处理外部共享库的复制就行。
内容的提问来源于stack exchange,提问作者dan123123
相关产品推荐
相关产品推荐

