Generator expression in RUNTIME_DEPENDENCY_SET DIRECTORIES

Hi,

I try to work around a shared library with a bad RUNPATH on linux. The RUNPATH does not exist on my local host but is included in the library delivery that I get for the moment. This leads to a “file Could not resolve runtime dependencies” error when using install(RUNTIME_DEPENDENCY_SET).

I have a shared library A that links against shared library B and C and the RUNPATH of shared library A is set but not existing on my machine. If I try to install library A now the dependency for library B can’t be found.
I get a

CMake Error at cmake_install.cmake:85 (file):
  file Could not resolve runtime dependencies:

    liblibB.so
    liblibC.so

Now my idea was to add an additional search directory to the install(RUNTIME_DEPENDENCY_SET) based on the INTERFACE_LINK_DIRECTORIES target property to work around the problem. However if I use a generator expression for that the returned semicolon separated list in case of multiple dependencies is wrapped in quotes and passed to file(GET_RUNTIME_DEPENDENCIES) where it is not interpreted as a list anymore.

Here is a minimal example where I tried to reconstruct the problem.

cmake_minimum_required(VERSION 3.24)
project(my_test_project)

add_library(libB SHARED ${CMAKE_CURRENT_SOURCE_DIR}/libB/libB.cpp)
target_include_directories(libB PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libB)

add_library(libC SHARED ${CMAKE_CURRENT_SOURCE_DIR}/libC/libC.cpp)
target_include_directories(libC PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libC)

add_library(libA SHARED ${CMAKE_CURRENT_SOURCE_DIR}/libA/libA.cpp)
target_include_directories(libA PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libA)
target_link_libraries(libA PUBLIC libB libC)

# unset RUNPATH to simulate broken one
set_target_properties(libA PROPERTIES SKIP_BUILD_RPATH True)

add_executable(main main.cpp)
target_link_libraries(main PRIVATE libA)

install(TARGETS
    main
    libA
    RUNTIME_DEPENDENCY_SET myRuntimeSet
)

install(RUNTIME_DEPENDENCY_SET myRuntimeSet
    DIRECTORIES $<TARGET_PROPERTY:libA,INTERFACE_LINK_DIRECTORIES>
)

Is there a way to prevent DIRECTORIES $<TARGET_PROPERTY:libA,INTERFACE_LINK_DIRECTORIES> to be interpreted as string and passed to the file command in the cmake_install.cmake? And in my example the requested target property is empty at all. Why is that the case? Shouldn’t it contain paths to liblibB and liblibC? In a real example it’s filled properly.

I’m not sure what cmake_install.cmake is going to do with it as the target and its properties do not exist anymore. This needs to be resolved at generate time.

It seems the issue is the unconditional quote-wrapping. It should probably do genex-expansion and then quote-wrap. An issue for this would be good I think.

Cc: @kyle.edwards

I have the same problem, writing:

install(RUNTIME_DEPENDENCY_SET exe_deps
        DIRECTORIES
        "$<TARGET_RUNTIME_DLL_DIRS:${EXECUTABLE_TARGET}>"
)

generates (semi-correctly) a code block in cmake_install.cmake like this:

if(CMAKE_INSTALL_COMPONENT STREQUAL "Unspecified" OR NOT CMAKE_INSTALL_COMPONENT)
  file(GET_RUNTIME_DEPENDENCIES
    RESOLVED_DEPENDENCIES_VAR _CMAKE_DEPS
    EXECUTABLES
      "H:/work/git/meta-extract/build/Release/stage/bin/meta_extract.exe"
    DIRECTORIES
      "C:/Users/my/.conan2/p/some5adecf33bc168/p/bin;C:/Users/my/.conan2/p/thing92e964c4b7d75/p/bin"
    )
endif()

Unfortunately the file() command interprets the DIRECTORIES string as a single argument, and not as 2 distinct directories.

Same happens when I have those directories assembled manually in a list variable and pass that as argument.

Is there a way to prevent the quotation marks, similar to COMMAND_EXPAND_LISTS, maybe?

Not today:

I created a ticket for that problem: https://gitlab.kitware.com/cmake/cmake/-/issues/26076