diff --git a/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp b/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp index 076cce4965..aca7a41950 100644 --- a/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp +++ b/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp @@ -673,18 +673,17 @@ namespace AZ { AZ_Assert(path && path[0] != '%', "%% is deprecated, @ is the only valid alias token"); AZStd::string_view pathView(path); - AZStd::string_view aliasKey; - AZStd::string_view aliasValue; - for (const auto& alias : m_aliases) - { - AZStd::string_view key{ alias.first }; - if (AZ::StringFunc::StartsWith(pathView, key)) // we only support aliases at the front of the path + + const auto found = AZStd::find_if(m_aliases.begin(), m_aliases.end(), + [pathView](const auto& alias) { - aliasKey = key; - aliasValue = alias.second; - break; - } - } + return pathView.starts_with(alias.first); + }); + + using string_view_pair = AZStd::pair; + auto [aliasKey, aliasValue] = (found != m_aliases.end()) ? string_view_pair(*found) + : string_view_pair{}; + size_t requiredResolvedPathSize = pathView.size() - aliasKey.size() + aliasValue.size() + 1; AZ_Assert(path != resolvedPath && resolvedPathSize >= requiredResolvedPathSize, "Resolved path is incorrect"); // we assert above, but we also need to properly handle the case when the resolvedPath buffer size diff --git a/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h b/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h index 9d33d96215..a5c2bf6475 100644 --- a/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h +++ b/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h @@ -132,6 +132,7 @@ public: AZ::IO::FileIOBase::SetInstance(nullptr); delete m_localFileIO; + m_localFileIO = nullptr; if (m_otherFileIO) { diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index 1a8e805f91..3dfef0bbbf 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -29,6 +29,20 @@ define_property(TARGET PROPERTY GEM_MODULE ]] ) +define_property(TARGET PROPERTY RUNTIME_DEPENDENCIES_DEPENDS + BRIEF_DOCS "Defines the dependencies the runtime dependencies of a target has" + FULL_DOCS [[ + Property which is queried through generator expressions at the moment + the target is declared so a custom command that will do the copies can + be generated later. Custom commands need to be declared in the same folder + the target is declared, however, runtime dependencies need all targets + to be declared, so it is done towards the end of CMake parsing. When + runtime dependencies are processed, this target property is filled so the + right dependencies are set for the custom command. + This property contains all the files that are going to be copied to the output + when the target gets built. + ]] +) #! ly_add_target: adds a target and provides parameters for the common configurations. # @@ -310,16 +324,35 @@ function(ly_add_target) set_property(GLOBAL APPEND PROPERTY LY_ALL_TARGET_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) endif() + # Custom commands need to be declared in the same folder as the target that they use. + # Not all the targets will require runtime dependencies, but we will generate at least an + # empty file for them. set(runtime_dependencies_list SHARED MODULE EXECUTABLE APPLICATION) if(NOT ly_add_target_IMPORTED AND linking_options IN_LIST runtime_dependencies_list) - add_custom_command(TARGET ${ly_add_target_NAME} POST_BUILD + # the stamp file will be the one that triggers the execution of the custom rule. At the end + # of running the copy of runtime dependencies, the stamp file is touched so the timestamp is updated. + # Adding a config as part of the name since the stamp file is added to the VS project. + # Note the STAMP_OUTPUT_FILE need to match with the one used in runtime dependencies (e.g. RuntimeDependencies_common.cmake) + set(STAMP_OUTPUT_FILE ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${ly_add_target_NAME}_$.stamp) + add_custom_command( + OUTPUT ${STAMP_OUTPUT_FILE} + DEPENDS "$>" COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${ly_add_target_NAME}.cmake - DEPENDS ${CMAKE_BINARY_DIR}/runtime_dependencies/${ly_add_target_NAME}.cmake - MESSAGE "Copying runtime dependencies..." + COMMENT "Copying ${ly_add_target_NAME} runtime dependencies to output..." VERBATIM ) + # Unfortunately the VS generator cannot deal with generation expressions as part of the file name, wrapping the + # stamp file on each configuration so it gets properly excluded by the generator + unset(stamp_files_per_config) + foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) + set(stamp_file_conf ${CMAKE_BINARY_DIR}/runtime_dependencies/${conf}/${ly_add_target_NAME}_${conf}.stamp) + set_source_files_properties(${stamp_file_conf} PROPERTIES GENERATED TRUE SKIP_AUTOGEN TRUE) + list(APPEND stamp_files_per_config $<$:${stamp_file_conf}>) + endforeach() + target_sources(${ly_add_target_NAME} PRIVATE ${stamp_files_per_config}) + endif() if(ly_add_target_AUTOGEN_RULES) diff --git a/cmake/LyAutoGen.cmake b/cmake/LyAutoGen.cmake index 4aec0f9726..2f5891d837 100644 --- a/cmake/LyAutoGen.cmake +++ b/cmake/LyAutoGen.cmake @@ -34,8 +34,8 @@ function(ly_add_autogen) add_custom_command( OUTPUT ${AUTOGEN_OUTPUTS} DEPENDS ${AZCG_DEPENDENCIES} - COMMAND ${CMAKE_COMMAND} -E echo "Running AutoGen for ${ly_add_autogen_NAME}" COMMAND ${LY_PYTHON_CMD} "${LY_ROOT_FOLDER}/cmake/AzAutoGen.py" "${CMAKE_BINARY_DIR}/Azcg/TemplateCache/" "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated/" "${CMAKE_CURRENT_SOURCE_DIR}" "${AZCG_INPUTFILES}" "${ly_add_autogen_AUTOGEN_RULES}" + COMMENT "Running AutoGen for ${ly_add_autogen_NAME}" VERBATIM ) set_target_properties(${ly_add_autogen_NAME} PROPERTIES AUTOGEN_INPUT_FILES "${AZCG_INPUTFILES}") diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index bee2349e75..0bd598f70e 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -486,7 +486,8 @@ endfunction()" ly_get_runtime_dependencies(runtime_dependencies ${target}) foreach(runtime_dependency ${runtime_dependencies}) unset(runtime_command) - ly_get_runtime_dependency_command(runtime_command ${runtime_dependency}) + unset(runtime_depend) # unused, but required to be passed to ly_get_runtime_dependency_command + ly_get_runtime_dependency_command(runtime_command runtime_depend ${runtime_dependency}) string(CONFIGURE "${runtime_command}" runtime_command @ONLY) list(APPEND runtime_commands ${runtime_command}) endforeach() diff --git a/cmake/Platform/Common/RuntimeDependencies_common.cmake b/cmake/Platform/Common/RuntimeDependencies_common.cmake index a669602ff7..dbc8513c97 100644 --- a/cmake/Platform/Common/RuntimeDependencies_common.cmake +++ b/cmake/Platform/Common/RuntimeDependencies_common.cmake @@ -113,7 +113,7 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) unset(target_locations) get_target_property(target_locations ${ly_TARGET} ${imported_property}) if(target_locations) - list(APPEND all_runtime_dependencies ${target_locations}) + list(APPEND all_runtime_dependencies "${target_locations}") else() # Check if the property exists for configurations unset(target_locations) @@ -156,7 +156,7 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) endfunction() -function(ly_get_runtime_dependency_command ly_RUNTIME_COMMAND ly_TARGET) +function(ly_get_runtime_dependency_command ly_RUNTIME_COMMAND ly_RUNTIME_DEPEND ly_TARGET) # To optimize this, we are going to cache the commands for the targets we requested. A lot of targets end up being # dependencies of other targets. @@ -166,6 +166,8 @@ function(ly_get_runtime_dependency_command ly_RUNTIME_COMMAND ly_TARGET) # We already walked through this target get_property(cached_command GLOBAL PROPERTY LY_RUNTIME_DEPENDENCY_COMMAND_${ly_TARGET}) set(${ly_RUNTIME_COMMAND} ${cached_command} PARENT_SCOPE) + get_property(cached_depend GLOBAL PROPERTY LY_RUNTIME_DEPENDENCY_DEPEND_${ly_TARGET}) + set(${ly_RUNTIME_DEPEND} "${cached_depend}" PARENT_SCOPE) return() endif() @@ -223,6 +225,8 @@ function(ly_get_runtime_dependency_command ly_RUNTIME_COMMAND ly_TARGET) set_property(GLOBAL PROPERTY LY_RUNTIME_DEPENDENCY_COMMAND_${ly_TARGET} "${runtime_command}") set(${ly_RUNTIME_COMMAND} ${runtime_command} PARENT_SCOPE) + set_property(GLOBAL PROPERTY LY_RUNTIME_DEPENDENCY_DEPEND_${ly_TARGET} "${source_file}") + set(${ly_RUNTIME_DEPEND} "${source_file}" PARENT_SCOPE) endfunction() @@ -245,17 +249,20 @@ function(ly_delayed_generate_runtime_dependencies) unset(runtime_dependencies) unset(LY_COPY_COMMANDS) + unset(runtime_depends) ly_get_runtime_dependencies(runtime_dependencies ${target}) foreach(runtime_dependency ${runtime_dependencies}) unset(runtime_command) - ly_get_runtime_dependency_command(runtime_command ${runtime_dependency}) + unset(runtime_depend) + ly_get_runtime_dependency_command(runtime_command runtime_depend ${runtime_dependency}) string(APPEND LY_COPY_COMMANDS ${runtime_command}) + list(APPEND runtime_depends ${runtime_depend}) endforeach() - # Generate the output file + # Generate the output file, note the STAMP_OUTPUT_FILE need to match with the one defined in LYWrappers.cmake + set(STAMP_OUTPUT_FILE ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${target}_$.stamp) set(target_file_dir "$") - set(target_file "$") ly_file_read(${LY_RUNTIME_DEPENDENCIES_TEMPLATE} template_file) string(CONFIGURE "${LY_COPY_COMMANDS}" LY_COPY_COMMANDS @ONLY) string(CONFIGURE "${template_file}" configured_template_file @ONLY) @@ -263,6 +270,9 @@ function(ly_delayed_generate_runtime_dependencies) OUTPUT ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${target}.cmake CONTENT "${configured_template_file}" ) + + # set the property that is consumed from the custom command generated in LyWrappers.cmake + set_target_properties(${target} PROPERTIES RUNTIME_DEPENDENCIES_DEPENDS "${runtime_depends}") endforeach() diff --git a/cmake/Platform/Common/runtime_dependencies_common.cmake.in b/cmake/Platform/Common/runtime_dependencies_common.cmake.in index bb280f895b..6e41dbaad1 100644 --- a/cmake/Platform/Common/runtime_dependencies_common.cmake.in +++ b/cmake/Platform/Common/runtime_dependencies_common.cmake.in @@ -22,3 +22,5 @@ function(ly_copy source_file target_directory) endfunction() @LY_COPY_COMMANDS@ + +file(TOUCH @STAMP_OUTPUT_FILE@)