【问题标题】:How to specify the output directory of a given DLL?如何指定给定 DLL 的输出目录?
【发布时间】:2019-06-09 12:19:06
【问题描述】:

我正在使用以下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 以外的平台上正常工作,而且它似乎应该根据以下文档工作:

【问题讨论】:

    标签: windows dll cmake shared-libraries


    【解决方案1】:

    简答

    在 Windows 上,与其他平台不同,您应该使用 RUNTIME_OUTPUT_DIRECTORY 而不是 LIBRARY_OUTPUT_DIRECTORY 来指定共享库的输出目录。

    长答案

    这在 CMake 文档中记录了关于 Output Artifacts:

    运行时输出工件

    构建系统的运行时输出工件 目标可能是:

    • 由 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
    )
    

    【讨论】:

    • 在具有共享库、测试和可执行文件的复杂 CMake 项目中,我主要使用项目的 CMAKE_RUNTIME_OUTPUT_DIRECTORY、CMAKE_ARCHIVE_OUTPUT_DIRECTORY 和 CMAKE_LIBRARY_OUTPUT_DIRECTORY 变量。它们还允许您根据构建类型设置输出目录,例如CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG,CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO,...
    • @vre 如果更喜欢使用全局变量而不是每个目标的属性,当然,您可以这样做。但重点仍然存在:在 Windows 上,共享库将转到 CMAKE_RUNTIME_OUTPUT_DIRECTORY,而在 Linux 和 macOS 上,它们将转到 CMAKE_LIBRARY_OUTPUT_DIRECTORY :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 2018-03-31
    • 2021-11-16
    • 1970-01-01
    相关资源
    最近更新 更多