问题描述
我正在使用以下 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上,我正在构建库使用:
And on Windows, I'm building the library using:
mkdir build
cd build
cmake ../src
cmake --build .
输出文件: 〜/ build / Debug /foo.dll
预期的输出文件: 〜/ build / Debug / subdir /foo.dll
我在做什么错了?
工作正常在Windows以外的平台上,似乎应该根据以下文档进行操作:
It works fine on platforms other than Windows, and it seems like it should work according to the following documentation:
- 。
- add_library
- set_target_properties
- LIBRARY_OUTPUT_DIRECTORY
- cmake-generator-expressions.
推荐答案
简短答案
在Windows上,与其他平台不同,应使用 RUNTIME_OUTPUT_DIRECTORY
代替 LIBRARY_OUTPUT_DIRECTORY
来指定共享库的输出目录。
Short answer
On Windows, unlike other platforms, you should use RUNTIME_OUTPUT_DIRECTORY
instead of LIBRARY_OUTPUT_DIRECTORY
to specify the output directory of a shared library.
这在CMake文档中有关:
This is documented on the CMake documentation about Output Artifacts:
构建系统
目标的运行时输出工件可能是:
A runtime output artifact of a buildsystem target may be:
- 可执行文件(例如.exe)由
add_executable()命令创建的可执行目标。 - 在DLL平台上:可执行文件(例如
.dll)由add_library()命令
使用SHARED选项创建的共享库目标。 RUNTIME_OUTPUT_DIRECTORY和
RUNTIME_OUTPUT_NAME目标属性可用于控制构建树中的运行时
输出工件位置和名称。
- The executable file (e.g. .exe) of an executable target created by the add_executable() command.
- On DLL platforms: the executable file (e.g. .dll) of a shared library target created by the add_library() command with the SHARED option. The RUNTIME_OUTPUT_DIRECTORY and RUNTIME_OUTPUT_NAME target properties may be used to control runtime output artifact locations and names in the build tree.
库输出工件
构建系统
目标的库输出工件可能是:
A library output artifact of a buildsystem target may be:
- 由add_library()命令使用MODULE选项创建的模块库目标
的可加载模块文件(例如.dll或.so)。 - 在
非DLL平台上:由
共享库目标创建的共享库文件(例如.so或.dylib)使用
的SHARED选项执行add_library()命令。 LIBRARY_OUTPUT_DIRECTORY和
LIBRARY_OUTPUT_NAME目标属性可用于控制库
输出构件的位置和生成树中的名称。
- The loadable module file (e.g. .dll or .so) of a module library target created by the add_library() command with the MODULE option.
- On non-DLL platforms: the shared library file (e.g. .so or .dylib) of a shared library target created by the add_library() command with the SHARED option. The LIBRARY_OUTPUT_DIRECTORY and LIBRARY_OUTPUT_NAME target properties may be used to control library output artifact locations and names in the build tree.
但是为什么CMake在DLL平台(Windows)和非DLL平台(macOS,Linux等)之间产生如此大的差异?
But why would CMake make such a difference between DLL platforms (Windows) and non-DLL platforms (macOS, Linux, etc.)?
我找不到记录该设计决定的资料,但是我认为其基本原理是Windows不支持 rpath
的概念,即 .exe
文件无法在内部存储其依赖的 .dll
文件的位置。因此,在Windows上, .dll
文件通常与 .exe
文件存储在同一文件夹中,以确保在运行时可以找到DLL。相反,在Unix系统上,共享库文件通常存储在单独的 lib
文件夹中,而应用程序二进制文件则存储在 bin
文件夹,这不是问题,因为二进制文件可以使用 rpath
存储其依赖项的位置。
I couldn't find a source documenting this design decision, but I believe the rationale is that Windows does not support the concept of rpath
, that is, .exe
files can't store internally the location of their dependent .dll
files. Therefore, on Windows, .dll
files are often stored in the same folder as .exe
files to make sure that the DLLs are found at runtime. Instead, on Unix systems, shared library files are often stored in a separate lib
folder, while application binaries are stored in a bin
folder, which is not a problem because binaries can store the location of their dependencies using rpath
.
在结论,对于跨平台开发来说,定义 LIBRARY_OUTPUT_DIRECTORY
和 RUNTIME_OUTPUT_DIRECTORY
都是有意义的,就像这样:
In conclusion, it makes sense for cross-platform development to define both LIBRARY_OUTPUT_DIRECTORY
and RUNTIME_OUTPUT_DIRECTORY
, like so:
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
)
这篇关于如何指定给定DLL的输出目录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!