|
@@ -69,75 +69,106 @@ function(ly_detect_cycle_through_visitation item visited_items visited_items_var
|
|
set(${visited_items_var} "${visited_items}" PARENT_SCOPE)
|
|
set(${visited_items_var} "${visited_items}" PARENT_SCOPE)
|
|
endfunction()
|
|
endfunction()
|
|
|
|
|
|
-#!ly_get_gem_load_dependencies: Retrieves the list of "load" dependencies for a target
|
|
|
|
-# Visits through only MANUALLY_ADDED_DEPENDENCIES of targets with a GEM_MODULE property
|
|
|
|
|
|
+#!o3de_get_gem_load_dependencies: Retrieves the list of "load" dependencies for a target
|
|
|
|
+# Visits through MANUALLY_ADDED_DEPENDENCIES of targets with a GEM_MODULE property
|
|
# to determine which gems a target needs to load
|
|
# to determine which gems a target needs to load
|
|
-# ly_get_runtime_dependencies cannot be used as it will recurse through non-manually added dependencies
|
|
|
|
|
|
+#
|
|
|
|
+# NOTE: ly_get_runtime_dependencies cannot be used as it will recurse through non-manually added dependencies
|
|
# to add manually added added which results in false load dependencies.
|
|
# to add manually added added which results in false load dependencies.
|
|
-# \arg:ly_GEM_LOAD_DEPENDENCIES(name) - Output variable to be populated gem load dependencies
|
|
|
|
-# \arg:ly_TARGET(TARGET) - CMake target to examine for dependencies
|
|
|
|
-function(ly_get_gem_load_dependencies ly_GEM_LOAD_DEPENDENCIES ly_TARGET)
|
|
|
|
- if(NOT TARGET ${ly_TARGET})
|
|
|
|
|
|
+# \arg:GEM_LOAD_DEPENDENCIES(name) - Output variable to be populated gem load dependencies
|
|
|
|
+# \arg:TARGET(TARGET) - CMake target to examine for dependencies
|
|
|
|
+# \arg:CYCLE_DETECTION_SET(variable name)[optional] - Used to track cycles in load dependencies
|
|
|
|
+function(o3de_get_gem_load_dependencies)
|
|
|
|
+ set(options)
|
|
|
|
+ set(oneValueArgs TARGET GEM_LOAD_DEPENDENCIES_VAR)
|
|
|
|
+ set(multiValueArgs CYCLE_DETECTION_SET)
|
|
|
|
+
|
|
|
|
+ cmake_parse_arguments(o3de_get_gem_load_dependencies "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
|
|
+ if(NOT TARGET ${o3de_get_gem_load_dependencies_TARGET})
|
|
return() # Nothing to do
|
|
return() # Nothing to do
|
|
endif()
|
|
endif()
|
|
- # Internally we use a third parameter to pass the list of targets that we have traversed. This is
|
|
|
|
- # used to detect runtime cycles
|
|
|
|
- if(ARGC EQUAL 3)
|
|
|
|
- set(ly_CYCLE_DETECTION_TARGETS ${ARGV2})
|
|
|
|
- else()
|
|
|
|
- set(ly_CYCLE_DETECTION_TARGETS "")
|
|
|
|
|
|
+
|
|
|
|
+ # Define the indent level variable to 0 in the first iteration
|
|
|
|
+ if(NOT DEFINED indent_level)
|
|
|
|
+ set(indent_level "0")
|
|
endif()
|
|
endif()
|
|
|
|
|
|
|
|
+ # Set indent string for current indent level
|
|
|
|
+ string(REPEAT " " "${indent_level}" indent)
|
|
|
|
+
|
|
|
|
+ set(target ${o3de_get_gem_load_dependencies_TARGET})
|
|
|
|
+ set(gem_load_dependencies_var ${o3de_get_gem_load_dependencies_GEM_LOAD_DEPENDENCIES_VAR})
|
|
|
|
+ set(cycle_detection_targets ${o3de_get_gem_load_dependencies_CYCLE_DETECTION_SET})
|
|
|
|
+
|
|
# Optimize the search by caching gem load dependencies
|
|
# Optimize the search by caching gem load dependencies
|
|
- get_property(are_dependencies_cached GLOBAL PROPERTY LY_GEM_LOAD_DEPENDENCIES_${ly_TARGET} SET)
|
|
|
|
|
|
+ get_property(are_dependencies_cached GLOBAL PROPERTY "LY_GEM_LOAD_DEPENDENCIES,${target}" SET)
|
|
if(are_dependencies_cached)
|
|
if(are_dependencies_cached)
|
|
# We already walked through this target
|
|
# We already walked through this target
|
|
- get_property(cached_dependencies GLOBAL PROPERTY LY_GEM_LOAD_DEPENDENCIES_${ly_TARGET})
|
|
|
|
- set(${ly_GEM_LOAD_DEPENDENCIES} ${cached_dependencies} PARENT_SCOPE)
|
|
|
|
|
|
+ get_property(cached_dependencies GLOBAL PROPERTY "LY_GEM_LOAD_DEPENDENCIES,${target}")
|
|
|
|
+ set(${gem_load_dependencies_var} ${cached_dependencies} PARENT_SCOPE)
|
|
|
|
+ message(DEBUG "${indent}Found cache load dependencies for Gem Target \"${target}\": ${cached_dependencies}")
|
|
return()
|
|
return()
|
|
endif()
|
|
endif()
|
|
|
|
|
|
|
|
+ message(DEBUG "${indent}Visiting target \"${target}\" when looking for gem module load dependencies")
|
|
|
|
+
|
|
# detect cycles
|
|
# detect cycles
|
|
unset(cycle_detected)
|
|
unset(cycle_detected)
|
|
- ly_detect_cycle_through_visitation(${ly_TARGET} "${ly_CYCLE_DETECTION_TARGETS}" ly_CYCLE_DETECTION_TARGETS cycle_detected)
|
|
|
|
|
|
+ ly_detect_cycle_through_visitation(${target} "${cycle_detection_targets}" cycle_detection_targets cycle_detected)
|
|
if(cycle_detected)
|
|
if(cycle_detected)
|
|
message(FATAL_ERROR "Runtime dependency detected: ${cycle_detected}")
|
|
message(FATAL_ERROR "Runtime dependency detected: ${cycle_detected}")
|
|
endif()
|
|
endif()
|
|
|
|
|
|
- unset(all_gem_load_dependencies)
|
|
|
|
-
|
|
|
|
# For load dependencies, we want to copy over the dependency and traverse them
|
|
# For load dependencies, we want to copy over the dependency and traverse them
|
|
# Only if the dependency has a GEM_MODULE property
|
|
# Only if the dependency has a GEM_MODULE property
|
|
|
|
+ get_property(manually_added_dependencies TARGET ${target} PROPERTY MANUALLY_ADDED_DEPENDENCIES)
|
|
unset(load_dependencies)
|
|
unset(load_dependencies)
|
|
- get_target_property(load_dependencies ${ly_TARGET} MANUALLY_ADDED_DEPENDENCIES)
|
|
|
|
- if(load_dependencies)
|
|
|
|
- foreach(load_dependency ${load_dependencies})
|
|
|
|
- # Skip wrapping produced when targets are not created in the same directory
|
|
|
|
- ly_de_alias_target(${load_dependency} dealias_load_dependency)
|
|
|
|
- get_property(is_gem_target TARGET ${dealias_load_dependency} PROPERTY GEM_MODULE SET)
|
|
|
|
- # If the dependency is a "gem module" then add it as a load dependencies
|
|
|
|
- # and recurse into its manually added dependencies
|
|
|
|
- if (is_gem_target)
|
|
|
|
- unset(dependencies)
|
|
|
|
- ly_get_gem_load_dependencies(dependencies ${dealias_load_dependency} "${ly_CYCLE_DETECTION_TARGETS}")
|
|
|
|
- list(APPEND all_gem_load_dependencies ${dependencies})
|
|
|
|
- list(APPEND all_gem_load_dependencies ${dealias_load_dependency})
|
|
|
|
- endif()
|
|
|
|
- endforeach()
|
|
|
|
|
|
+ if(manually_added_dependencies)
|
|
|
|
+ list(APPEND load_dependencies ${manually_added_dependencies})
|
|
|
|
+ message(VERBOSE "${indent}Gem Target \"${target}\" has direct manually added dependencies of: ${manually_added_dependencies}")
|
|
endif()
|
|
endif()
|
|
|
|
|
|
|
|
+ # unset all_gem_load_dependencies to prevent using variable values from the PARENT_SCOPE
|
|
|
|
+ unset(all_gem_load_dependencies)
|
|
|
|
+ # Remove duplicate load dependencies
|
|
|
|
+ list(REMOVE_DUPLICATES load_dependencies)
|
|
|
|
+ foreach(load_dependency IN LISTS load_dependencies)
|
|
|
|
+ # Skip wrapping produced when targets are not created in the same directory
|
|
|
|
+ ly_de_alias_target(${load_dependency} dealias_load_dependency)
|
|
|
|
+ get_property(is_gem_target TARGET ${dealias_load_dependency} PROPERTY GEM_MODULE SET)
|
|
|
|
+ # If the dependency is a "gem module" then add it as a load dependencies
|
|
|
|
+ # and recurse into its manually added dependencies
|
|
|
|
+ if (is_gem_target)
|
|
|
|
+ # shift identation level for recursive calls to ${CMAKE_CURRENT_FUNCTION}
|
|
|
|
+ set(current_indent_level "${indent_level}")
|
|
|
|
+ math(EXPR indent_level "${current_indent_level} + 2")
|
|
|
|
+ unset(dependencies)
|
|
|
|
+ o3de_get_gem_load_dependencies(
|
|
|
|
+ GEM_LOAD_DEPENDENCIES_VAR dependencies
|
|
|
|
+ TARGET ${dealias_load_dependency}
|
|
|
|
+ CYCLE_DETECTION_SET "${cycle_detection_set}"
|
|
|
|
+ )
|
|
|
|
+ # restore indentation level
|
|
|
|
+ set(indent_level "${current_indent_level}")
|
|
|
|
+
|
|
|
|
+ list(APPEND all_gem_load_dependencies ${dependencies})
|
|
|
|
+ list(APPEND all_gem_load_dependencies ${dealias_load_dependency})
|
|
|
|
+ endif()
|
|
|
|
+ endforeach()
|
|
|
|
+
|
|
list(REMOVE_DUPLICATES all_gem_load_dependencies)
|
|
list(REMOVE_DUPLICATES all_gem_load_dependencies)
|
|
- set_property(GLOBAL PROPERTY LY_GEM_LOAD_DEPENDENCIES_${ly_TARGET} "${all_gem_load_dependencies}")
|
|
|
|
- set(${ly_GEM_LOAD_DEPENDENCIES} ${all_gem_load_dependencies} PARENT_SCOPE)
|
|
|
|
- message(VERBOSE "Gem Target \"${ly_TARGET}\" has load dependencies of: ${all_gem_load_dependencies}")
|
|
|
|
|
|
+ set_property(GLOBAL PROPERTY "LY_GEM_LOAD_DEPENDENCIES,${target}" "${all_gem_load_dependencies}")
|
|
|
|
+ set(${gem_load_dependencies_var} ${all_gem_load_dependencies} PARENT_SCOPE)
|
|
|
|
+ message(VERBOSE "${indent}Gem Target \"${target}\" has load dependencies of: ${all_gem_load_dependencies}")
|
|
|
|
|
|
endfunction()
|
|
endfunction()
|
|
|
|
|
|
-#!ly_get_gem_module_root: Uses the supplied gem_target to lookup the nearest gem.json file above the SOURCE_DIR
|
|
|
|
|
|
+#!o3de_get_gem_root_from_target: Uses the supplied gem_target to lookup the nearest
|
|
|
|
+# gem.json file at an ancestor of targets SOURCE_DIR property
|
|
#
|
|
#
|
|
# \arg:gem_target(TARGET) - Target to look upwards from using its SOURCE_DIR property
|
|
# \arg:gem_target(TARGET) - Target to look upwards from using its SOURCE_DIR property
|
|
-function(ly_get_gem_module_root output_gem_module_root output_gem_name gem_target)
|
|
|
|
- unset(${output_gem_module_root} PARENT_SCOPE)
|
|
|
|
|
|
+function(o3de_get_gem_root_from_target output_gem_root output_gem_name gem_target)
|
|
|
|
+ unset(${output_gem_root} PARENT_SCOPE)
|
|
get_property(gem_source_dir TARGET ${gem_target} PROPERTY SOURCE_DIR)
|
|
get_property(gem_source_dir TARGET ${gem_target} PROPERTY SOURCE_DIR)
|
|
|
|
|
|
# the o3de_find_ancestor_gem_root looks up the nearest gem root path
|
|
# the o3de_find_ancestor_gem_root looks up the nearest gem root path
|
|
@@ -146,7 +177,7 @@ function(ly_get_gem_module_root output_gem_module_root output_gem_name gem_targe
|
|
|
|
|
|
# Set the gem module root output directory to the location with the gem.json file within it or
|
|
# Set the gem module root output directory to the location with the gem.json file within it or
|
|
# the supplied gem_target SOURCE_DIR location if no gem.json file was found
|
|
# the supplied gem_target SOURCE_DIR location if no gem.json file was found
|
|
- set(${output_gem_module_root} ${gem_source_dir} PARENT_SCOPE)
|
|
|
|
|
|
+ set(${output_gem_root} ${gem_source_dir} PARENT_SCOPE)
|
|
|
|
|
|
# Set the gem name output value to the name of the gem as in the gem.json file
|
|
# Set the gem name output value to the name of the gem as in the gem.json file
|
|
if(gem_name)
|
|
if(gem_name)
|
|
@@ -166,7 +197,7 @@ function(ly_populate_gem_objects output_gem_setreg_objects all_gem_dependencies)
|
|
message(FATAL_ERROR "Dependency ${gem_target} from ${target} does not exist")
|
|
message(FATAL_ERROR "Dependency ${gem_target} from ${target} does not exist")
|
|
endif()
|
|
endif()
|
|
|
|
|
|
- ly_get_gem_module_root(gem_module_root gem_name_value ${gem_target})
|
|
|
|
|
|
+ o3de_get_gem_root_from_target(gem_module_root gem_name_value ${gem_target})
|
|
if (NOT gem_module_root)
|
|
if (NOT gem_module_root)
|
|
# If the target doesn't have a gem.json, skip it
|
|
# If the target doesn't have a gem.json, skip it
|
|
continue()
|
|
continue()
|
|
@@ -215,26 +246,31 @@ function(ly_delayed_generate_settings_registry)
|
|
endif()
|
|
endif()
|
|
|
|
|
|
get_property(ly_delayed_load_targets GLOBAL PROPERTY LY_DELAYED_LOAD_DEPENDENCIES)
|
|
get_property(ly_delayed_load_targets GLOBAL PROPERTY LY_DELAYED_LOAD_DEPENDENCIES)
|
|
- foreach(prefix_target ${ly_delayed_load_targets})
|
|
|
|
- string(REPLACE "," ";" prefix_target_list "${prefix_target}")
|
|
|
|
- list(LENGTH prefix_target_list prefix_target_length)
|
|
|
|
- if(prefix_target_length EQUAL 0)
|
|
|
|
|
|
+ foreach(prefix_target_variant ${ly_delayed_load_targets})
|
|
|
|
+ string(REPLACE "," ";" prefix_target_variant_list "${prefix_target_variant}")
|
|
|
|
+ list(LENGTH prefix_target_variant_list prefix_target_variant_length)
|
|
|
|
+ if(prefix_target_variant_length EQUAL 0)
|
|
continue()
|
|
continue()
|
|
endif()
|
|
endif()
|
|
|
|
|
|
- # Retrieve the target name from the back of the list
|
|
|
|
- list(POP_BACK prefix_target_list target)
|
|
|
|
- # Retrieves the prefix if available from the remaining element of the list
|
|
|
|
- list(POP_BACK prefix_target_list prefix)
|
|
|
|
|
|
+ # Retrieves the prefix if available from the front of the list
|
|
|
|
+ list(POP_FRONT prefix_target_variant_list prefix)
|
|
|
|
+ # Retrieve the target name from the next element of the list
|
|
|
|
+ list(POP_FRONT prefix_target_variant_list target)
|
|
|
|
+ # Retreive the variant name from the last element of the list
|
|
|
|
+ list(POP_BACK prefix_target_variant_list variant)
|
|
|
|
|
|
# Get the gem dependencies for the given project and target combination
|
|
# Get the gem dependencies for the given project and target combination
|
|
- get_property(gem_dependencies GLOBAL PROPERTY LY_DELAYED_LOAD_"${prefix_target}")
|
|
|
|
- message(VERBOSE "${prefix_target} has direct gem load dependencies of ${gem_dependencies}")
|
|
|
|
- list(REMOVE_DUPLICATES gem_dependencies) # Strip out any duplicate gem targets
|
|
|
|
|
|
+ get_property(target_load_dependencies GLOBAL PROPERTY LY_DELAYED_LOAD_"${prefix_target_variant}")
|
|
|
|
+ message(VERBOSE "prefix=${prefix},target=${target},variant=${variant} has direct load dependencies of ${target_load_dependencies}")
|
|
|
|
+ list(REMOVE_DUPLICATES target_load_dependencies) # Strip out any duplicate load dependency CMake targets
|
|
unset(all_gem_dependencies)
|
|
unset(all_gem_dependencies)
|
|
|
|
|
|
- foreach(gem_target ${gem_dependencies})
|
|
|
|
- ly_get_gem_load_dependencies(gem_load_gem_dependencies ${gem_target})
|
|
|
|
|
|
+ foreach(gem_target IN LISTS target_load_dependencies)
|
|
|
|
+ o3de_get_gem_load_dependencies(
|
|
|
|
+ GEM_LOAD_DEPENDENCIES_VAR gem_load_gem_dependencies
|
|
|
|
+ TARGET "${gem_target}"
|
|
|
|
+ )
|
|
list(APPEND all_gem_dependencies ${gem_load_gem_dependencies} ${gem_target})
|
|
list(APPEND all_gem_dependencies ${gem_load_gem_dependencies} ${gem_target})
|
|
endforeach()
|
|
endforeach()
|
|
list(REMOVE_DUPLICATES all_gem_dependencies)
|
|
list(REMOVE_DUPLICATES all_gem_dependencies)
|
|
@@ -250,7 +286,7 @@ function(ly_delayed_generate_settings_registry)
|
|
|
|
|
|
# Fill out the gem_setreg_objects variable with the json fields for each gem
|
|
# Fill out the gem_setreg_objects variable with the json fields for each gem
|
|
unset(gem_setreg_objects)
|
|
unset(gem_setreg_objects)
|
|
- ly_populate_gem_objects(gem_json "${all_gem_dependencies}")
|
|
|
|
|
|
+ ly_populate_gem_objects(gem_load_dependencies_json "${all_gem_dependencies}")
|
|
|
|
|
|
string(REPLACE "." "_" escaped_target ${target})
|
|
string(REPLACE "." "_" escaped_target ${target})
|
|
string(JOIN "." specialization_name ${prefix} ${escaped_target})
|
|
string(JOIN "." specialization_name ${prefix} ${escaped_target})
|
|
@@ -270,11 +306,11 @@ function(ly_delayed_generate_settings_registry)
|
|
set(target_dir $<TARGET_FILE_DIR:${target}>)
|
|
set(target_dir $<TARGET_FILE_DIR:${target}>)
|
|
endif()
|
|
endif()
|
|
set(dependencies_setreg ${target_dir}/Registry/cmake_dependencies.${specialization_name}.setreg)
|
|
set(dependencies_setreg ${target_dir}/Registry/cmake_dependencies.${specialization_name}.setreg)
|
|
- file(GENERATE OUTPUT ${dependencies_setreg} CONTENT "${gem_json}")
|
|
|
|
|
|
+ file(GENERATE OUTPUT ${dependencies_setreg} CONTENT "${gem_load_dependencies_json}")
|
|
set_property(TARGET ${target} APPEND PROPERTY INTERFACE_LY_TARGET_FILES "${dependencies_setreg}\nRegistry")
|
|
set_property(TARGET ${target} APPEND PROPERTY INTERFACE_LY_TARGET_FILES "${dependencies_setreg}\nRegistry")
|
|
|
|
|
|
- # Clear out load dependencies for the project/target combination
|
|
|
|
- set_property(GLOBAL PROPERTY LY_DELAYED_LOAD_"${prefix_target}")
|
|
|
|
|
|
+ # Clear out load dependencies for the prefix,target,variant combination
|
|
|
|
+ set_property(GLOBAL PROPERTY LY_DELAYED_LOAD_"${prefix_target_variant}")
|
|
endforeach()
|
|
endforeach()
|
|
|
|
|
|
# Clear out the load targets from the global load dependencies list
|
|
# Clear out the load targets from the global load dependencies list
|