Files
o3de/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in
T
SJ 1f542838bb [Mac] Generate O3DE SDK app bundle that can be notarized and distributed (#4150)
* [Mac] Initial support for building with hardened runtime enabled and code signing the binaries and bundles generated by the CMake install process.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Move call to ly_post_install_step
2. Entitlements should only be added for executables
3. Change use of CMake exec_program to newer execute_process
4. Remove broken symlinks from embedded Python frameworks
5. Run post install code signing only if hardened runtime is enabled

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Remove unnecessary flag

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Remove unnecessary additional call to condesign python inside a bundle

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Move commonly used install functions for codesigning, copying files, and fixing frameworks to a utility script
2. Remove unnecessary wait in the Editor/AP launchers I added earlier.
3. Codesign 3rd party libraries for distribution.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Codesigning on 3rd party libs should only happen when hardened runtime is enabled.
2. Change the order of the if blocks in Editor's main_dummy.cpp. This was causing strange notarization issues because it wass too similar to AP's main executable.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Add new line to end of file

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Move architecture specification to PAL_mac cmake file. 2. Codesign failure should be fatal.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Address some PR feedback

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Remove unnecessary comment. Change if to use IN_LIST.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* HOME may not always be defined. Adding alternate POSIX way of determining HOME.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Checking in partial work to get O3DE SDK built as an app bundle. Has a bunch of debug code that needs to be cleaned up.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Remove this and add it back later with fixed casing.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Adding file back with fixed case

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Add entitlements sparingly(only when necessary)
2. Convert entitlements to plist files which we can directly pass to codesign
3. Install python site-packages in the o3de_sdk launcher and then launch the project manger.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Move hardened runtime check to codesigning functions only. This way, non-hardened runtime install is identical to the former except for codesign. Makes it easy for QA to test internally.
2. Move cmake min version for install to the pre-install steps.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Remove the dummy launchers for AssetProcessor and Editor
2. Add loader_path to the rpaths of binaries outside an app bundle so that the dynamic loader can load their dependencies if any.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Remove file named main_dummy.cpp

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Add O3DE SDK launcher

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Add missing runtime dependencies to gems

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Update the path to binaries when codesigning to the correct one.
2. Remove some debug messages.
3. Move installed binary path setreg generation to the target install function. This way, we get the correct path to the bundle accounting for different configs and subdirectories.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Add explanatory comments.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. ly_install_add_install_path_setreg cannot be called during install target because the runtime dependencies are already processed by then.
2. The SDK launcher now uses the ProjectManager's bundle setreg to find the path to the installed binaries

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Update path to install relative binaries after merge from dev

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Only one config of the SDK launcher needs to be installed. Preinstall steps should not be run per config, but only once.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Install python dependencies using the get_python.sh script.
2. Replace any reference to hard-coded package name/version numbers with variables.
3. Add one more missing runtime dependency.
4. Misc. PR feedback.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Remove the need for setreg files in all tool bundle. Project binary path can be used instead.
2. Move O3DE_SDK_Launcher to Code/Tools/BundleLauncher
3. Add ly_install_run_script() function for install(SCRIPT) functionality.
4. Address some other PR feedback.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Add source permission when installing O3DE_SDK executable.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Rename setreg file to add specialization tag.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Remove LY_BUILD_PERMUTATION that's not needed

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Add BinariesInstallPath.setreg to all our bundles like before. This is now only added during the install process though.
2. Fix path in Install_common.cmake

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Fix comment

Signed-off-by: amzn-sj <srikkant@amazon.com>
2021-09-20 11:13:47 -05:00

225 lines
10 KiB
CMake

#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var)
# Qt frameworks could resolve the binary to eg qt/lib/QtCore.framework/Headers/QtCore instead of qt/lib/QtCore.framework/Versions/5/QtCore
# This is because GetPrerequisites.cmake gp_resolve_item function searches for the first file that matches the "frameworks name"
if(${${resolved_var}} AND ${item} MATCHES "/(Qt[^\\.]+\\.framework)/(.*)")
set(qt_framework ${CMAKE_MATCH_1})
set(qt_framework_subpath ${CMAKE_MATCH_2})
string(REGEX REPLACE "(.*)/(Qt[^\\.]+\\.framework)/(.*)" "\\1/\\2/${qt_framework_subpath}" new_resolved_item "${${resolved_item_var}}")
set(${resolved_item_var} ${new_resolved_item} PARENT_SCOPE)
endif()
endfunction()
include(BundleUtilities)
cmake_policy(SET CMP0012 NEW) # new policy for the if that evaluates a boolean out of the LY_BUILD_FIXUP_BUNDLE expansion
cmake_policy(SET CMP0009 NEW) # do not traverse symlinks on GLOB_RECURSE
set(anything_new FALSE)
set(plugin_libs)
set(plugin_dirs)
set(depends_on_python FALSE)
find_program(LY_INSTALL_NAME_TOOL install_name_tool)
if (NOT LY_INSTALL_NAME_TOOL)
message(FATAL_ERROR "Unable to locate 'install_name_tool'")
endif()
function(ly_copy source_file target_directory)
get_filename_component(target_filename "${source_file}" NAME)
# If target_directory is a bundle
if("${target_directory}" MATCHES "\\.app/Contents/MacOS")
set(target_is_bundle TRUE)
if("${source_file}" MATCHES "\\.[Ff]ramework[^\\.]")
if(NOT @LY_BUILD_FIXUP_BUNDLE@)
return()
endif()
# fixup origin to copy the whole Framework folder and change destination to Contents/Frameworks
string(REGEX REPLACE "(.*\\.[Ff]ramework).*" "\\1" source_file "${source_file}")
get_filename_component(source_file_folder "${source_file}" DIRECTORY)
# Python.framework produces a bug in BundleUtilities so it needs manual handling
# https://gitlab.kitware.com/cmake/cmake/-/issues/20165
if("${source_file}" MATCHES "Python.framework")
# fixup the destination so it ends up in Contents/Frameworks
string(REGEX REPLACE "(.*\\.app/Contents)/MacOS" "\\1/Frameworks" target_directory "${target_directory}")
set(local_plugin_dirs ${plugin_dirs})
list(APPEND local_plugin_dirs "${target_directory}/Python.framework")
set(target_filename Python.framework)
set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE)
set(depends_on_python TRUE PARENT_SCOPE)
else()
set(local_plugin_dirs ${plugin_dirs})
list(APPEND local_plugin_dirs "${source_file_folder}")
set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE)
return()
endif()
elseif("${source_file}" MATCHES "qt/plugins")
if(NOT @LY_BUILD_FIXUP_BUNDLE@)
return()
endif()
# fixup the destination so it ends up in Contents/PlugIns
string(REGEX REPLACE "(.*\\.app/Contents)/MacOS" "\\1/PlugIns" target_directory "${target_directory}")
set(local_plugin_dirs ${plugin_dirs})
list(APPEND local_plugin_dirs "${target_directory}")
set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE)
set(local_plugin_libs ${plugin_libs})
list(APPEND local_plugin_libs "${target_directory}/${target_filename}")
set(plugin_libs ${local_plugin_libs} PARENT_SCOPE)
elseif("${source_file}" MATCHES "qt/translations")
return() # skip, is this used?
elseif("${source_file}" MATCHES ".dylib")
set(local_plugin_dirs ${plugin_dirs})
list(APPEND local_plugin_dirs "${target_directory}")
set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE)
endif()
else()
# target is not a bundle
set(target_is_bundle FALSE)
if("${source_file}" MATCHES "\\.[Ff]ramework[^\\.]")
# fixup origin to copy the whole Framework folder
string(REGEX REPLACE "(.*\\.[Ff]ramework).*" "\\1" source_file "${source_file}")
get_filename_component(target_filename "${source_file}" NAME)
if("${source_file}" MATCHES "Python.framework")
set(depends_on_python TRUE PARENT_SCOPE)
endif()
endif()
endif()
cmake_path(COMPARE "${source_file}" EQUAL "${target_directory}/${target_filename}" same_location)
if(NOT ${same_location})
if(NOT EXISTS "${target_directory}")
file(MAKE_DIRECTORY "${target_directory}")
endif()
if(NOT EXISTS "${target_directory}/${target_filename}" OR "${source_file}" IS_NEWER_THAN "${target_directory}/${target_filename}")
message(STATUS "Copying \"${source_file}\" to \"${target_directory}\"...")
if(NOT target_is_bundle)
# if it is a bundle, there is no contention about the files in the destination, each bundle target will copy everything
# we dont want these files to invalidate the bundle and cause a new signature
file(LOCK ${target_directory}/${target_filename}.lock GUARD FUNCTION TIMEOUT 300)
endif()
file(COPY "${source_file}" DESTINATION "${target_directory}" FILE_PERMISSIONS @LY_COPY_PERMISSIONS@ FOLLOW_SYMLINK_CHAIN)
file(TOUCH_NOCREATE ${target_directory}/${target_filename})
set(anything_new TRUE PARENT_SCOPE)
endif()
endif()
endfunction()
@LY_COPY_COMMANDS@
if(NOT @LY_BUILD_FIXUP_BUNDLE@)
return()
endif()
if(@target_file_dir@ MATCHES ".app/Contents/MacOS")
string(REGEX REPLACE "(.*\\.app)/Contents/MacOS.*" "\\1" bundle_path "@target_file_dir@")
set(fixup_timestamp_file "${bundle_path}.fixup.stamp")
if(NOT anything_new)
if(NOT EXISTS "${fixup_timestamp_file}" OR "${bundle_path}" IS_NEWER_THAN "${fixup_timestamp_file}")
set(anything_new TRUE)
endif()
endif()
if(anything_new)
unset(fixup_bundle_ignore)
# LYN-4505: Patch dxc, is configured in the wrong folder in 3p
if(EXISTS ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
list(APPEND fixup_bundle_ignore dxc-3.7)
endif()
# LYN-4502: Patch python bundle, it contains some windows executables, some files that fixup_bundle doesnt like and has
# other issues that produce signature problems
if(depends_on_python)
message(STATUS "Fixing ${bundle_path}/Contents/Frameworks/Python.framework...")
list(APPEND fixup_bundle_ignore Python python3.7m python3.7)
file(REMOVE_RECURSE
${bundle_path}/Contents/Frameworks/Python.framework/Versions/Current
${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/Headers
${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/Python
${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/test
${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/scipy/io/tests
${bundle_path}/Contents/Frameworks/Python.framework/Python
${bundle_path}/Contents/Frameworks/Python.framework/Resources
${bundle_path}/Contents/Frameworks/Python.framework/Headers
)
file(GLOB_RECURSE exe_file_list "${bundle_path}/Contents/Frameworks/Python.framework/**/*.exe")
if(exe_file_list)
file(REMOVE_RECURSE ${exe_file_list})
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink include/python3.7m Headers
WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7
)
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink 3.7 Current
WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework/Versions/
)
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Python Python
WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework
)
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Headers Headers
WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework
)
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Resources Resources
WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework
)
file(CHMOD ${bundle_path}/Contents/Frameworks/Python.framework/Versions/Current/Python
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
endif()
list(REMOVE_DUPLICATES plugin_libs)
list(REMOVE_DUPLICATES plugin_dirs)
fixup_bundle("${bundle_path}" "${plugin_libs}" "${plugin_dirs}" IGNORE_ITEM ${fixup_bundle_ignore})
file(TOUCH "${bundle_path}")
file(TOUCH "${fixup_timestamp_file}")
# fixup bundle ends up removing the rpath of dxc (despite we exclude it)
if(EXISTS ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
execute_process(COMMAND ${LY_INSTALL_NAME_TOOL} -add_rpath @executable_path/../lib ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
endif()
# misplaced .DS_Store files can cause signing to fail
# Interrupted signatures can leave cstemp files behind that fail next signature
file(GLOB_RECURSE remove_file_list
"${bundle_path}/**/.DS_Store"
"${bundle_path/}**/*.cstemp"
)
if(remove_file_list)
file(REMOVE_RECURSE ${remove_file_list})
endif()
endif()
else() # Non-bundle case
if(depends_on_python)
# RPATH fix python
execute_process(COMMAND ${LY_INSTALL_NAME_TOOL} -change @rpath/Python @rpath/Python.framework/Versions/Current/Python @target_file@)
endif()
endif()