runtime_dependencies_mac.cmake.in 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var)
  9. # Qt frameworks could resolve the binary to eg qt/lib/QtCore.framework/Headers/QtCore instead of qt/lib/QtCore.framework/Versions/5/QtCore
  10. # This is because GetPrerequisites.cmake gp_resolve_item function searches for the first file that matches the "frameworks name"
  11. if(${${resolved_var}} AND ${item} MATCHES "/(Qt[^\\.]+\\.framework)/(.*)")
  12. set(qt_framework ${CMAKE_MATCH_1})
  13. set(qt_framework_subpath ${CMAKE_MATCH_2})
  14. string(REGEX REPLACE "(.*)/(Qt[^\\.]+\\.framework)/(.*)" "\\1/\\2/${qt_framework_subpath}" new_resolved_item "${${resolved_item_var}}")
  15. set(${resolved_item_var} ${new_resolved_item} PARENT_SCOPE)
  16. endif()
  17. endfunction()
  18. include(BundleUtilities)
  19. cmake_policy(SET CMP0012 NEW) # new policy for the if that evaluates a boolean out of the LY_BUILD_FIXUP_BUNDLE expansion
  20. cmake_policy(SET CMP0009 NEW) # do not traverse symlinks on GLOB_RECURSE
  21. set(anything_new FALSE)
  22. set(plugin_libs)
  23. set(plugin_dirs)
  24. set(depends_on_python FALSE)
  25. find_program(LY_INSTALL_NAME_TOOL install_name_tool)
  26. if (NOT LY_INSTALL_NAME_TOOL)
  27. message(FATAL_ERROR "Unable to locate 'install_name_tool'")
  28. endif()
  29. function(ly_copy source_file target_directory)
  30. get_filename_component(target_filename "${source_file}" NAME)
  31. # If target_directory is a bundle
  32. if("${target_directory}" MATCHES "\\.app/Contents/MacOS")
  33. set(target_is_bundle TRUE)
  34. if("${source_file}" MATCHES "\\.[Ff]ramework[^\\.]")
  35. if(NOT @LY_BUILD_FIXUP_BUNDLE@)
  36. return()
  37. endif()
  38. # fixup origin to copy the whole Framework folder and change destination to Contents/Frameworks
  39. string(REGEX REPLACE "(.*\\.[Ff]ramework).*" "\\1" source_file "${source_file}")
  40. get_filename_component(source_file_folder "${source_file}" DIRECTORY)
  41. # Python.framework produces a bug in BundleUtilities so it needs manual handling
  42. # https://gitlab.kitware.com/cmake/cmake/-/issues/20165
  43. if("${source_file}" MATCHES "Python.framework")
  44. # fixup the destination so it ends up in Contents/Frameworks
  45. string(REGEX REPLACE "(.*\\.app/Contents)/MacOS" "\\1/Frameworks" target_directory "${target_directory}")
  46. set(local_plugin_dirs ${plugin_dirs})
  47. list(APPEND local_plugin_dirs "${target_directory}/Python.framework")
  48. set(target_filename Python.framework)
  49. set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE)
  50. set(depends_on_python TRUE PARENT_SCOPE)
  51. else()
  52. set(local_plugin_dirs ${plugin_dirs})
  53. list(APPEND local_plugin_dirs "${source_file_folder}")
  54. set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE)
  55. return()
  56. endif()
  57. elseif("${source_file}" MATCHES "qt/plugins")
  58. if(NOT @LY_BUILD_FIXUP_BUNDLE@)
  59. return()
  60. endif()
  61. # fixup the destination so it ends up in Contents/PlugIns
  62. string(REGEX REPLACE "(.*\\.app/Contents)/MacOS" "\\1/PlugIns" target_directory "${target_directory}")
  63. set(local_plugin_dirs ${plugin_dirs})
  64. list(APPEND local_plugin_dirs "${target_directory}")
  65. set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE)
  66. set(local_plugin_libs ${plugin_libs})
  67. list(APPEND local_plugin_libs "${target_directory}/${target_filename}")
  68. set(plugin_libs ${local_plugin_libs} PARENT_SCOPE)
  69. elseif("${source_file}" MATCHES "qt/translations")
  70. return() # skip, is this used?
  71. elseif("${source_file}" MATCHES ".dylib")
  72. set(local_plugin_dirs ${plugin_dirs})
  73. list(APPEND local_plugin_dirs "${target_directory}")
  74. set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE)
  75. endif()
  76. else()
  77. # target is not a bundle
  78. set(target_is_bundle FALSE)
  79. if("${source_file}" MATCHES "\\.[Ff]ramework[^\\.]")
  80. # fixup origin to copy the whole Framework folder
  81. string(REGEX REPLACE "(.*\\.[Ff]ramework).*" "\\1" source_file "${source_file}")
  82. get_filename_component(target_filename "${source_file}" NAME)
  83. if("${source_file}" MATCHES "Python.framework")
  84. set(depends_on_python TRUE PARENT_SCOPE)
  85. endif()
  86. endif()
  87. endif()
  88. cmake_path(COMPARE "${source_file}" EQUAL "${target_directory}/${target_filename}" same_location)
  89. if(NOT ${same_location})
  90. if(NOT EXISTS "${target_directory}")
  91. file(MAKE_DIRECTORY "${target_directory}")
  92. endif()
  93. if(NOT EXISTS "${target_directory}/${target_filename}" OR "${source_file}" IS_NEWER_THAN "${target_directory}/${target_filename}")
  94. message(STATUS "Copying \"${source_file}\" to \"${target_directory}\"...")
  95. if(NOT target_is_bundle)
  96. # if it is a bundle, there is no contention about the files in the destination, each bundle target will copy everything
  97. # we dont want these files to invalidate the bundle and cause a new signature
  98. file(LOCK ${target_directory}/${target_filename}.lock GUARD FUNCTION TIMEOUT 300)
  99. endif()
  100. file(COPY "${source_file}" DESTINATION "${target_directory}" FILE_PERMISSIONS @LY_COPY_PERMISSIONS@ FOLLOW_SYMLINK_CHAIN)
  101. file(TOUCH_NOCREATE ${target_directory}/${target_filename})
  102. set(anything_new TRUE PARENT_SCOPE)
  103. endif()
  104. endif()
  105. endfunction()
  106. @LY_COPY_COMMANDS@
  107. if(NOT @LY_BUILD_FIXUP_BUNDLE@)
  108. return()
  109. endif()
  110. if(@target_file_dir@ MATCHES ".app/Contents/MacOS")
  111. string(REGEX REPLACE "(.*\\.app)/Contents/MacOS.*" "\\1" bundle_path "@target_file_dir@")
  112. set(fixup_timestamp_file "${bundle_path}.fixup.stamp")
  113. if(NOT anything_new)
  114. if(NOT EXISTS "${fixup_timestamp_file}" OR "${bundle_path}" IS_NEWER_THAN "${fixup_timestamp_file}")
  115. set(anything_new TRUE)
  116. endif()
  117. endif()
  118. if(anything_new)
  119. unset(fixup_bundle_ignore)
  120. # LYN-4505: Patch dxc, is configured in the wrong folder in 3p
  121. if(EXISTS ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
  122. list(APPEND fixup_bundle_ignore dxc-3.7)
  123. endif()
  124. # LYN-4502: Patch python bundle, it contains some windows executables, some files that fixup_bundle doesnt like and has
  125. # other issues that produce signature problems
  126. if(depends_on_python)
  127. message(STATUS "Fixing ${bundle_path}/Contents/Frameworks/Python.framework...")
  128. list(APPEND fixup_bundle_ignore Python python3.7m python3.7)
  129. file(REMOVE_RECURSE
  130. ${bundle_path}/Contents/Frameworks/Python.framework/Versions/Current
  131. ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/Headers
  132. ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/Python
  133. ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/test
  134. ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/scipy/io/tests
  135. ${bundle_path}/Contents/Frameworks/Python.framework/Python
  136. ${bundle_path}/Contents/Frameworks/Python.framework/Resources
  137. ${bundle_path}/Contents/Frameworks/Python.framework/Headers
  138. )
  139. file(GLOB_RECURSE exe_file_list "${bundle_path}/Contents/Frameworks/Python.framework/**/*.exe")
  140. if(exe_file_list)
  141. file(REMOVE_RECURSE ${exe_file_list})
  142. endif()
  143. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink include/python3.7m Headers
  144. WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7
  145. )
  146. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink 3.7 Current
  147. WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework/Versions/
  148. )
  149. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Python Python
  150. WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework
  151. )
  152. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Headers Headers
  153. WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework
  154. )
  155. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Resources Resources
  156. WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework
  157. )
  158. file(CHMOD ${bundle_path}/Contents/Frameworks/Python.framework/Versions/Current/Python
  159. PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
  160. )
  161. endif()
  162. list(REMOVE_DUPLICATES plugin_libs)
  163. list(REMOVE_DUPLICATES plugin_dirs)
  164. fixup_bundle("${bundle_path}" "${plugin_libs}" "${plugin_dirs}" IGNORE_ITEM ${fixup_bundle_ignore})
  165. file(TOUCH "${bundle_path}")
  166. file(TOUCH "${fixup_timestamp_file}")
  167. # fixup bundle ends up removing the rpath of dxc (despite we exclude it)
  168. if(EXISTS ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
  169. execute_process(COMMAND ${LY_INSTALL_NAME_TOOL} -add_rpath @executable_path/../lib ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
  170. endif()
  171. # misplaced .DS_Store files can cause signing to fail
  172. # Interrupted signatures can leave cstemp files behind that fail next signature
  173. file(GLOB_RECURSE remove_file_list
  174. "${bundle_path}/**/.DS_Store"
  175. "${bundle_path/}**/*.cstemp"
  176. )
  177. if(remove_file_list)
  178. file(REMOVE_RECURSE ${remove_file_list})
  179. endif()
  180. endif()
  181. else() # Non-bundle case
  182. if(depends_on_python)
  183. # RPATH fix python
  184. execute_process(COMMAND ${LY_INSTALL_NAME_TOOL} -change @rpath/Python @rpath/Python.framework/Versions/Current/Python @target_file@)
  185. endif()
  186. endif()