如何指定给定DLL的输出目录?

时间:2019-06-09 12:19:06

标签: 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
)

在Windows上,我使用以下命令构建库:

mkdir build
cd build
cmake ../src
cmake --build .

输出文件: ~/build/Debug/foo.dll

预期的输出文件: ~/build/Debug/subdir/foo.dll

我在做什么错了?

它在Windows以外的平台上都可以正常工作,并且似乎应该根据以下文档进行工作:

1 个答案:

答案 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_DIRECTORYRUNTIME_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
)