Windows下CMake指定DLL输出目录未生效,如何排查解决?
问题分析与解决方案
这是个典型的CMake跨平台配置细节坑!问题出在Windows平台对动态库文件的属性划分和类Unix系统不一样,咱们来拆解清楚:
核心原因
CMake在不同平台对SHARED库的输出属性做了明确区分:
- 在Linux/macOS等类Unix系统中,SHARED库文件(
.so/.dylib)归属于LIBRARY目标,会严格遵循LIBRARY_OUTPUT_DIRECTORY的路径设置; - 但在Windows上,构建SHARED库会生成两个关键文件:
- 实际的动态链接库(
.dll):属于RUNTIME目标,受RUNTIME_OUTPUT_DIRECTORY属性控制; - 对应的导入库(
.lib):属于ARCHIVE目标,受ARCHIVE_OUTPUT_DIRECTORY属性控制;
- 实际的动态链接库(
你只设置了LIBRARY_OUTPUT_DIRECTORY,所以Windows下的.dll文件会使用默认输出路径,而不是你指定的subdir目录——这也是为什么其他平台能正常工作的原因。
修复方案
只需要在set_target_properties中同时补充RUNTIME_OUTPUT_DIRECTORY(如果需要导入库也放到同一目录,再加上ARCHIVE_OUTPUT_DIRECTORY)即可:
cmake_minimum_required(VERSION 3.1.0) project(foo) add_library(foo SHARED foo.cpp) set_target_properties(foo PROPERTIES # 类Unix平台的共享库路径 LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>/subdir" # Windows下的DLL文件路径 RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>/subdir" # Windows下的导入库路径(可选,根据需求决定是否需要) ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>/subdir" )
如果希望项目中所有目标都统一使用这个路径,也可以直接设置全局变量(放在project指令之后即可):
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>/subdir") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>/subdir") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>/subdir")
修改后重新执行你的构建命令:
mkdir build cd build cmake ../src cmake --build .
此时Windows下的foo.dll(以及foo.lib)就会生成到~/build/Debug/subdir/目录下了。
内容的提问来源于stack exchange,提问作者Boris Dalstein




