igl_copy_dll.cmake 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. # Transitively list all link libraries of a target (recursive call)
  2. function(igl_get_dependencies_recursive OUTPUT_VARIABLE TARGET)
  3. get_target_property(_aliased ${TARGET} ALIASED_TARGET)
  4. if(_aliased)
  5. set(TARGET ${_aliased})
  6. endif()
  7. get_target_property(_IMPORTED ${TARGET} IMPORTED)
  8. get_target_property(_TYPE ${TARGET} TYPE)
  9. if(_IMPORTED OR (${_TYPE} STREQUAL "INTERFACE_LIBRARY"))
  10. get_target_property(TARGET_DEPENDENCIES ${TARGET} INTERFACE_LINK_LIBRARIES)
  11. else()
  12. get_target_property(TARGET_DEPENDENCIES ${TARGET} LINK_LIBRARIES)
  13. endif()
  14. # MKL-specific list of runtime dependencies
  15. get_property(RUNTIME_DEPENDENCIES TARGET ${TARGET} PROPERTY mkl_RUNTIME_DEPENDENCIES)
  16. if(RUNTIME_DEPENDENCIES)
  17. list(APPEND TARGET_DEPENDENCIES ${RUNTIME_DEPENDENCIES})
  18. endif()
  19. set(VISITED_TARGETS ${${OUTPUT_VARIABLE}})
  20. foreach(DEPENDENCY IN ITEMS ${TARGET_DEPENDENCIES})
  21. if(TARGET ${DEPENDENCY})
  22. get_target_property(_aliased ${DEPENDENCY} ALIASED_TARGET)
  23. if(_aliased)
  24. set(DEPENDENCY ${_aliased})
  25. endif()
  26. if(NOT (DEPENDENCY IN_LIST VISITED_TARGETS))
  27. list(APPEND VISITED_TARGETS ${DEPENDENCY})
  28. igl_get_dependencies_recursive(VISITED_TARGETS ${DEPENDENCY})
  29. endif()
  30. endif()
  31. endforeach()
  32. set(${OUTPUT_VARIABLE} ${VISITED_TARGETS} PARENT_SCOPE)
  33. endfunction()
  34. # Transitively list all link libraries of a target
  35. function(igl_get_dependencies OUTPUT_VARIABLE TARGET)
  36. set(DISCOVERED_TARGETS "")
  37. igl_get_dependencies_recursive(DISCOVERED_TARGETS ${TARGET})
  38. set(${OUTPUT_VARIABLE} ${DISCOVERED_TARGETS} PARENT_SCOPE)
  39. endfunction()
  40. # Copy .dll dependencies to a target executable's folder. This function must be called *after* all the CMake
  41. # dependencies of the executable target have been defined, otherwise some .dlls might not be copied to the target
  42. # folder.
  43. function(igl_copy_dll target)
  44. if(NOT WIN32)
  45. return()
  46. endif()
  47. if(NOT TARGET ${target})
  48. message(STATUS "igl_copy_dll() was called with a non-target: ${target}")
  49. return()
  50. endif()
  51. # Sanity checks
  52. get_target_property(TYPE ${target} TYPE)
  53. if(NOT ${TYPE} STREQUAL "EXECUTABLE")
  54. message(FATAL_ERROR "igl_copy_dll() was called on a non-executable target: ${target}")
  55. endif()
  56. # Create a custom command to do the actual copy. This needs to be executed before Catch2's POST_BUILD command,
  57. # so we define this as a PRE_LINK command for the executable target.
  58. add_custom_command(
  59. TARGET ${target}
  60. PRE_LINK
  61. COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/runtime_deps/copy_dll_${target}_$<CONFIG>.cmake"
  62. COMMAND ${CMAKE_COMMAND} -P "${CMAKE_BINARY_DIR}/runtime_deps/copy_dll_${target}_$<CONFIG>.cmake"
  63. COMMENT "Copying dlls for target ${target}"
  64. )
  65. # Retrieve all target dependencies
  66. igl_get_dependencies(TARGET_DEPENDENCIES ${target})
  67. # Iterate over dependencies, and create a copy rule for each .dll that we find
  68. set(COPY_SCRIPT_CONTENT "")
  69. foreach(DEPENDENCY IN ITEMS ${TARGET_DEPENDENCIES})
  70. get_target_property(TYPE ${DEPENDENCY} TYPE)
  71. if(NOT (${TYPE} STREQUAL "SHARED_LIBRARY" OR ${TYPE} STREQUAL "MODULE_LIBRARY"))
  72. continue()
  73. endif()
  74. # Instruction to copy target file if it exists
  75. string(APPEND COPY_SCRIPT_CONTENT
  76. "if(EXISTS \"$<TARGET_FILE:${DEPENDENCY}>\")\n "
  77. "execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "
  78. "\"$<TARGET_FILE:${DEPENDENCY}>\" "
  79. "\"$<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_NAME:${DEPENDENCY}>\")\n"
  80. "endif()\n"
  81. )
  82. endforeach()
  83. # Finally generate one script for each configuration supported by this generator
  84. message(STATUS "Populating copy rules for target: ${target}")
  85. file(GENERATE
  86. OUTPUT ${CMAKE_BINARY_DIR}/runtime_deps/copy_dll_${target}_$<CONFIG>.cmake
  87. CONTENT "${COPY_SCRIPT_CONTENT}"
  88. )
  89. endfunction()