# # All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or # its licensors. # # For complete copyright and license terms please see the LICENSE at the root of this # distribution (the "License"). All use of this software is governed by the License, # or, if provided, by the license below or the license accompanying this file. Do not # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # set(CMAKE_INSTALL_MESSAGE NEVER) # Simplify messages to reduce output noise ly_set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Core) cmake_path(RELATIVE_PATH CMAKE_RUNTIME_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE runtime_output_directory) cmake_path(RELATIVE_PATH CMAKE_LIBRARY_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE library_output_directory) # Anywhere CMAKE_INSTALL_PREFIX is used, it has to be escaped so it is baked into the cmake_install.cmake script instead # of baking the path. This is needed so `cmake --install --prefix ` works regardless of the CMAKE_INSTALL_PREFIX # used to generate the solution. # CMAKE_INSTALL_PREFIX is still used when building the INSTALL target set(install_output_folder "\${CMAKE_INSTALL_PREFIX}/${runtime_output_directory}/${PAL_PLATFORM_NAME}/$") function(ly_get_engine_relative_source_dir absolute_target_source_dir output_source_dir) # Get a relative target source directory to the LY root folder if possible # Otherwise use the final component name cmake_path(IS_PREFIX LY_ROOT_FOLDER ${absolute_target_source_dir} is_target_prefix_of_engine_root) if(is_target_prefix_of_engine_root) cmake_path(RELATIVE_PATH absolute_target_source_dir BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE relative_target_source_dir) else() # In this case the target source directory is outside of the engine root of the target source directory and concatenate the first # is used first 8 characters of the absolute path SHA256 hash to make a unique relative directory # that can be used to install the generated CMakeLists.txt # of a SHA256 hash string(SHA256 target_source_hash ${absolute_target_source_dir}) string(SUBSTRING ${target_source_hash} 0 8 target_source_hash) cmake_path(GET absolute_target_source_dir FILENAME target_source_dirname) cmake_path(SET relative_target_source_dir "${target_source_dirname}-${target_source_hash}") endif() set(${output_source_dir} ${relative_target_source_dir} PARENT_SCOPE) endfunction() #! ly_setup_target: Setup the data needed to re-create the cmake target commands for a single target function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_target_source_dir) # De-alias target name ly_de_alias_target(${ALIAS_TARGET_NAME} TARGET_NAME) # Get the target source directory relative to the LY root folder ly_get_engine_relative_source_dir(${absolute_target_source_dir} relative_target_source_dir) # get the component ID. if the property isn't set for the target, it will auto fallback to use CMAKE_INSTALL_DEFAULT_COMPONENT_NAME get_property(install_component TARGET ${TARGET_NAME} PROPERTY INSTALL_COMPONENT) # All include directories marked PUBLIC or INTERFACE will be installed. We dont use PUBLIC_HEADER because in order to do that # we need to set the PUBLIC_HEADER property of the target for all the headers we are exporting. After doing that, installing the # headers end up in one folder instead of duplicating the folder structure of the public/interface include directory. # Instead, we install them with install(DIRECTORY) set(include_location "include") get_target_property(include_directories ${TARGET_NAME} INTERFACE_INCLUDE_DIRECTORIES) if (include_directories) unset(public_headers) foreach(include_directory ${include_directories}) string(GENEX_STRIP ${include_directory} include_genex_expr) if(include_genex_expr STREQUAL include_directory) # only for cases where there are no generation expressions unset(current_public_headers) cmake_path(NORMAL_PATH include_directory) string(REGEX REPLACE "/$" "" include_directory "${include_directory}") cmake_path(IS_PREFIX LY_ROOT_FOLDER ${absolute_target_source_dir} NORMALIZE include_directory_child_of_o3de_root) if(NOT include_directory_child_of_o3de_root) message(FATAL_ERROR "Include directory of \"${include_directory}\" is outside of the O3DE root folder of \"${LY_ROOT_FOLDER}\". For the INSTALL step, the O3DE root folder must be a prefix of all include directories") endif() cmake_path(RELATIVE_PATH include_directory BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE rel_include_dir) cmake_path(APPEND include_location "${rel_include_dir}" ".." OUTPUT_VARIABLE destination_dir) cmake_path(NORMAL_PATH destination_dir) install(DIRECTORY ${include_directory} DESTINATION ${destination_dir} COMPONENT ${install_component} FILES_MATCHING PATTERN *.h PATTERN *.hpp PATTERN *.inl ) endif() endforeach() endif() # Get the output folders, archive is always the same, but runtime/library can be in subfolders defined per target cmake_path(RELATIVE_PATH CMAKE_ARCHIVE_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE archive_output_directory) get_target_property(target_runtime_output_directory ${TARGET_NAME} RUNTIME_OUTPUT_DIRECTORY) if(target_runtime_output_directory) cmake_path(RELATIVE_PATH target_runtime_output_directory BASE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_runtime_output_subdirectory) endif() get_target_property(target_library_output_directory ${TARGET_NAME} LIBRARY_OUTPUT_DIRECTORY) if(target_library_output_directory) cmake_path(RELATIVE_PATH target_library_output_directory BASE_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_library_output_subdirectory) endif() install( TARGETS ${TARGET_NAME} ARCHIVE DESTINATION ${archive_output_directory}/${PAL_PLATFORM_NAME}/$ COMPONENT ${install_component} LIBRARY DESTINATION ${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory} COMPONENT ${install_component} RUNTIME DESTINATION ${runtime_output_directory}/${PAL_PLATFORM_NAME}/$/${target_runtime_output_subdirectory} COMPONENT ${install_component} ) # CMakeLists.txt file string(REGEX MATCH "(.*)::(.*)$" match ${ALIAS_TARGET_NAME}) if(match) set(NAMESPACE_PLACEHOLDER "NAMESPACE ${CMAKE_MATCH_1}") set(NAME_PLACEHOLDER ${CMAKE_MATCH_2}) else() set(NAMESPACE_PLACEHOLDER "") set(NAME_PLACEHOLDER ${TARGET_NAME}) endif() set(TARGET_TYPE_PLACEHOLDER "") get_target_property(target_type ${NAME_PLACEHOLDER} TYPE) # Remove the _LIBRARY since we dont need to pass that to ly_add_targets string(REPLACE "_LIBRARY" "" TARGET_TYPE_PLACEHOLDER ${target_type}) # For HEADER_ONLY libs we end up generating "INTERFACE" libraries, need to specify HEADERONLY instead string(REPLACE "INTERFACE" "HEADERONLY" TARGET_TYPE_PLACEHOLDER ${TARGET_TYPE_PLACEHOLDER}) if(TARGET_TYPE_PLACEHOLDER STREQUAL "MODULE") get_target_property(gem_module ${NAME_PLACEHOLDER} GEM_MODULE) if(gem_module) set(TARGET_TYPE_PLACEHOLDER "GEM_MODULE") endif() endif() get_target_property(COMPILE_DEFINITIONS_PLACEHOLDER ${TARGET_NAME} INTERFACE_COMPILE_DEFINITIONS) if(COMPILE_DEFINITIONS_PLACEHOLDER) string(REPLACE ";" "\n" COMPILE_DEFINITIONS_PLACEHOLDER "${COMPILE_DEFINITIONS_PLACEHOLDER}") else() unset(COMPILE_DEFINITIONS_PLACEHOLDER) endif() # Includes need additional processing to add the install root if(include_directories) foreach(include ${include_directories}) string(GENEX_STRIP ${include} include_genex_expr) if(include_genex_expr STREQUAL include) # only for cases where there are no generation expressions cmake_path(RELATIVE_PATH include BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE target_include) cmake_path(NORMAL_PATH target_include) # Escape the LY_ROOT_FOLDER variable so that it isn't resolved during the install step string(APPEND INCLUDE_DIRECTORIES_PLACEHOLDER "\${LY_ROOT_FOLDER}/${target_include}\n") endif() endforeach() endif() get_target_property(RUNTIME_DEPENDENCIES_PLACEHOLDER ${TARGET_NAME} MANUALLY_ADDED_DEPENDENCIES) if(RUNTIME_DEPENDENCIES_PLACEHOLDER) # not found properties return the name of the variable with a "-NOTFOUND" at the end, here we set it to empty if not found string(REPLACE ";" "\n" RUNTIME_DEPENDENCIES_PLACEHOLDER "${RUNTIME_DEPENDENCIES_PLACEHOLDER}") else() unset(RUNTIME_DEPENDENCIES_PLACEHOLDER) endif() get_target_property(inteface_build_dependencies_props ${TARGET_NAME} INTERFACE_LINK_LIBRARIES) unset(INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER) if(inteface_build_dependencies_props) foreach(build_dependency ${inteface_build_dependencies_props}) # Skip wrapping produced when targets are not created in the same directory if(NOT ${build_dependency} MATCHES "^::@") list(APPEND INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER "${build_dependency}") endif() endforeach() endif() # We also need to pass the private link libraries since we will use that to generate the runtime dependencies get_target_property(private_build_dependencies_props ${TARGET_NAME} LINK_LIBRARIES) if(private_build_dependencies_props) foreach(build_dependency ${private_build_dependencies_props}) # Skip wrapping produced when targets are not created in the same directory if(NOT ${build_dependency} MATCHES "^::@") list(APPEND INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER "${build_dependency}") endif() endforeach() endif() list(REMOVE_DUPLICATES INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER) string(REPLACE ";" "\n" INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER "${INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER}") # Config file set(target_file_contents "# Generated by O3DE install\n\n") if(NOT target_type STREQUAL INTERFACE_LIBRARY) unset(target_location) set(runtime_types EXECUTABLE APPLICATION) if(target_type IN_LIST runtime_types) set(target_location "\${LY_ROOT_FOLDER}/${runtime_output_directory}/${PAL_PLATFORM_NAME}/$/${target_runtime_output_subdirectory}/$") elseif(target_type STREQUAL MODULE_LIBRARY) set(target_location "\${LY_ROOT_FOLDER}/${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory}/$") elseif(target_type STREQUAL SHARED_LIBRARY) string(APPEND target_file_contents "set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY IMPORTED_IMPLIB $<$$:\"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\"$ ) ") string(APPEND target_file_contents "set_property(TARGET ${TARGET_NAME} PROPERTY IMPORTED_IMPLIB_$> \"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\" ) ") set(target_location "\${LY_ROOT_FOLDER}/${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory}/$") else() # STATIC_LIBRARY, OBJECT_LIBRARY, INTERFACE_LIBRARY set(target_location "\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$") endif() if(target_location) string(APPEND target_file_contents "set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY IMPORTED_LOCATION $<$$:${target_location}$ ) set_property(TARGET ${TARGET_NAME} PROPERTY IMPORTED_LOCATION_$> ${target_location} ) ") endif() endif() set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}) file(GENERATE OUTPUT "${target_install_source_dir}/${NAME_PLACEHOLDER}_$.cmake" CONTENT "${target_file_contents}") install(FILES "${target_install_source_dir}/${NAME_PLACEHOLDER}_$.cmake" DESTINATION ${relative_target_source_dir} COMPONENT ${install_component} ) # Since a CMakeLists.txt could contain multiple targets, we generate it in a folder per target file(READ ${LY_ROOT_FOLDER}/cmake/install/InstalledTarget.in target_cmakelists_template) string(CONFIGURE ${target_cmakelists_template} output_cmakelists_data @ONLY) set(${OUTPUT_CONFIGURED_TARGET} ${output_cmakelists_data} PARENT_SCOPE) endfunction() #! ly_setup_subdirectories: setups all targets on a per directory basis function(ly_setup_subdirectories) get_property(all_subdirectories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) foreach(target_subdirectory IN LISTS all_subdirectories) ly_setup_subdirectory(${target_subdirectory}) endforeach() endfunction() #! ly_setup_subdirectory: setup all targets in the subdirectory function(ly_setup_subdirectory absolute_target_source_dir) # Get the target source directory relative to the LY roo folder ly_get_engine_relative_source_dir(${absolute_target_source_dir} relative_target_source_dir) # The builtin BUILDSYSTEM_TARGETS property isn't being used here as that returns the de-alised # TARGET and we need the alias namespace for recreating the CMakeLists.txt in the install layout get_property(ALIAS_TARGETS_NAME DIRECTORY ${absolute_target_source_dir} PROPERTY LY_DIRECTORY_TARGETS) foreach(ALIAS_TARGET_NAME IN LISTS ALIAS_TARGETS_NAME) ly_setup_target(configured_target ${ALIAS_TARGET_NAME} ${absolute_target_source_dir}) string(APPEND all_configured_targets "${configured_target}") endforeach() # Replicate the ly_create_alias() calls based on the SOURCE_DIR for each target that generates an installed CMakeLists.txt string(JOIN "\n" create_alias_template "if(NOT TARGET @ALIAS_NAME@)" " ly_create_alias(NAME @ALIAS_NAME@ NAMESPACE @ALIAS_NAMESPACE@ TARGETS @ALIAS_TARGETS@)" "endif()" "" ) get_property(create_alias_commands_arg_list DIRECTORY ${absolute_target_source_dir} PROPERTY LY_CREATE_ALIAS_ARGUMENTS) foreach(create_alias_single_command_arg_list ${create_alias_commands_arg_list}) # Split the ly_create_alias arguments back out based on commas string(REPLACE "," ";" create_alias_single_command_arg_list "${create_alias_single_command_arg_list}") list(POP_FRONT create_alias_single_command_arg_list ALIAS_NAME) list(POP_FRONT create_alias_single_command_arg_list ALIAS_NAMESPACE) # The rest of the list are the target dependencies set(ALIAS_TARGETS ${create_alias_single_command_arg_list}) string(CONFIGURE "${create_alias_template}" create_alias_command @ONLY) string(APPEND CREATE_ALIASES_PLACEHOLDER ${create_alias_command}) endforeach() # Reproduce the ly_enable_gems() calls made in the the SOURCE_DIR for this target into the CMakeLists.txt that # is about to be generated string(JOIN "\n" enable_gems_template " ly_enable_gems(@enable_gem_PROJECT_NAME@ @enable_gem_GEM@ @enable_gem_GEM_FILE@ @enable_gem_VARIANTS@ @enable_gem_TARGETS@)" "endif()" "" ) get_property(enable_gems_commands_arg_list DIRECTORY ${absolute_target_source_dir} PROPERTY LY_ENABLE_GEMS_ARGUMENTS) foreach(enable_gems_single_command_arg_list ${enable_gems_commands_arg_list}) # Split the ly_enable_gems arguments back out based on commas string(REPLACE "," ";" ly_enable_gems_single_command_arg_list "${enable_gems_single_command_arg_list}") list(POP_FRONT enable_gems_single_command_arg_list enable_gem_PROJECT_NAME) list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM) list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM_FILE) list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM) list(POP_FRONT enable_gems_single_command_arg_list enable_gem_VARIANTS) list(POP_FRONT enable_gems_single_command_arg_list enable_gem_TARGETS) foreach(enable_gem_arg_kw IN ITEMS PROJECT_NAME GEM GEM_FILE GEM VARIANTS TARGETS) list(POP_FRONT enable_gems_single_command_arg_list enable_gem_${enable_gem_arg_kw}) if(enable_gem_${enable_gem_arg_kw}) # if the argument exist append to argument keyword to the front string(PREPEND enable_gem_${enable_gem_arg_kw} "${enable_gem_arg_kw} ") endif() endforeach() string(CONFIGURE "${enable_gems_template}" enable_gems_command @ONLY) string(APPEND ENABLE_GEMS_PLACEHOLDER ${enable_gems_command}) endforeach() file(READ ${LY_ROOT_FOLDER}/cmake/install/Copyright.in cmake_copyright_comment) # Initialize the target install source directory to path underneath the current binary directory set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}) # Write out all the aggregated ly_add_target function calls and the final ly_create_alias() calls to the target CMakeLists.txt file(WRITE ${target_install_source_dir}/CMakeLists.txt "${cmake_copyright_comment}" "${all_configured_targets}" "\n" "${CREATE_ALIASES_PLACEHOLDER}" "${ENABLE_GEMS_PLACEHOLDER}" ) # get the component ID. if the property isn't set for the directory, it will auto fallback to use CMAKE_INSTALL_DEFAULT_COMPONENT_NAME get_property(install_component DIRECTORY ${absolute_target_source_dir} PROPERTY INSTALL_COMPONENT) install(FILES "${target_install_source_dir}/CMakeLists.txt" DESTINATION ${relative_target_source_dir} COMPONENT ${install_component} ) endfunction() #! ly_setup_o3de_install: orchestrates the installation of the different parts. This is the entry point from the root CMakeLists.txt function(ly_setup_o3de_install) ly_setup_subdirectories() ly_setup_cmake_install() ly_setup_target_generator() ly_setup_runtime_dependencies() ly_setup_others() endfunction() #! ly_setup_cmake_install: install the "cmake" folder function(ly_setup_cmake_install) install(DIRECTORY "${LY_ROOT_FOLDER}/cmake" DESTINATION . PATTERN "__pycache__" EXCLUDE REGEX "Findo3de.cmake" EXCLUDE REGEX "Platform\/.*\/BuiltInPackages_.*\.cmake" EXCLUDE ) # Transform the LY_EXTERNAL_SUBDIRS list into a json array set(indent " ") foreach(external_subdir ${LY_EXTERNAL_SUBDIRS}) cmake_path(RELATIVE_PATH external_subdir BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE engine_rel_external_subdir) list(APPEND relative_external_subdirs "\"${engine_rel_external_subdir}\"") endforeach() list(JOIN relative_external_subdirs ",\n${indent}" LY_INSTALL_EXTERNAL_SUBDIRS) # Read the "templates" key from the source engine.json o3de_read_json_array(engine_templates ${LY_ROOT_FOLDER}/engine.json "templates") foreach(template_path ${engine_templates}) list(APPEND relative_templates "\"${template_path}\"") endforeach() list(JOIN relative_templates ",\n${indent}" LY_INSTALL_TEMPLATES) configure_file(${LY_ROOT_FOLDER}/cmake/install/engine.json.in ${CMAKE_CURRENT_BINARY_DIR}/cmake/engine.json @ONLY) install( FILES "${LY_ROOT_FOLDER}/CMakeLists.txt" "${CMAKE_CURRENT_BINARY_DIR}/cmake/engine.json" DESTINATION . ) # Collect all Find files that were added with ly_add_external_target_path unset(additional_find_files) get_property(additional_module_paths GLOBAL PROPERTY LY_ADDITIONAL_MODULE_PATH) foreach(additional_module_path ${additional_module_paths}) unset(find_files) file(GLOB find_files "${additional_module_path}/Find*.cmake") list(APPEND additional_find_files "${find_files}") endforeach() install(FILES ${additional_find_files} DESTINATION cmake/3rdParty ) # Findo3de.cmake file: we generate a different Findo3de.camke file than the one we have in cmake. This one is going to expose all # targets that are pre-built unset(FIND_PACKAGES_PLACEHOLDER) # Add to the FIND_PACKAGES_PLACEHOLDER all directories in which ly_add_target were called in get_property(all_subdirectories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) foreach(target_subdirectory IN LISTS all_subdirectories) cmake_path(RELATIVE_PATH target_subdirectory BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE relative_target_subdirectory) string(APPEND FIND_PACKAGES_PLACEHOLDER " add_subdirectory(${relative_target_subdirectory})\n") endforeach() configure_file(${LY_ROOT_FOLDER}/cmake/install/Findo3de.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cmake/Findo3de.cmake @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/Findo3de.cmake" DESTINATION cmake ) # BuiltInPackage_.cmake: since associations could happen in any cmake file across the engine. We collect # all the associations in ly_associate_package and then generate them into BuiltInPackages_.cmake. This # will consolidate all associations in one file get_property(all_package_names GLOBAL PROPERTY LY_PACKAGE_NAMES) set(builtinpackages "# Generated by O3DE install\n\n") foreach(package_name IN LISTS all_package_names) get_property(package_hash GLOBAL PROPERTY LY_PACKAGE_HASH_${package_name}) get_property(targets GLOBAL PROPERTY LY_PACKAGE_TARGETS_${package_name}) string(APPEND builtinpackages "ly_associate_package(PACKAGE_NAME ${package_name} TARGETS ${targets} PACKAGE_HASH ${package_hash})\n") endforeach() set(pal_builtin_file ${CMAKE_CURRENT_BINARY_DIR}/cmake/3rdParty/Platform/${PAL_PLATFORM_NAME}/BuiltInPackages_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) file(GENERATE OUTPUT ${pal_builtin_file} CONTENT ${builtinpackages} ) install(FILES "${pal_builtin_file}" DESTINATION cmake/3rdParty/Platform/${PAL_PLATFORM_NAME} ) endfunction() #! ly_setup_runtime_dependencies: install runtime dependencies function(ly_setup_runtime_dependencies) # Common functions used by the bellow code install(CODE "function(ly_deploy_qt_install target_output) execute_process(COMMAND \"${WINDEPLOYQT_EXECUTABLE}\" --verbose 0 --no-compiler-runtime \"\${target_output}\" ERROR_VARIABLE deploy_error RESULT_VARIABLE deploy_result) if (NOT \${deploy_result} EQUAL 0) if(NOT deploy_error MATCHES \"does not seem to be a Qt executable\" ) message(SEND_ERROR \"Deploying qt for \${target_output} returned \${deploy_result}: \${deploy_error}\") endif() endif() endfunction() function(ly_copy source_file target_directory) file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) endfunction()" ) unset(runtime_commands) get_property(all_targets GLOBAL PROPERTY LY_ALL_TARGETS) foreach(alias_target IN LISTS all_targets) ly_de_alias_target(${alias_target} target) # Exclude targets that dont produce runtime outputs get_target_property(target_type ${target} TYPE) if(NOT target_type IN_LIST LY_TARGET_TYPES_WITH_RUNTIME_OUTPUTS) continue() endif() get_target_property(target_runtime_output_directory ${target} RUNTIME_OUTPUT_DIRECTORY) if(target_runtime_output_directory) cmake_path(RELATIVE_PATH target_runtime_output_directory BASE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_runtime_output_subdirectory) endif() # Qt get_property(has_qt_dependency GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${target}) if(has_qt_dependency) # Qt deploy needs to be done after the binary is copied to the output, so we do a install(CODE) which effectively # puts it as a postbuild step of the "install" target. Binaries are copied at that point. if(NOT EXISTS ${WINDEPLOYQT_EXECUTABLE}) message(FATAL_ERROR "Qt deploy executable not found: ${WINDEPLOYQT_EXECUTABLE}") endif() set(target_output "${install_output_folder}/${target_runtime_output_subdirectory}/$") list(APPEND runtime_commands "ly_deploy_qt_install(\"${target_output}\")\n") endif() # runtime dependencies that need to be copied to the output set(target_file_dir "${install_output_folder}/${target_runtime_output_subdirectory}") ly_get_runtime_dependencies(runtime_dependencies ${target}) foreach(runtime_dependency ${runtime_dependencies}) unset(runtime_command) ly_get_runtime_dependency_command(runtime_command ${runtime_dependency}) string(CONFIGURE "${runtime_command}" runtime_command @ONLY) list(APPEND runtime_commands ${runtime_command}) endforeach() endforeach() list(REMOVE_DUPLICATES runtime_commands) list(JOIN runtime_commands " " runtime_commands_str) # the spaces are just to see the right identation in the cmake_install.cmake file install(CODE "${runtime_commands_str}" ) endfunction() #! ly_setup_others: install directories required by the engine function(ly_setup_others) # List of directories we want to install relative to engine root set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole) foreach(dir ${DIRECTORIES_TO_INSTALL}) get_filename_component(install_path ${dir} DIRECTORY) if (NOT install_path) set(install_path .) endif() install(DIRECTORY "${LY_ROOT_FOLDER}/${dir}" DESTINATION ${install_path} PATTERN "__pycache__" EXCLUDE ) endforeach() # Scripts file(GLOB o3de_scripts "${LY_ROOT_FOLDER}/scripts/o3de.*") install(FILES ${o3de_scripts} DESTINATION ./scripts ) install(DIRECTORY ${LY_ROOT_FOLDER}/scripts/bundler ${LY_ROOT_FOLDER}/scripts/o3de DESTINATION ./scripts PATTERN "__pycache__" EXCLUDE PATTERN "CMakeLists.txt" EXCLUDE PATTERN "tests" EXCLUDE ) install(DIRECTORY "${LY_ROOT_FOLDER}/python" DESTINATION . REGEX "downloaded_packages" EXCLUDE REGEX "runtime" EXCLUDE ) # Registry install(DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$/Registry DESTINATION ./${runtime_output_directory}/${PAL_PLATFORM_NAME}/$ ) install(DIRECTORY ${LY_ROOT_FOLDER}/Registry DESTINATION . ) # Engine Source Assets install(DIRECTORY ${LY_ROOT_FOLDER}/Assets DESTINATION . ) # Gem Source Assets and Registry # Find all gem directories relative to the CMake Source Dir file(GLOB_RECURSE gems_assets_path LIST_DIRECTORIES TRUE RELATIVE "${LY_ROOT_FOLDER}/" "Gems/*" ) list(FILTER gems_assets_path INCLUDE REGEX "/(Assets|Registry)$") foreach (gem_assets_path ${gems_assets_path}) set(gem_abs_assets_path ${LY_ROOT_FOLDER}/${gem_assets_path}/) if (EXISTS ${gem_abs_assets_path}) # The trailing slash is IMPORTANT here as that is needed to prevent # the "Assets" folder from being copied underneath the /Assets folder install(DIRECTORY ${gem_abs_assets_path} DESTINATION ${gem_assets_path} ) endif() endforeach() # gem.json files file(GLOB_RECURSE gems_json_path LIST_DIRECTORIES FALSE RELATIVE "${LY_ROOT_FOLDER}" "Gems/*/gem.json" ) foreach(gem_json_path ${gems_json_path}) get_filename_component(gem_relative_path ${gem_json_path} DIRECTORY) install(FILES ${gem_json_path} DESTINATION ${gem_relative_path} ) endforeach() # Additional files needed by gems install(DIRECTORY ${LY_ROOT_FOLDER}/Gems/Atom/Asset/ImageProcessingAtom/Config DESTINATION Gems/Atom/Asset/ImageProcessingAtom ) # Templates install(DIRECTORY ${LY_ROOT_FOLDER}/Templates DESTINATION . ) # Misc install(FILES ${LY_ROOT_FOLDER}/ctest_pytest.ini ${LY_ROOT_FOLDER}/LICENSE.txt ${LY_ROOT_FOLDER}/README.md DESTINATION . ) endfunction() #! ly_setup_target_generator: install source files needed for project launcher generation function(ly_setup_target_generator) install(FILES ${LY_ROOT_FOLDER}/Code/LauncherUnified/launcher_generator.cmake ${LY_ROOT_FOLDER}/Code/LauncherUnified/launcher_project_files.cmake ${LY_ROOT_FOLDER}/Code/LauncherUnified/LauncherProject.cpp ${LY_ROOT_FOLDER}/Code/LauncherUnified/StaticModules.in DESTINATION LauncherGenerator ) install(DIRECTORY ${LY_ROOT_FOLDER}/Code/LauncherUnified/Platform DESTINATION LauncherGenerator ) install(FILES ${LY_ROOT_FOLDER}/Code/LauncherUnified/FindLauncherGenerator.cmake DESTINATION cmake ) endfunction()