Bor*_*ein 8 windows dll cmake shared-libraries
我正在使用以下内容src/CMakeLists.txt:
cmake_minimum_required(VERSION 3.1.0)
project(foo)
add_library(foo SHARED foo.cpp)
set_target_properties(foo
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/subdir
)
Run Code Online (Sandbox Code Playgroud)
在 Windows 上,我使用以下方法构建库:
mkdir build
cd build
cmake ../src
cmake --build .
Run Code Online (Sandbox Code Playgroud)
输出文件: ~/build/Debug/foo.dll
预期输出文件: ~/build/Debug/subdir/foo.dll
我究竟做错了什么?
它在 Windows 以外的平台上运行良好,并且似乎应该根据以下文档运行:
Bor*_*ein 18
在 Windows 上,与其他平台不同,您应该使用RUNTIME_OUTPUT_DIRECTORY而不是LIBRARY_OUTPUT_DIRECTORY指定共享库的输出目录。
有关输出工件的 CMake 文档对此进行了记录:
运行时输出工件
构建系统目标的运行时输出工件可能是:
- 由add_executable() 命令创建的可执行目标的可执行文件(例如.exe)。
- 在 DLL 平台上:由带有 SHARED 选项的 add_library() 命令创建的共享库目标的可执行文件(例如 .dll) 。RUNTIME_OUTPUT_DIRECTORY 和 RUNTIME_OUTPUT_NAME 目标属性可用于控制构建树中的运行时输出工件位置和名称。
库输出工件
构建系统目标的库输出工件可能是:
- 由带有 MODULE 选项的 add_library() 命令创建的模块库目标的可加载模块文件(例如 .dll 或 .so)。
- 在非 DLL 平台上:由带有 SHARED 选项的 add_library() 命令创建的共享库目标的共享库文件(例如 .so 或 .dylib)。LIBRARY_OUTPUT_DIRECTORY 和 LIBRARY_OUTPUT_NAME 目标属性可用于控制构建树中的库输出工件位置和名称。
但为什么 CMake 会在 DLL 平台(Windows)和非 DLL 平台(macOS、Linux 等)之间产生如此大的差异?
我找不到记录此设计决策的源代码,但我相信其基本原理是 Windows 不支持 的概念rpath,即.exe文件无法在内部存储其依赖.dll文件的位置。因此,在 Windows 上,.dll文件通常存储在与.exe文件相同的文件夹中,以确保在运行时可以找到 DLL。相反,在 Unix 系统上,共享库文件通常存储在单独的lib文件夹中,而应用程序二进制文件存储在bin文件夹中,这不是问题,因为二进制文件可以使用rpath.
总之,跨平台开发定义LIBRARY_OUTPUT_DIRECTORY和是有意义的RUNTIME_OUTPUT_DIRECTORY,如下所示:
cmake_minimum_required(VERSION 3.1.0)
project(foo)
add_library(foo SHARED foo.cpp)
set_target_properties(foo
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/lib
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/bin
)
Run Code Online (Sandbox Code Playgroud)