How to specify the output directory of a given DLL?

安稳与你 提交于 2020-07-16 08:26:52

问题


I'm using the following 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
)

And on Windows, I'm building the library using:

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

Output File: ~/build/Debug/foo.dll

Expected Output File: ~/build/Debug/subdir/foo.dll

What am I doing wrong?

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.

回答1:


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.

Long answer

This is documented on the CMake documentation about Output Artifacts:

Runtime Output Artifacts

A runtime output artifact of a buildsystem target may be:

  • 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.

Library Output Artifacts

A library output artifact of a buildsystem target may be:

  • 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.

But why would CMake make such a difference between DLL platforms (Windows) and non-DLL platforms (macOS, Linux, etc.)?

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.

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
)


来源:https://stackoverflow.com/questions/56514533/how-to-specify-the-output-directory-of-a-given-dll

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!