install(IMPORTED_RUNTIME_ARTIFACTS ...) with a conditionally static/shared dependency

Hey,

I was setting up a project with CMake 3.21 (with CMakePresets.json) with one preset that uses system packages and one that uses the vcpkg toolchain (if installed) to make development easy to get in (specifically for Windows).

When installing dependencies (currently only SDL2) I ran into the problem that install(IMPORTED_RUNTIME_ARTIFACTS SDL2::SDL2 ...) on linux using the vcpkg preset errors due to it being an alias, because if SDL2 is build statically (vcpkg default on linux) it aliases SDL2::SDL2-static to SDL2::SDL2 (even if it wouldn’t be an alias I expect it to error since it’s a static library).

Breakdown:

  • Windows + Native install: CMake configuration error since it can’t find SDL2 (expected)
  • Windows + vcpkg install: Everything works fine and installs dependencies (expected)
  • Linux + Native install: Everything works fine and installs dependencies (expected)
  • Linux + vcpkg install: CMake configuration error because SDL2::SDL2 is an alias (unsure what to do about this?)

Now I was wondering if there is any specific way I could get this to install the dependencies only when they are built dynamically?

You can detect the type of a target by querying its properties. If it is ALIAS, you can get the alias name and recurse on that.

While I’ve just kinda given up on trying to get a clean solution to this I’ve figured out this snippet for now that kinda does the job in case anyone else is in need of a similar solution:

get_directory_property(IMPORTED_TARGETS IMPORTED_TARGETS)

unset(IMPORTED_TARGETS_INSTALL)
foreach(TARGET IN LISTS IMPORTED_TARGETS)
    get_target_property(TARGET_TYPE ${TARGET} TYPE)
    if (${TARGET_TYPE} MATCHES "(EXECUTABLE|SHARED_LIBRARY|MODULE_LIBRARY)")
        list(APPEND IMPORTED_TARGETS_INSTALL ${TARGET})
    endif (${TARGET_TYPE} MATCHES "(EXECUTABLE|SHARED_LIBRARY|MODULE_LIBRARY)")
endforeach(TARGET IN LISTS IMPORTED_TARGETS)

install(IMPORTED_RUNTIME_ARTIFACTS
    ${IMPORTED_TARGETS_INSTALL}
    RUNTIME
        DESTINATION ${CMAKE_INSTALL_BINDIR}
        COMPONENT Dependencies
    LIBRARY
        DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT Dependencies
)

TLDR: get all imported targets in the current directory, filter non-installable imports out and then install the rest