RuntimeDependencies_common.cmake 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. #
  2. # Copyright (c) Contributors to the Open 3D Engine Project.
  3. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. #
  5. # SPDX-License-Identifier: Apache-2.0 OR MIT
  6. #
  7. #
  8. set(LY_COPY_PERMISSIONS "OWNER_READ OWNER_WRITE OWNER_EXECUTE")
  9. set(LY_TARGET_TYPES_WITH_RUNTIME_OUTPUTS UTILITY MODULE_LIBRARY SHARED_LIBRARY EXECUTABLE APPLICATION)
  10. # There are several dependencies to handle:
  11. # 1. Dependencies to 3rdparty libraries. This involves copying IMPORTED_LOCATION to the folder where the target is.
  12. # Some 3rdParty may require to copy the IMPORTED_LOCATION to a relative folder to where the target is.
  13. # 2. Dependencies to files. This involves copying INTERFACE_LY_TARGET_FILES to the folder where the target is. In
  14. # this case, the files may include a relative folder to where the target is.
  15. # 3. In some platforms and types of targets, we also need to copy the MANUALLY_ADDED_DEPENDENCIES to the folder where the
  16. # target is. This is because the target is not in the same folder as the added dependencies.
  17. # In all cases, we need to recursively walk through dependencies to find the above. In multiple cases, we will end up
  18. # with the same files trying to be copied to the same place. This is expected, we still want to be able to produce a
  19. # working output per target, so there will be duplication.
  20. # The Dependencies get stored in the following args:
  21. # \arg: COPY_DEPENDENCIES_VAR stores the encoded file dependency with the output subdirectory to copy the file dependency
  22. # These dependencies are set via the `ly_add_target_files` command
  23. # \arg: TARGET_DEPENDENCIES_VAR stores all MANUALLY_ADDED_DEPENDENCIES for the target by recursively visiting
  24. # each target added dependencies
  25. # These dependences are set via [add_dependencies](https://cmake.org/cmake/help/latest/command/add_dependencies.html)
  26. # \arg: LINK_DEPENDENCIES_VAR stores all link library dependencies found by recursing the LINK_LIBRARIES TARGET property
  27. # These are dependencies specified to the [target_link_libraries](https://cmake.org/cmake/help/latest/command/target_link_libraries.html?highlight=target_link_libraries) command
  28. # \arg: IMPORTED_DEPENDENCIES_VAR populated with the IMPORTED_LOCATION(_<config>) or INTERFACE_IMPORTED_LOCATION(_<config>) property of the TARGET
  29. # when the target is an IMPORTED library with a pre-built binary
  30. # Regular Arguments are as follows:
  31. # \arg: TARGET CMake target to search for the dependencies
  32. function(o3de_get_dependencies_for_target)
  33. set(options)
  34. set(oneValueArgs TARGET COPY_DEPENDENCIES_VAR TARGET_DEPENDENCIES_VAR LINK_DEPENDENCIES_VAR IMPORTED_DEPENDENCIES_VAR)
  35. set(multiValueArgs)
  36. cmake_parse_arguments("${CMAKE_CURRENT_FUNCTION}" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  37. set(target "${${CMAKE_CURRENT_FUNCTION}_TARGET}")
  38. set(copy_dependencies_var "${${CMAKE_CURRENT_FUNCTION}_COPY_DEPENDENCIES_VAR}")
  39. set(target_dependencies_var "${${CMAKE_CURRENT_FUNCTION}_TARGET_DEPENDENCIES_VAR}")
  40. set(link_dependencies_var "${${CMAKE_CURRENT_FUNCTION}_LINK_DEPENDENCIES_VAR}")
  41. set(imported_dependencies_var "${${CMAKE_CURRENT_FUNCTION}_IMPORTED_DEPENDENCIES_VAR}")
  42. # check to see if this target is a 3rdParty lib that was a downloaded package,
  43. # and if so, activate it. This also calls find_package so there is no reason
  44. # to do so later.
  45. ly_parse_third_party_dependencies(${target})
  46. # The above needs to be done before the below early out of this function!
  47. if(NOT TARGET ${target})
  48. return() # Nothing to do
  49. endif()
  50. ly_de_alias_target(${target} target)
  51. # To optimize the search, we are going to cache the dependencies for the targets we already walked through.
  52. # To do so, we will create several variables named target} which will contain a list
  53. # of all the dependencies
  54. # If the variable is not there, that means we have not walked it yet.
  55. get_property(are_dependencies_cached GLOBAL PROPERTY O3DE_DEPENDENCIES_CACHED_${target} SET)
  56. if(are_dependencies_cached)
  57. # We already walked through this target
  58. if (NOT copy_dependencies_var STREQUAL "")
  59. get_property(copy_dependencies GLOBAL PROPERTY O3DE_COPY_DEPENDENCIES_${target})
  60. set(${copy_dependencies_var} ${copy_dependencies} PARENT_SCOPE)
  61. endif()
  62. if (NOT target_dependencies_var STREQUAL "")
  63. get_property(target_dependencies GLOBAL PROPERTY O3DE_TARGET_DEPENDENCIES_${target})
  64. set(${target_dependencies_var} ${target_dependencies} PARENT_SCOPE)
  65. endif()
  66. if (NOT link_dependencies_var STREQUAL "")
  67. get_property(link_dependencies GLOBAL PROPERTY O3DE_LINK_DEPENDENCIES_${target})
  68. set(${link_dependencies_var} ${link_dependencies} PARENT_SCOPE)
  69. endif()
  70. if (NOT imported_dependencies_var STREQUAL "")
  71. get_property(imported_dependencies GLOBAL PROPERTY O3DE_IMPORTED_DEPENDENCIES_${target})
  72. set(${imported_dependencies_var} ${imported_dependencies} PARENT_SCOPE)
  73. endif()
  74. return()
  75. endif()
  76. # Unset the aggregate dependency list variables
  77. unset(all_copy_dependencies)
  78. unset(all_target_dependencies)
  79. unset(all_link_dependencies)
  80. unset(all_imported_dependencies)
  81. # Collect all dependencies to other targets. Dependencies are through linking (LINK_LIBRARIES), and
  82. # other manual dependencies (MANUALLY_ADDED_DEPENDENCIES)
  83. get_target_property(target_type ${target} TYPE)
  84. unset(link_dependencies)
  85. unset(dependencies)
  86. get_target_property(dependencies ${target} INTERFACE_LINK_LIBRARIES)
  87. if(dependencies)
  88. list(APPEND link_dependencies ${dependencies})
  89. endif()
  90. if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
  91. unset(dependencies)
  92. get_target_property(dependencies ${target} LINK_LIBRARIES)
  93. if(dependencies)
  94. list(APPEND link_dependencies ${dependencies})
  95. endif()
  96. endif()
  97. # link dependencies are not runtime dependencies (we dont have anything to copy) however, we need to traverse
  98. # them since them or some dependency downstream could have something to copy over
  99. foreach(link_dependency IN LISTS link_dependencies)
  100. if(${link_dependency} MATCHES "^::@")
  101. # Skip wraping produced when targets are not created in the same directory
  102. # (https://cmake.org/cmake/help/latest/prop_tgt/LINK_LIBRARIES.html)
  103. continue()
  104. endif()
  105. if(TARGET ${link_dependency})
  106. get_target_property(is_imported ${link_dependency} IMPORTED)
  107. get_target_property(is_system_library ${link_dependency} LY_SYSTEM_LIBRARY)
  108. if(is_imported AND is_system_library)
  109. continue()
  110. endif()
  111. # If the link dependency target has runtime outputs itself then
  112. # add it as a runtime dependency as well.
  113. get_target_property(link_dependency_type ${link_dependency} TYPE)
  114. if(link_dependency_type IN_LIST LY_TARGET_TYPES_WITH_RUNTIME_OUTPUTS)
  115. list(APPEND all_link_dependencies ${link_dependency})
  116. endif()
  117. endif()
  118. unset(dependent_copy_dependencies)
  119. unset(dependent_target_dependencies)
  120. unset(dependent_link_dependencies)
  121. unset(dependent_imported_dependencies)
  122. o3de_get_dependencies_for_target(
  123. TARGET "${link_dependency}"
  124. COPY_DEPENDENCIES_VAR dependent_copy_dependencies
  125. TARGET_DEPENDENCIES_VAR dependent_target_dependencies
  126. LINK_DEPENDENCIES_VAR dependent_link_dependencies
  127. IMPORTED_DEPENDENCIES_VAR dependent_imported_dependencies
  128. )
  129. list(APPEND all_copy_dependencies ${dependent_copy_dependencies})
  130. list(APPEND all_target_dependencies ${dependent_target_dependencies})
  131. list(APPEND all_link_dependencies ${dependent_link_dependencies})
  132. list(APPEND all_imported_dependencies ${dependent_imported_dependencies})
  133. endforeach()
  134. # For manual dependencies, we want to copy over the dependency and traverse them\
  135. unset(manual_dependencies)
  136. get_target_property(manual_dependencies ${target} MANUALLY_ADDED_DEPENDENCIES)
  137. if(manual_dependencies)
  138. foreach(manual_dependency ${manual_dependencies})
  139. if(NOT ${manual_dependency} MATCHES "^::@") # Skip wraping produced when targets are not created in the same directory (https://cmake.org/cmake/help/latest/prop_tgt/LINK_LIBRARIES.html)
  140. unset(dependent_copy_dependencies)
  141. unset(dependent_target_dependencies)
  142. unset(dependent_link_dependencies)
  143. unset(dependent_imported_dependencies)
  144. o3de_get_dependencies_for_target(
  145. TARGET "${manual_dependency}"
  146. COPY_DEPENDENCIES_VAR dependent_copy_dependencies
  147. TARGET_DEPENDENCIES_VAR dependent_target_dependencies
  148. LINK_DEPENDENCIES_VAR dependent_link_dependencies
  149. IMPORTED_DEPENDENCIES_VAR dependent_imported_dependencies
  150. )
  151. list(APPEND all_copy_dependencies ${dependent_copy_dependencies})
  152. list(APPEND all_target_dependencies ${dependent_target_dependencies})
  153. list(APPEND all_link_dependencies ${dependent_link_dependencies})
  154. list(APPEND all_imported_dependencies ${dependent_imported_dependencies})
  155. # Append the current manuallly added dependency to the end
  156. list(APPEND all_target_dependencies ${manual_dependency})
  157. endif()
  158. endforeach()
  159. endif()
  160. # Add the imported locations
  161. get_target_property(is_imported ${target} IMPORTED)
  162. if(is_imported)
  163. set(skip_imported FALSE)
  164. if(target_type MATCHES "(STATIC_LIBRARY|OBJECT_LIBRARY)")
  165. # No need to copy these dependencies since the outputs are not used at runtime
  166. set(skip_imported TRUE)
  167. endif()
  168. if(NOT skip_imported)
  169. # Add imported locations
  170. if(target_type STREQUAL "INTERFACE_LIBRARY")
  171. set(imported_property INTERFACE_IMPORTED_LOCATION)
  172. else()
  173. set(imported_property IMPORTED_LOCATION)
  174. endif()
  175. # The below loop emulates CMake's search for imported locations:
  176. unset(target_locations)
  177. foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES)
  178. string(TOUPPER ${conf} UCONF)
  179. # try to use the mapping
  180. get_target_property(mapped_conf ${target} MAP_IMPORTED_CONFIG_${UCONF})
  181. if(NOT mapped_conf)
  182. # if there's no mapping specified, prefer a matching conf if its available
  183. # and if its not, fall back to the blank/empty one (the semicolon is not a typo)
  184. set(mapped_conf "${UCONF};")
  185. endif()
  186. unset(current_target_locations)
  187. # note that mapped_conf is a LIST, we need to iterate the list and find the first one that exists:
  188. foreach(check_conf IN LISTS mapped_conf)
  189. # check_conf will either be a string like "RELEASE" or the blank empty string.
  190. if (check_conf)
  191. # a non-empty element indicates to look fro IMPORTED_LOCATION_xxxxxxxxx
  192. get_target_property(current_target_locations ${target} ${imported_property}_${check_conf})
  193. else()
  194. # an empty element indicates to look at the IMPORTED_LOCATION with no suffix.
  195. get_target_property(current_target_locations ${target} ${imported_property})
  196. endif()
  197. if(current_target_locations)
  198. # we need to escape any semicolons, since this could be a list.
  199. string(REPLACE ";" "$<SEMICOLON>" current_target_locations "${current_target_locations}")
  200. string(APPEND target_locations "$<$<CONFIG:${conf}>:${current_target_locations}>")
  201. break() # stop looking after the first one is found (This emulates CMakes behavior)
  202. endif()
  203. endforeach()
  204. if (NOT current_target_locations)
  205. # we didn't find any locations.
  206. if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
  207. # If you explicitly chose to declare a STATIC library but not supply an imported location
  208. # then its a mistake.
  209. message(FATAL_ERROR "${target_type} Library ${target} specified MAP_IMPORTED_CONFIG_${UCONF} = ${mapped_conf} but did not have any of ${imported_property}_xxxx set")
  210. endif()
  211. endif()
  212. endforeach()
  213. if(target_locations)
  214. list(APPEND all_imported_dependencies ${target_locations})
  215. endif()
  216. endif()
  217. endif()
  218. # Add target files (these are the ones added with ly_add_target_files)
  219. get_target_property(interface_target_files ${target} INTERFACE_LY_TARGET_FILES)
  220. if(interface_target_files)
  221. list(APPEND all_copy_dependencies ${interface_target_files})
  222. endif()
  223. # Remove duplicates from each set of dependencies
  224. list(REMOVE_DUPLICATES all_copy_dependencies)
  225. list(REMOVE_DUPLICATES all_target_dependencies)
  226. list(REMOVE_DUPLICATES all_link_dependencies)
  227. list(REMOVE_DUPLICATES all_imported_dependencies)
  228. # Add each type of dependencies to global property which act as a cache for
  229. # future calls with the same target
  230. set_property(GLOBAL PROPERTY O3DE_COPY_DEPENDENCIES_${target} ${all_copy_dependencies})
  231. set_property(GLOBAL PROPERTY O3DE_TARGET_DEPENDENCIES_${target} ${all_target_dependencies})
  232. set_property(GLOBAL PROPERTY O3DE_LINK_DEPENDENCIES_${target} ${all_link_dependencies})
  233. set_property(GLOBAL PROPERTY O3DE_IMPORTED_DEPENDENCIES_${target} ${all_imported_dependencies})
  234. # Set the O3DE_DEPENDENCIES_CACHED property for the target to indicate
  235. # the dependency search does not need to be done again
  236. set_property(GLOBAL PROPERTY O3DE_DEPENDENCIES_CACHED_${target} TRUE)
  237. # Update each of result variables for each typer of dependencies
  238. if (NOT copy_dependencies_var STREQUAL "")
  239. set(${copy_dependencies_var} ${all_copy_dependencies} PARENT_SCOPE)
  240. endif()
  241. if (NOT target_dependencies_var STREQUAL "")
  242. set(${target_dependencies_var} ${all_target_dependencies} PARENT_SCOPE)
  243. endif()
  244. if (NOT link_dependencies_var STREQUAL "")
  245. set(${link_dependencies_var} ${all_link_dependencies} PARENT_SCOPE)
  246. endif()
  247. if (NOT imported_dependencies_var STREQUAL "")
  248. set(${imported_dependencies_var} ${all_imported_dependencies} PARENT_SCOPE)
  249. endif()
  250. endfunction()
  251. #! This function accepts a dependency and returns
  252. #! a command to perform on that dependency as well as a file dependency
  253. #! which can be provided to the cmake to trigger the command to re-run
  254. # If the result variable is not supplied, nothing is set
  255. function(o3de_get_command_for_dependency)
  256. set(options)
  257. set(oneValueArgs DEPENDENCY COMMAND_VAR FILE_DEPENDENCY_VAR)
  258. set(multiValueArgs)
  259. cmake_parse_arguments("${CMAKE_CURRENT_FUNCTION}" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  260. set(dependency "${${CMAKE_CURRENT_FUNCTION}_DEPENDENCY}")
  261. set(command_var "${${CMAKE_CURRENT_FUNCTION}_COMMAND_VAR}")
  262. set(file_dependency_var "${${CMAKE_CURRENT_FUNCTION}_FILE_DEPENDENCY_VAR}")
  263. # To optimize this, we are going to cache the commands for the targets we requested. A lot of targets end up being
  264. # dependencies of other targets.
  265. get_property(is_command_cached GLOBAL PROPERTY O3DE_COMMAND_FOR_DEPENDENCY_${dependency} SET)
  266. if(is_command_cached)
  267. # We already walked through this target
  268. if (NOT command_var STREQUAL "")
  269. get_property(cached_command GLOBAL PROPERTY O3DE_COMMAND_FOR_DEPENDENCY_${dependency})
  270. set(${command_var} ${cached_command} PARENT_SCOPE)
  271. endif()
  272. if (NOT file_dependency_var STREQUAL "")
  273. get_property(cached_depend GLOBAL PROPERTY O3DE_FILE_DEPENDENCY_FOR_DEPENDENCY_${dependency})
  274. set(${file_dependency_var} "${cached_depend}" PARENT_SCOPE)
  275. endif()
  276. return()
  277. endif()
  278. unset(target_directory)
  279. unset(source_file)
  280. if(TARGET ${dependency})
  281. get_target_property(target_type ${dependency} TYPE)
  282. if(NOT target_type IN_LIST LY_TARGET_TYPES_WITH_RUNTIME_OUTPUTS)
  283. return()
  284. endif()
  285. set(source_file $<TARGET_FILE:${dependency}>)
  286. get_target_property(runtime_directory ${dependency} RUNTIME_OUTPUT_DIRECTORY)
  287. if(runtime_directory)
  288. file(RELATIVE_PATH target_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${runtime_directory})
  289. endif()
  290. # Query the SOURCE TYPE from the Target and pass it to the ly_copy command below
  291. get_property(source_type TARGET ${dependency} PROPERTY TYPE)
  292. # Also query if the source target is a gem module as well
  293. get_property(source_gem_module TARGET ${dependency} PROPERTY GEM_MODULE)
  294. else()
  295. string(REGEX MATCH "^([^\n]*)[\n]?(.*)$" target_file_regex "${dependency}")
  296. if(NOT target_file_regex)
  297. message(FATAL_ERROR "Unexpected error parsing \"${dependency}\"")
  298. endif()
  299. set(source_file ${CMAKE_MATCH_1})
  300. set(target_directory ${CMAKE_MATCH_2})
  301. endif()
  302. # Some notes on the generated command:
  303. # To support platforms where the binaries end in different places, we are going to assume that all dependencies,
  304. # including the ones we are building, need to be copied over. However, we add a check to prevent copying something
  305. # over itself. This detection cannot happen now because the target we are copying for varies.
  306. unset(runtime_command)
  307. string(APPEND runtime_command "ly_copy(\"${source_file}\" \"${target_directory}\" TARGET_FILE_DIR \"@target_file_dir@\""
  308. " SOURCE_TYPE \"${source_type}\" SOURCE_GEM_MODULE \"${source_gem_module}\")\n")
  309. set_property(GLOBAL PROPERTY O3DE_COMMAND_FOR_DEPENDENCY_${dependency} "${runtime_command}")
  310. set(${command_var} ${runtime_command} PARENT_SCOPE)
  311. if(NOT command_var STREQUAL "")
  312. set_property(GLOBAL PROPERTY O3DE_FILE_DEPENDENCY_FOR_DEPENDENCY_${dependency} "${source_file}")
  313. endif()
  314. if (NOT file_dependency_var STREQUAL "")
  315. set(${file_dependency_var} "${source_file}" PARENT_SCOPE)
  316. endif()
  317. endfunction()
  318. #! Extracts the source file tied to the dependency
  319. #! The dependency can be a TARGET or a file
  320. function(o3de_get_file_from_dependency)
  321. set(options)
  322. set(oneValueArgs SOURCE_FILE_VAR DEPENDENCY)
  323. set(multiValueArgs)
  324. cmake_parse_arguments("${CMAKE_CURRENT_FUNCTION}" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  325. set(dependency "${${CMAKE_CURRENT_FUNCTION}_DEPENDENCY}")
  326. set(source_file_var "${${CMAKE_CURRENT_FUNCTION}_SOURCE_FILE_VAR}")
  327. # Clear the variable pointed to by the source_file_var in the PARENT_SCOPE
  328. unset("${source_file_var}" PARENT_SCOPE)
  329. unset(source_file)
  330. if(TARGET ${dependency})
  331. get_property(target_type TARGET ${dependency} PROPERTY TYPE)
  332. if(NOT target_type IN_LIST LY_TARGET_TYPES_WITH_RUNTIME_OUTPUTS)
  333. return()
  334. endif()
  335. set(source_file $<TARGET_FILE:${dependency}>)
  336. else()
  337. string(REGEX MATCH "^([^\n]*)[\n]?(.*)$" file_regex "${dependency}")
  338. if(NOT file_regex)
  339. message(FATAL_ERROR "Cannot parse source file from \"${dependency}\" using regular expression")
  340. endif()
  341. cmake_path(SET source_file NORMALIZE ${CMAKE_MATCH_1})
  342. endif()
  343. if (source_file)
  344. set("${source_file_var}" "${source_file}" PARENT_SCOPE)
  345. endif()
  346. endfunction()
  347. function(o3de_transform_dependencies_to_files)
  348. set(options)
  349. set(oneValueArgs FILES_VAR)
  350. set(multiValueArgs DEPENDENCIES)
  351. cmake_parse_arguments("${CMAKE_CURRENT_FUNCTION}" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  352. set(dependencies "${${CMAKE_CURRENT_FUNCTION}_DEPENDENCIES}")
  353. set(files_var "${${CMAKE_CURRENT_FUNCTION}_FILES_VAR}")
  354. # Clear the variable output list variable in the PARENT_SCOPE
  355. unset("${files_var}" PARENT_SCOPE)
  356. unset(files)
  357. foreach(dependency IN LISTS dependencies)
  358. unset(source_file)
  359. o3de_get_file_from_dependency(
  360. SOURCE_FILE_VAR source_file
  361. DEPENDENCY "${dependency}"
  362. )
  363. list(APPEND files "${source_file}")
  364. endforeach()
  365. if(files)
  366. set("${files_var}" "${files}" PARENT_SCOPE)
  367. endif()
  368. endfunction()
  369. function(ly_delayed_generate_runtime_dependencies)
  370. get_property(additional_module_paths GLOBAL PROPERTY LY_ADDITIONAL_MODULE_PATH)
  371. list(APPEND CMAKE_MODULE_PATH ${additional_module_paths})
  372. get_property(all_targets GLOBAL PROPERTY LY_ALL_TARGETS)
  373. foreach(aliased_target IN LISTS all_targets)
  374. unset(target)
  375. ly_de_alias_target(${aliased_target} target)
  376. # Exclude targets that dont produce runtime outputs
  377. get_target_property(target_type ${target} TYPE)
  378. if(NOT target_type IN_LIST LY_TARGET_TYPES_WITH_RUNTIME_OUTPUTS)
  379. continue()
  380. endif()
  381. unset(LY_COPY_COMMANDS)
  382. unset(runtime_depends)
  383. unset(target_copy_dependencies)
  384. unset(target_target_dependencies)
  385. unset(target_link_dependencies)
  386. unset(target_imported_dependencies)
  387. o3de_get_dependencies_for_target(
  388. TARGET "${target}"
  389. COPY_DEPENDENCIES_VAR target_copy_dependencies
  390. TARGET_DEPENDENCIES_VAR target_target_dependencies
  391. LINK_DEPENDENCIES_VAR target_link_dependencies
  392. IMPORTED_DEPENDENCIES_VAR target_imported_dependencies
  393. )
  394. # Convert dependencies to files or generator expressions that can transform to files
  395. o3de_transform_dependencies_to_files(FILES_VAR target_copy_files
  396. DEPENDENCIES "${target_copy_dependencies}")
  397. o3de_transform_dependencies_to_files(FILES_VAR target_target_files
  398. DEPENDENCIES "${target_target_dependencies}")
  399. o3de_transform_dependencies_to_files(FILES_VAR target_link_files
  400. DEPENDENCIES "${target_link_dependencies}")
  401. o3de_transform_dependencies_to_files(FILES_VAR target_imported_files
  402. DEPENDENCIES "${target_imported_dependencies}")
  403. message(DEBUG "TARGET \"${target}\" has the following file dependencies:\n"
  404. "copy files -> \"${target_copy_files}\""
  405. "target files -> \"${target_target_files}\""
  406. "link files -> \"${target_copy_files}\""
  407. "imported files -> \"${target_copy_files}\"")
  408. foreach(dependency_for_target IN LISTS target_copy_dependencies
  409. target_link_dependencies
  410. target_target_dependencies
  411. target_imported_dependencies)
  412. unset(runtime_command)
  413. unset(runtime_depend)
  414. o3de_get_command_for_dependency(COMMAND_VAR runtime_command
  415. FILE_DEPENDENCY_VAR runtime_depend
  416. DEPENDENCY "${dependency_for_target}")
  417. string(APPEND LY_COPY_COMMANDS ${runtime_command})
  418. list(APPEND runtime_depends ${runtime_depend})
  419. endforeach()
  420. # Generate the output file, note the STAMP_OUTPUT_FILE need to match with the one defined in LYWrappers.cmake
  421. set(STAMP_OUTPUT_FILE ${CMAKE_BINARY_DIR}/runtime_dependencies/$<CONFIG>/${target}.stamp)
  422. unset(target_file_dir)
  423. unset(target_bundle_dir)
  424. unset(target_bundle_content_dir)
  425. # UTILITY type targets does not have a target file, so the CMAKE_RUNTIME_OUTPUT_DIRECTORY is used
  426. if (NOT target_type STREQUAL UTILITY)
  427. set(target_file_dir "$<TARGET_FILE_DIR:${target}>")
  428. set(target_file "$<TARGET_FILE:${target}>")
  429. # If the target is a bundle, configure the TARGET_BUNDLE_DIR
  430. # into the generated cmake file with runtime dependencies
  431. get_property(is_bundle TARGET ${target} PROPERTY MACOSX_BUNDLE)
  432. if(is_bundle)
  433. set(target_bundle_dir "$<TARGET_BUNDLE_DIR:${target}>")
  434. set(target_bundle_content_dir "$<TARGET_BUNDLE_CONTENT_DIR:${target}>")
  435. endif()
  436. else()
  437. set(target_file_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
  438. unset(target_file)
  439. endif()
  440. if(DEFINED ENV{USERPROFILE} AND EXISTS $ENV{USERPROFILE})
  441. set(PYTHON_ROOT_PATH "$ENV{USERPROFILE}/.o3de/Python") # Windows
  442. else()
  443. set(PYTHON_ROOT_PATH "$ENV{HOME}/.o3de/Python") # Unix
  444. endif()
  445. set(PYTHON_PACKAGES_ROOT_PATH "${PYTHON_ROOT_PATH}/packages")
  446. cmake_path(NORMAL_PATH PYTHON_PACKAGES_ROOT_PATH )
  447. set(LY_CURRENT_PYTHON_PACKAGE_PATH "${PYTHON_PACKAGES_ROOT_PATH}/${LY_PYTHON_PACKAGE_NAME}")
  448. cmake_path(NORMAL_PATH LY_CURRENT_PYTHON_PACKAGE_PATH )
  449. ly_file_read(${LY_RUNTIME_DEPENDENCIES_TEMPLATE} template_file)
  450. string(CONFIGURE "${LY_COPY_COMMANDS}" LY_COPY_COMMANDS @ONLY)
  451. string(CONFIGURE "${template_file}" configured_template_file @ONLY)
  452. file(GENERATE
  453. OUTPUT ${CMAKE_BINARY_DIR}/runtime_dependencies/$<CONFIG>/${target}.cmake
  454. CONTENT "${configured_template_file}"
  455. )
  456. # set the property that is consumed from the custom command generated in LyWrappers.cmake
  457. set_target_properties(${target} PROPERTIES RUNTIME_DEPENDENCIES_DEPENDS "${runtime_depends}")
  458. endforeach()
  459. endfunction()