我正在使用以下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
)
在Windows上,我使用以下命令构建库:
mkdir build
cd build
cmake ../src
cmake --build .
输出文件: ~/build/Debug/foo.dll
预期的输出文件: ~/build/Debug/subdir/foo.dll
我在做什么错了?
它在Windows以外的平台上都可以正常工作,并且似乎应该根据以下文档进行工作:
答案 0 :(得分:0)
在Windows上,与其他平台不同,您应该使用RUNTIME_OUTPUT_DIRECTORY
而不是LIBRARY_OUTPUT_DIRECTORY
来指定共享库的输出目录。
这是关于Output Artifacts的CMake文档中记录的内容:
运行时输出工件
构建系统的运行时输出工件 目标可能是:
- 由目标创建的可执行目标的可执行文件(例如.exe) add_executable()命令。
- 在DLL平台上:可执行文件(例如 (.dll)(由add_library()命令创建) 与共享选项。 RUNTIME_OUTPUT_DIRECTORY和 RUNTIME_OUTPUT_NAME目标属性可用于控制运行时 在构建树中输出工件位置和名称。
库输出工件
构建系统的库输出工件 目标可能是:
- 模块库目标的可加载模块文件(例如.dll或.so) 由具有MODULE选项的add_library()命令创建。
- 开启 非DLL平台:的共享库文件(例如.so或.dylib) 由add_library()命令使用以下命令创建的共享库目标 共享选项。 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
)