3

Basically I want CMake to copy dependency's dll to the same directory of the executable. Suppose I have the following directory structure:

my-project/
    CMakeLists.txt
    lib/
        CMakeLists.txt
        ... # Some source files
    app/
        CMakeLists.txt
        ... # Some source files

The library lib depends on some third party dll, say foo.dll. The executable in app, say app.exe, depends on lib.

I've written a FindFOO.cmake to make the third party library foo.dll an imported target named foo.

Now when I compile app, in order to run the executable, foo.dll is required to be in the same directory as app.exe. How can this be achieved automatically with cmake? And what if I want to use CPack to package the application into an installer?

Richard
  • 233
  • 1
  • 3
  • 9

1 Answers1

2

CMAKE_RUNTIME_OUTPUT_DIRECTORY is your friend.

If this variable is created before creating some target, if the target is RUNTIME, it will define where the output of the target will be placed.

In your case, it can be used to force foo.dll and app.exe to be in the same folder. Your root CMakeLists.txt should look like this:

cmake_minimum_required(VERSION 3.15)
project(foo_and_app)

# app.exe and foo.dll will be in bin subfolder of build dir 
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

add_subdirectory(lib)
add_subdirectory(app)

#not connected to placement, but only to package creation
include(CPack)

It should be noted that this variable is used to initialize the properties of the targets added, meaning that everything may also be achieved by directly manipulating appropriate target properties.

Regarding packaging, what you ask is possible, regardless of the placement of runtime targets, by using install cmake statement. In lib/CMakeLists.txt you should add something like this:

# suppose that the target named `foo`,
# i.e. it is added by add_library(foo SHARED .....)  

install(TARGETS foo 
        RUNTIME DESTINATION bin
        )

same should be done for app/CMakeLists.txt:

# suppose that the target named `app`,
# i.e. it is added by add_executable(app .....)  

install(TARGETS app 
        RUNTIME DESTINATION bin
        )

If you have these install statements, the final destination will be bin folder within the chosen install folder.

In the end, here are the links for CMake documentation describing:

CMAKE_RUNTIME_OUTPUT_DIRECTORY variable

RUNTIME cmake targets

install(TARGETS ...)

gordan.sikic
  • 1,174
  • 8
  • 8
  • for dll library you must use **LIBRARY_OUTPUT_DIRECTORY** src: https://cmake.org/cmake/help/latest/prop_tgt/LIBRARY_OUTPUT_DIRECTORY.html runtime is for *add_executable* note: you also have ARCHIVE_OUTPUT_LIBRARY for static libraries... – Mizux Sep 05 '19 at 13:11
  • 1
    @Mizux: If I recall correctly, shared libraries in Windows are made of two files: A `.dll` and an associated `.lib` import library file. When you call `add_library(SHARED)`, CMake handles the [`.dll` file as a `RUNTIME` output artifact](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#runtime-output-artifacts) just like the `.exe` files. – TManhente Sep 25 '19 at 13:35
  • 1
    He is asking about 3rd-party imported library. How CMAKE_RUNTIME_OUTPUT_DIRECTORY can help???? – def Dec 02 '21 at 01:24