Installing dll dependencies using RUNTIME_DEPENDENCY_SET and $<TARGET_RUNTIME_DLL_DIRS:${target}> bug?

I think I found an issue with how the cmake_install.cmake is generated or I’m using it wrong.

Using the latest, 3.29.4, and attempting to create an install routine to bundle runtime dlls, for a product; dlls are for things like OpenDDS, OpenCV, VLC, etc.

I created the following two chunks:

install(TARGETS ${PROJECT_NAME} RUNTIME_DEPENDENCY_SET deps DESTINATION bin)

install(RUNTIME_DEPENDENCY_SET deps
        DIRECTORIES
        "$<TARGET_RUNTIME_DLL_DIRS:${PROJECT_NAME}>"
)

And looking in the the generate cmake_install.cmake file, I can see the created routine; it calls out the correct exe, a set of directories and post_exclude_file_strict that contains a list of dlls that are created by subprojects from the same solution. Awesome! Problem is, when I run my install routine, it fails to satisfy the dll’s that are found listed under DIRECTORIES.

After some troubleshooting, I think I discovered why. It looks like cmake is incorrectly creating the list of paths under DIRECTORIES. They are set up as a single quoted string, delimited by a semicolon. If I manually edit this sub routine, and break apart the directories into their own quoted strings, so they’d look like: (Dummy path names)

DIRECTORIES 
  "C:/Dir1/"
  "C:/Dir2/"
  "C:/dir3/bin"

instead of

DIRECTORIES 
  "C:/Dir1/;C:/Dir2/;C:/dir3/bin"

And then rerun my install routine, it no longer reports failure to find the dlls in those directories.

Am I doing something incorrectly? It seems cmake should generate the DIRECTORIES field properly but maybe I’m missing something

Use only:

I’ve actually tried this in the beginning with less success.

Cmake_install is regenerated but it has no knowledge what directories to search with just that one line. Additionally, it now fails to understand the bitness of that exe and which dlls it needs to search for.

As a note: I break down out external library by a win32 or win64 sub directory that sits within the root of the library name folder. So, for example, for OpenDDS, it would be similar to C:\Libraries\OpenDDS\win32 or C:\Libraries\OpenDDS\win64

In the method I used; the DIRECTORIES field was actually set up, automatically to point to C:\Libraries\OpenDDS\win32\bin and could find what it needs. Same worked for x64 exe, it chose the correct dir, with the win64 path.

The method I used I discovered here Generator expression in RUNTIME_DEPENDENCY_SET DIRECTORIES - Code - CMake Discourse

If it didn’t group the directories list in a single quoted, delimited list, this method would just work and it seems it would fix the lack of knowledge a basic install(RUNTIME_DEPENDENCY_SET) command has towards choosing the correct bitness

It sounds like you need the list to be expanded on the semicolon delimiters, but the expansion is being prevented by the quotes in

According to https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#lists, it seems like you should try removing the quotes.

I think I tried that and I just tried it again without the quotes. It seems surrounding the gen expression in quotes or not, has the same effect. The created cmake_install still contains a delimited listed surrounded by one set of quotes and fails to understand the directories.

I ended up creating my own macro that uses a few gen expressions, file(GET_RUNTIME_DEPENDENCIES) and a foreach to install the dependencies. It works in the way I’d expect RUNTIME_DEPENDENCY_SET to work.