igl_copy_dll.cmake 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. # Sanity checks
  48. get_target_property(TYPE ${target} TYPE)
  49. if(NOT ${TYPE} STREQUAL "EXECUTABLE")
  50. message(FATAL_ERROR "igl_copy_dll() was called on a non-executable target: ${target}")
  51. endif()
  52. # Create a custom command to do the actual copy. This needs to be executed before Catch2's POST_BUILD command,
  53. # so we define this as a PRE_LINK command for the executable target.
  54. add_custom_command(
  55. TARGET ${target}
  56. PRE_LINK
  57. COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/runtime_deps/copy_dll_${target}_$<CONFIG>.cmake"
  58. COMMAND ${CMAKE_COMMAND} -P "${CMAKE_BINARY_DIR}/runtime_deps/copy_dll_${target}_$<CONFIG>.cmake"
  59. COMMENT "Copying dlls for target ${target}"
  60. )
  61. # Retrieve all target dependencies
  62. igl_get_dependencies(TARGET_DEPENDENCIES ${target})
  63. # Iterate over dependencies, and create a copy rule for each .dll that we find
  64. set(COPY_SCRIPT_CONTENT "")
  65. foreach(DEPENDENCY IN ITEMS ${TARGET_DEPENDENCIES})
  66. get_target_property(TYPE ${DEPENDENCY} TYPE)
  67. if(NOT (${TYPE} STREQUAL "SHARED_LIBRARY" OR ${TYPE} STREQUAL "MODULE_LIBRARY"))
  68. continue()
  69. endif()
  70. # Instruction to copy target file if it exists
  71. string(APPEND COPY_SCRIPT_CONTENT
  72. "if(EXISTS \"$<TARGET_FILE:${DEPENDENCY}>\")\n "
  73. "execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "
  74. "\"$<TARGET_FILE:${DEPENDENCY}>\" "
  75. "\"$<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_NAME:${DEPENDENCY}>\")\n"
  76. "endif()\n"
  77. )
  78. endforeach()
  79. # Finally generate one script for each configuration supported by this generator
  80. message(STATUS "Populating copy rules for target: ${target}")
  81. file(GENERATE
  82. OUTPUT ${CMAKE_BINARY_DIR}/runtime_deps/copy_dll_${target}_$<CONFIG>.cmake
  83. CONTENT "${COPY_SCRIPT_CONTENT}"
  84. )
  85. endfunction()