Packaging.cmake 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. if(NOT PAL_TRAIT_BUILD_CPACK_SUPPORTED)
  9. return()
  10. endif()
  11. # public facing options will be used for conversion into cpack specific ones below.
  12. set(LY_INSTALLER_LICENSE_URL "" CACHE STRING "Optionally embed a link to the license instead of raw text")
  13. set(LY_INSTALLER_AUTO_GEN_TAG OFF CACHE BOOL
  14. "Automatically generate a build tag based on the git repo and append it to the download/upload URLs. \
  15. Format: <branch>/<commit_date>-<commit_hash>"
  16. )
  17. set(LY_INSTALLER_DOWNLOAD_URL "" CACHE STRING
  18. "Base URL embedded into the installer to download additional artifacts, the host target and version \
  19. number will automatically appended as '<version>/<host>'. If LY_INSTALLER_AUTO_GEN_TAG is set, the \
  20. full URL format will be: <base_url>/<build_tag>/<host>"
  21. )
  22. set(LY_INSTALLER_UPLOAD_URL "" CACHE STRING
  23. "Base URL used to upload the installer artifacts after generation, the host target and version number \
  24. will automatically appended as '<version>/<host>'. If LY_INSTALLER_AUTO_GEN_TAG is set, the full URL \
  25. format will be: <base_url>/<build_tag>/<host>. Can also be set via LY_INSTALLER_UPLOAD_URL environment \
  26. variable. Currently only accepts S3 URLs e.g. s3://<bucket>/<prefix>"
  27. )
  28. set(LY_INSTALLER_AWS_PROFILE "" CACHE STRING
  29. "AWS CLI profile for uploading artifacts. Can also be set via LY_INSTALLER_AWS_PROFILE environment variable."
  30. )
  31. set(CPACK_DESIRED_CMAKE_VERSION 3.20.2)
  32. # set all common cpack variable overrides first so they can be accessible via configure_file
  33. # when the platform specific settings are applied below. additionally, any variable with
  34. # the "CPACK_" prefix will automatically be cached for use in any phase of cpack namely
  35. # pre/post build
  36. set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
  37. set(CPACK_PACKAGE_FULL_NAME "Open3D Engine")
  38. set(CPACK_PACKAGE_VENDOR "O3DE Binary Project a Series of LF Projects, LLC")
  39. set(CPACK_PACKAGE_VERSION "${LY_VERSION_STRING}")
  40. set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Installation Tool")
  41. string(TOLOWER "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}" CPACK_PACKAGE_FILE_NAME)
  42. set(DEFAULT_LICENSE_NAME "Apache-2.0")
  43. set(DEFAULT_LICENSE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
  44. set(CPACK_RESOURCE_FILE_LICENSE ${DEFAULT_LICENSE_FILE})
  45. set(CPACK_LICENSE_URL ${LY_INSTALLER_LICENSE_URL})
  46. set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}/${CPACK_PACKAGE_VERSION}")
  47. # neither of the SOURCE_DIR variables equate to anything during execution of pre/post build scripts
  48. set(CPACK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
  49. set(CPACK_BINARY_DIR ${CMAKE_BINARY_DIR}/_CPack) # to match other CPack out dirs
  50. # this config file allows the dynamic setting of cpack variables at cpack-time instead of cmake configure
  51. set(CPACK_PROJECT_CONFIG_FILE ${CPACK_SOURCE_DIR}/PackagingConfig.cmake)
  52. set(CPACK_AUTO_GEN_TAG ${LY_INSTALLER_AUTO_GEN_TAG})
  53. # attempt to apply platform specific settings
  54. ly_get_absolute_pal_filename(pal_dir ${CPACK_SOURCE_DIR}/Platform/${PAL_HOST_PLATFORM_NAME})
  55. include(${pal_dir}/Packaging_${PAL_HOST_PLATFORM_NAME_LOWERCASE}.cmake)
  56. # if we get here and the generator hasn't been set, then a non fatal error occurred disabling packaging support
  57. if(NOT CPACK_GENERATOR)
  58. return()
  59. endif()
  60. if(${CPACK_DESIRED_CMAKE_VERSION} VERSION_LESS ${CMAKE_MINIMUM_REQUIRED_VERSION})
  61. message(FATAL_ERROR
  62. "The desired version of CMake to be included in the package is "
  63. "below the minimum required version of CMake to run")
  64. endif()
  65. # pull down the desired copy of CMake so it can be included in the package
  66. if(NOT (CPACK_CMAKE_PACKAGE_FILE AND CPACK_CMAKE_PACKAGE_HASH))
  67. message(FATAL_ERROR
  68. "Packaging is missing one or more following properties required to include CMake: "
  69. " CPACK_CMAKE_PACKAGE_FILE, CPACK_CMAKE_PACKAGE_HASH")
  70. endif()
  71. set(_cmake_package_dest ${CPACK_BINARY_DIR}/${CPACK_CMAKE_PACKAGE_FILE})
  72. if(EXISTS ${_cmake_package_dest})
  73. file(SHA256 ${_cmake_package_dest} hash_of_downloaded_file)
  74. if (NOT "${hash_of_downloaded_file}" STREQUAL "${CPACK_CMAKE_PACKAGE_HASH}")
  75. message(STATUS "CMake ${CPACK_DESIRED_CMAKE_VERSION} found at ${_cmake_package_dest} but expected hash missmatches, re-downloading...")
  76. file(REMOVE ${_cmake_package_dest})
  77. else()
  78. message(STATUS "CMake ${CPACK_DESIRED_CMAKE_VERSION} found")
  79. endif()
  80. endif()
  81. if(NOT EXISTS ${_cmake_package_dest})
  82. # download it
  83. string(REPLACE "." ";" _version_componets "${CPACK_DESIRED_CMAKE_VERSION}")
  84. list(GET _version_componets 0 _major_version)
  85. list(GET _version_componets 1 _minor_version)
  86. set(_url_version_tag "v${_major_version}.${_minor_version}")
  87. set(_package_url "https://cmake.org/files/${_url_version_tag}/${CPACK_CMAKE_PACKAGE_FILE}")
  88. message(STATUS "Downloading CMake ${CPACK_DESIRED_CMAKE_VERSION} for packaging...")
  89. download_file(
  90. URL ${_package_url}
  91. TARGET_FILE ${_cmake_package_dest}
  92. EXPECTED_HASH ${CPACK_CMAKE_PACKAGE_HASH}
  93. RESULTS _results
  94. )
  95. list(GET _results 0 _status_code)
  96. if (${_status_code} EQUAL 0 AND EXISTS ${_cmake_package_dest})
  97. message(STATUS "CMake ${CPACK_DESIRED_CMAKE_VERSION} found")
  98. else()
  99. file(REMOVE ${_cmake_package_dest})
  100. list(REMOVE_AT _results 0)
  101. set(_error_message "An error occurred, code ${_status_code}. URL ${_package_url} - ${_results}")
  102. if(${_status_code} EQUAL 1)
  103. string(APPEND _error_message
  104. " Please double check the CPACK_CMAKE_PACKAGE_FILE and "
  105. "CPACK_CMAKE_PACKAGE_HASH properties before trying again.")
  106. endif()
  107. message(FATAL_ERROR ${_error_message})
  108. endif()
  109. endif()
  110. install(CODE "if(NOT LY_CORE_COMPONENT_ALREADY_INCLUDED)")
  111. install(FILES ${_cmake_package_dest}
  112. DESTINATION ./Tools/Redistributables/CMake
  113. COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}
  114. )
  115. install(CODE "endif()")
  116. # the version string and git tags are intended to be synchronized so it should be safe to use that instead
  117. # of directly calling into git which could get messy in certain scenarios
  118. if(${CPACK_PACKAGE_VERSION} VERSION_GREATER "0.0.0.0")
  119. set(_3rd_party_license_filename NOTICES.txt)
  120. set(_3rd_party_license_url "https://raw.githubusercontent.com/o3de/3p-package-source/${CPACK_PACKAGE_VERSION}/${_3rd_party_license_filename}")
  121. set(_3rd_party_license_dest ${CPACK_BINARY_DIR}/${_3rd_party_license_filename})
  122. # use the plain file downloader as we don't have the file hash available and using a dummy will
  123. # delete the file once it fails hash verification
  124. file(DOWNLOAD
  125. ${_3rd_party_license_url}
  126. ${_3rd_party_license_dest}
  127. STATUS _status
  128. TLS_VERIFY ON
  129. )
  130. list(POP_FRONT _status _status_code)
  131. if (${_status_code} EQUAL 0 AND EXISTS ${_3rd_party_license_dest})
  132. install(CODE "if(NOT LY_CORE_COMPONENT_ALREADY_INCLUDED)")
  133. install(FILES ${_3rd_party_license_dest}
  134. DESTINATION .
  135. COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}
  136. )
  137. install(CODE "endif()")
  138. else()
  139. file(REMOVE ${_3rd_party_license_dest})
  140. message(FATAL_ERROR "Failed to acquire the 3rd Party license manifest file at ${_3rd_party_license_url}. Error: ${_status}")
  141. endif()
  142. endif()
  143. # checks for and removes trailing slash
  144. function(strip_trailing_slash in_url out_url)
  145. string(LENGTH ${in_url} _url_length)
  146. MATH(EXPR _url_length "${_url_length}-1")
  147. string(SUBSTRING ${in_url} 0 ${_url_length} _clean_url)
  148. if("${in_url}" STREQUAL "${_clean_url}/")
  149. set(${out_url} ${_clean_url} PARENT_SCOPE)
  150. else()
  151. set(${out_url} ${in_url} PARENT_SCOPE)
  152. endif()
  153. endfunction()
  154. if(NOT LY_INSTALLER_UPLOAD_URL AND DEFINED ENV{LY_INSTALLER_UPLOAD_URL})
  155. set(LY_INSTALLER_UPLOAD_URL $ENV{LY_INSTALLER_UPLOAD_URL})
  156. endif()
  157. if(LY_INSTALLER_UPLOAD_URL)
  158. ly_is_s3_url(${LY_INSTALLER_UPLOAD_URL} _is_s3_bucket)
  159. if(NOT _is_s3_bucket)
  160. message(FATAL_ERROR "Only S3 installer uploading is supported at this time")
  161. endif()
  162. if (LY_INSTALLER_AWS_PROFILE)
  163. set(CPACK_AWS_PROFILE ${LY_INSTALLER_AWS_PROFILE})
  164. elseif (DEFINED ENV{LY_INSTALLER_AWS_PROFILE})
  165. set(CPACK_AWS_PROFILE $ENV{LY_INSTALLER_AWS_PROFILE})
  166. endif()
  167. strip_trailing_slash(${LY_INSTALLER_UPLOAD_URL} LY_INSTALLER_UPLOAD_URL)
  168. set(CPACK_UPLOAD_URL ${LY_INSTALLER_UPLOAD_URL})
  169. endif()
  170. # IMPORTANT: required to be included AFTER setting all property overrides
  171. include(CPack REQUIRED)
  172. # configure ALL components here
  173. file(APPEND "${CPACK_OUTPUT_CONFIG_FILE}" "
  174. set(CPACK_COMPONENTS_ALL ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME})
  175. set(CPACK_COMPONENT_${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}_DISPLAY_NAME \"${PROJECT_NAME}\")
  176. set(CPACK_COMPONENT_${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}_DESCRIPTION \"${PROJECT_NAME} Headers, scripts and common files\")
  177. set(CPACK_COMPONENT_${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}_REQUIRED TRUE)
  178. set(CPACK_COMPONENT_${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}_DISABLED FALSE)
  179. include(CPackComponents.cmake)
  180. ")
  181. # Generate a file (CPackComponents.config) that we will include that defines the components
  182. # for this build permutation. This way we can get components for other permutations being passed
  183. # through LY_INSTALL_EXTERNAL_BUILD_DIRS
  184. unset(cpack_components_contents)
  185. set(required "FALSE")
  186. set(disabled "FALSE")
  187. if(${LY_INSTALL_PERMUTATION_COMPONENT} STREQUAL DEFAULT)
  188. set(required "TRUE")
  189. else()
  190. set(disabled "TRUE")
  191. endif()
  192. string(APPEND cpack_components_contents "
  193. list(APPEND CPACK_COMPONENTS_ALL ${LY_INSTALL_PERMUTATION_COMPONENT})
  194. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_DISPLAY_NAME \"${PROJECT_NAME} (${LY_BUILD_PERMUTATION})\")
  195. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_DESCRIPTION \"${PROJECT_NAME} scripts and common files for ${LY_BUILD_PERMUTATION}\")
  196. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_DEPENDS ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME})
  197. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_REQUIRED ${required})
  198. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_DISABLED ${disabled})
  199. ")
  200. foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES)
  201. string(TOUPPER ${conf} UCONF)
  202. set(required "FALSE")
  203. set(disabled "FALSE")
  204. if(${conf} STREQUAL profile AND ${LY_INSTALL_PERMUTATION_COMPONENT} STREQUAL DEFAULT)
  205. set(required "TRUE")
  206. else()
  207. set(disabled "TRUE")
  208. endif()
  209. unset(permutation_description)
  210. if(${LY_INSTALL_PERMUTATION_COMPONENT} STREQUAL MONOLITHIC)
  211. set(permutation_description "monolithic ")
  212. endif()
  213. # Inject a check to not declare components that have not been built. We are using AzCore since that is a
  214. # common target that will always be build, in every permutation and configuration
  215. string(APPEND cpack_components_contents "
  216. if(EXISTS \"${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${conf}/${CMAKE_STATIC_LIBRARY_PREFIX}AzCore${CMAKE_STATIC_LIBRARY_SUFFIX}\")
  217. list(APPEND CPACK_COMPONENTS_ALL ${LY_INSTALL_PERMUTATION_COMPONENT}_${UCONF})
  218. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_${UCONF}_DISPLAY_NAME \"${PROJECT_NAME} (${permutation_description}${conf})\")
  219. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_${UCONF}_DESCRIPTION \"${PROJECT_NAME} Libraries and Applications in ${permutation_description}${conf}\")
  220. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_${UCONF}_DEPENDS ${LY_INSTALL_PERMUTATION_COMPONENT}_${UCONF})
  221. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_${UCONF}_REQUIRED ${required})
  222. set(CPACK_COMPONENT_${LY_INSTALL_PERMUTATION_COMPONENT}_${UCONF}_DISABLED ${disabled})
  223. endif()
  224. ")
  225. endforeach()
  226. file(WRITE "${CMAKE_BINARY_DIR}/CPackComponents.cmake" ${cpack_components_contents})
  227. # Inject other build directories
  228. foreach(external_dir ${LY_INSTALL_EXTERNAL_BUILD_DIRS})
  229. file(APPEND "${CPACK_OUTPUT_CONFIG_FILE}"
  230. "include(${external_dir}/CPackComponents.cmake)\n"
  231. )
  232. endforeach()
  233. if(LY_INSTALLER_DOWNLOAD_URL)
  234. strip_trailing_slash(${LY_INSTALLER_DOWNLOAD_URL} LY_INSTALLER_DOWNLOAD_URL)
  235. # this will set the following variables: CPACK_DOWNLOAD_SITE, CPACK_DOWNLOAD_ALL, and CPACK_UPLOAD_DIRECTORY (local)
  236. cpack_configure_downloads(
  237. ${LY_INSTALLER_DOWNLOAD_URL}
  238. UPLOAD_DIRECTORY ${CMAKE_BINARY_DIR}/_CPack_Uploads # to match the _CPack_Packages directory
  239. ALL
  240. )
  241. endif()