CMake目标未安装至指定组件:Windows下foo.dll缺失问题
我编写了如下CMake安装代码:
add_library(foo SHARED ...) install(TARGETS foo RUNTIME DESTINATION bin # foo.dll LIBRARY DESTINATION lib # libfoo.so COMPONENT libs) install(FILES conf DESTINATION etc COMPONENT libs)
在Linux系统中运行正常,执行cpack后,-libs包包含所有预期内容。但在Windows系统中,执行cpack生成的-libs包仅包含etc/conf,缺少bin/foo.dll。若执行无组件指定的make install,install_manifest.txt中则包含所有内容。请问为何Windows下组件安装时foo.dll未被部署?
原因与解决方法
原因分析
在Windows平台下,CMake对SHARED库的处理与Linux存在差异:SHARED库会生成两个核心文件——导入库(.lib,属于ARCHIVE目标类型)和运行时动态库(.dll,属于RUNTIME目标类型)。
你的原始install(TARGETS)命令中,虽然全局指定了COMPONENT libs,但在部分CMake版本或Windows特定构建环境下,RUNTIME类型的目标可能未被正确关联到指定的libs组件,导致cpack打包时遗漏了foo.dll。而无组件的make install能正常安装所有内容,是因为该命令会安装所有目标,不受组件筛选逻辑的限制。
解决方法
显式为每个目标类型指定组件
修改install(TARGETS)命令,为RUNTIME、LIBRARY(以及可选的ARCHIVE)目标单独指定COMPONENT libs,确保动态库明确归属到目标组件:add_library(foo SHARED ...) install(TARGETS foo RUNTIME DESTINATION bin COMPONENT libs # 显式关联libs组件 LIBRARY DESTINATION lib COMPONENT libs ARCHIVE DESTINATION lib COMPONENT libs) # 若需要打包导入库可添加 install(FILES conf DESTINATION etc COMPONENT libs)确认CPack组件配置
确保CMake配置中明确指定要打包的组件,避免cpack遗漏:set(CPACK_COMPONENTS_ALL libs)
完成上述修改后,执行cpack生成的-libs包就会包含bin/foo.dll和etc/conf文件。
内容的提问来源于stack exchange,提问作者Stewart

