How to install() additional runtime (DLL) dependencies of an IMPORTED target?

Porting an old project to CMake, Windows only. One of our modules uses an external SDK (header files, DLL, import library, debug/release). I encapsulate the external SDK like so:

set(EXTERNAL_SDK_DIR "/some/dir/to/sdk")
add_library(ExternalSDK SHARED IMPORTED)
set_target_properties(ExternalSDK PROPERTIES
    IMPORTED_CONFIGURATIONS        "DEBUG;RELEASE"
    IMPORTED_LOCATION_DEBUG        ${EXTERNAL_SDK_DIR}/debug/sdk.dll
    IMPORTED_IMPLIB_DEBUG          ${EXTERNAL_SDK_DIR}/debug/sdk.lib
    IMPORTED_LOCATION_RELEASE      ${EXTERNAL_SDK_DIR}/release/sdk.dll
    IMPORTED_IMPLIB_RELEASE        ${EXTERNAL_SDK_DIR}/release/sdk.lib
    INTERFACE_INCLUDE_DIRECTORIES  ${EXTERNAL_SDK_DIR}/include
)

This works nicely, I can then use it with target_link_libraries() as usual, and even install the sdk.dll using:

install(IMPORTED_RUNTIME_ARTIFACTS ExternalSDK RUNTIME DESTINATION .)

Now my problem is that ExternalSDK has additional DLL files it depends on, which is not required for linking (say: "sdk_dep1.dll, sdk_dep2.dll, etc.), but must be installed as well. These DLLs are located inside the SDK folders.

Is there some way of attaching these to the imported target, so the above install(IMPORTED_RUNTIME_ARTIFACTS ...) command also installs them? I tried setting IMPORTED_LINK_DEPENDENT_LIBRARIES and it’s per-config variants on ExternalSDK, but they still don’t get installed.

I’d appreciate any help with this! Thanks!

1 Like

IMPORTED_RUNTIME_ARTIFACTS will only traverse DLLs known to CMake via IMPORTED targets. You can use file(GET_RUNTIME_DEPENDENCIES) to find other libraries needed.

I don’t really need to “find” these additional DLLs, they are already there explicitly in the SDK itself, they have a known name. They are loaded dynamically (using LoadLibrary()) by the SDK during runtime (they are not plugins, but conceptually similar).
It seems to me file(GET_RUNTIME_DEPENDENCIES) is for some different purpose.

What I really want is to “bundle” or “tie” somehow these additional DLLs to the imported target, so the user of the imported target can easily install it together with it’s dependencies.

EDIT: While we’re at it, there’s another SDK which has additional executables bundled, which the SDK uses during runtime as surrogates to do some work, but the idea is the same, the executables will have to be copied next to the main SDK DLL (which the app is linked against). How should I go about bundling those?

They’'ll need to be managed manually then I’m afraid.

You’re best modeling this as if they were dependent targets with some genex to disable actually linking them somehow.

@ignus2 were you able to find a way to achieve what you were looking for?

@wuziq We found no general solution. So I wrote a function which takes care of installing the dependencies explicitly. The dependencies were wrapped as IMPORTED MODULE targets, though that is not strictly necessary, they might as well be installed as files.