How to best tell CMake where to find dll

2020-07-21 08:57发布

问题:

I have a simple project structure derived from the amazing tutorial

https://rix0r.nl/blog/2015/08/13/cmake-guide/

It looks as follows:

- src
  - CMakeLists.txt
  - mylib
    - include/mylib/mylibclass.h
    - src/mylibclass.cpp
    - CMakeLists.txt
  - myapp
    - src/myapp.cpp
    - CMakeLists.txt

The top level CMakeLists.txt contains:

cmake_minimum_required( VERSION 3.6 )
project( sample_project VERSION 0.1 LANGUAGES CXX )

set( BUILD_SHARED_LIBS ON CACHE BOOL "" )

add_subdirectory( mylib )
add_subdirectory( myapp )

The CMakeLists.txt in the mylib folder contains:

add_library( mylib src/mylibclass.cpp include/mylib/mylibclass.h )
set_target_properties( mylib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
target_include_directories( mylib
    PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PRIVATE src )  

And the one in the myapp folder contains:

add_executable( myapp src/myapp.cpp )
target_link_libraries( myapp mylib )

I want to use this structure to develop both mylib (as a shared or static library as determined by BUILD_SHARED_LIBS) and myapp. For this, I want to set myapp as my startup project in Visual Studio and compile and run in the MSVC debugger. This is not possible for the shared library case without extra CMake code, as the myapp.exe doesn't know where to find the mylib.dll.

What is best CMake practice to tell the program where to find the dll?

Edit:

Based on the suggestions by @Andre, I've added the following lines to the top level CMakeLists.txt:

set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out CACHE STRING "" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out CACHE STRING "" )

回答1:

The problem occurs, because your mylib.dll is not in the same folder as your myapp.exe nor is it in the %PATH% environment variable when Visual Studio tries to start your myapp.exe

The obvious solution is to make sure both dll and exe are in the same folder. There are several ways to do this:

  1. Put both exe and dll into a single "output" directory by setting the RUNTIME_OUTPUT_DIRECTORY and the LIBRARY_OUTPUT_DIRECTORY properties on your targets:

     set_target_properties( myapp PROPERTIES RUNTIME_OUTPUT_DIRECTORY 
        ${sample_project_BINARY_DIR}/build_results/bin )
     set_target_properties( mylib PROPERTIES LIBRARY_OUTPUT_DIRECTORY
        ${sample_project_BINARY_DIR}/build_results/bin )
    

    This will produce the myapp.exe and mylib.dll into a single build_results/bin folder in your top-level build folder.

  2. Or by setting the the global CMAKE_RUNTIME_OUTPUT_DIRECTORY and CMAKE_LIBRARY_OUTPUT_DIRECTORY variables which will do this for all targets in your sample_project.

  3. Copy the dll to the exe location after building, e.g. with

    add_custom_command(TARGET mylib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy mylib.dll ${myapp_BINARY_DIR}/. )