Merge remote-tracking branch 'origin/lawsonamzn_prototype_gem_naming_conventions' into ly-as-sdk/LYN-2948-phistere

This commit is contained in:
lumberyard-employee-dm
2021-05-26 00:38:51 -05:00
106 changed files with 861 additions and 616 deletions
+202
View File
@@ -0,0 +1,202 @@
#
# 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.
#
# This file contains utility wrappers for dealing with the Gems system.
# ly_create_alias
# given an alias to create, and a list of one or more targets,
# this creates an alias that depends on all of the given targets.
function(ly_create_alias)
set(options)
set(oneValueArgs NAME NAMESPACE)
set(multiValueArgs TARGETS)
cmake_parse_arguments(ly_create_alias "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT ly_create_alias_NAME)
message(FATAL_ERROR "Provide the name of the alias to create using the NAME keyword")
endif()
if (NOT ly_create_alias_NAMESPACE)
message(FATAL_ERROR "Provide the namespace of the alias to create using the NAMESPACE keyword")
endif()
if (NOT ly_create_alias_TARGETS)
message(FATAL_ERROR "Provide the name of the targets the alias be associated with, using the TARGETS keyword")
endif()
if(TARGET ${ly_create_alias_NAMESPACE}::${ly_create_alias_NAME})
message(FATAL_ERROR "Target already exists, cannot create an alias for it: ${ly_create_alias_NAMESPACE}::${ly_create_alias_NAME}\n"
"Make sure the target wasn't copy and pasted here or elsewhere.")
endif()
# easy version - if its juts one target, we can directly get the target, and make both aliases,
# the namespaced and non namespaced one, point at it.
list(LENGTH ly_create_alias_TARGETS number_of_targets)
if (number_of_targets EQUAL 1)
ly_de_alias_target(${ly_create_alias_TARGETS} de_aliased_target_name)
add_library(${ly_create_alias_NAMESPACE}::${ly_create_alias_NAME} ALIAS ${de_aliased_target_name})
if (NOT TARGET ${ly_create_alias_NAME})
add_library(${ly_create_alias_NAME} ALIAS ${de_aliased_target_name})
endif()
return()
endif()
# more complex version - one alias to multiple targets. To actually achieve this
# we have to create an interface library with those dependencies, then we have to create an alias to that target.
# by convention we create one without a namespace then alias the namespaced one.
if(TARGET ${ly_create_alias_NAME})
message(FATAL_ERROR "Internal alias target already exists, cannot create an alias for it: ${ly_create_alias_NAME}\n"
"This could be a copy-paste error, where some part of the ly_create_alias call was changed but the other")
endif()
add_library(${ly_create_alias_NAME} INTERFACE IMPORTED)
set_target_properties(${ly_create_alias_NAME} PROPERTIES GEM_MODULE TRUE)
foreach(target_name ${ly_create_alias_TARGETS})
ly_de_alias_target(${target_name} de_aliased_target_name)
if(NOT de_aliased_target_name)
message(FATAL_ERROR "Target not found in ly_create_alias call: ${target_name} - check your spelling of the target name")
endif()
list(APPEND final_targets ${de_aliased_target_name})
endforeach()
ly_parse_third_party_dependencies("${final_targets}")
ly_add_dependencies(${ly_create_alias_NAME} ${final_targets})
# now add the final alias:
add_library(${ly_create_alias_NAMESPACE}::${ly_create_alias_NAME} ALIAS ${ly_create_alias_NAME})
endfunction()
# ly_enable_gems
# this function makes sure that the given gems, or gems listed in the variable ENABLED_GEMS
# in the GEM_FILE name, are set as runtime dependencies (and thus loaded) for the given targets
# in the context of the given project.
# note that it can't do this immediately, so it saves the data for later processing.
# Note: If you don't supply a project name, it will apply it across the board to all projects.
# this is useful in the case of "ly_add_gems being called for so called 'mandatory gems' inside the engine.
# if you specify a gem name with a namespace, it will be used, otherwise it will assume Gem::
function(ly_enable_gems)
set(options)
set(oneValueArgs PROJECT_NAME GEM_FILE)
set(multiValueArgs GEMS TARGETS VARIANTS)
cmake_parse_arguments(ly_enable_gems "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT ly_enable_gems_TARGETS)
message(FATAL_ERROR "You must provide the targets to add gems to using the TARGETS keyword")
endif()
if (NOT ly_enable_gems_PROJECT_NAME)
message(VERBOSE "Note: ly_enable_gems called with no PROJECT_NAME name, applying to all projects: \n"
" - VARIANTS ${ly_enable_gems_VARIANTS} \n"
" - GEMS ${ly_enable_gems_GEMS} \n"
" - TARGETS ${ly_enable_gems_TARGETS} \n"
" - GEM_FILE ${ly_enable_gems_GEM_FILE}")
set(ly_enable_gems_PROJECT_NAME "__NOPROJECT__") # so that the token is not blank
endif()
if (NOT ly_enable_gems_VARIANTS)
message(FATAL_ERROR "You must provide at least 1 variant of the gem modules (Editor, Server, Client, Builder) to "
"add to your targets, using the VARIANTS keyword")
endif()
if ((NOT ly_enable_gems_GEMS AND NOT ly_enable_gems_GEM_FILE) OR (ly_enable_gems_GEMS AND ly_enable_gems_GEM_FILE))
message(FATAL_ERROR "Provide exactly one of either GEM_FILE (filename) or GEMS (list of gems) keywords.")
endif()
if (ly_enable_gems_GEM_FILE)
set(store_temp ${ENABLED_GEMS})
include(${ly_enable_gems_GEM_FILE} RESULT_VARIABLE was_able_to_load_the_file)
if(NOT was_able_to_load_the_file)
message(FATAL_ERROR "could not load the GEM_FILE ${ly_enable_gems_GEM_FILE}")
endif()
if(NOT ENABLED_GEMS)
message(FATAL_ERROR "GEM_FILE ${ly_enable_gems_GEM_FILE} did not set the value of ENABLED_GEMS.\n"
"Gem Files should contain set(ENABLED_GEMS ... <list of gem names>)")
endif()
set(ly_enable_gems_GEMS ${ENABLED_GEMS})
set(ENABLED_GEMS ${store_temp}) # restore value of ENABLED_GEMS just in case...
endif()
# all the actual work has to be done later.
foreach(target_name ${ly_enable_gems_TARGETS})
foreach(variant_name ${ly_enable_gems_VARIANTS})
set_property(GLOBAL APPEND PROPERTY LY_DELAYED_ENABLE_GEMS "${ly_enable_gems_PROJECT_NAME},${target_name},${variant_name}")
set_property(GLOBAL APPEND PROPERTY LY_DELAYED_ENABLE_GEMS_"${ly_enable_gems_PROJECT_NAME},${target_name},${variant_name}" ${ly_enable_gems_GEMS})
endforeach()
endforeach()
endfunction()
# call this before runtime dependencies are used to add any relevant targets
# saved by the above function
function(ly_enable_gems_delayed)
get_property(ly_delayed_enable_gems GLOBAL PROPERTY LY_DELAYED_ENABLE_GEMS)
foreach(project_target_variant ${ly_delayed_enable_gems})
# we expect a colon seperated list of
# PROJECT_NAME,target_name,variant_name
string(REPLACE "," ";" project_target_variant_list "${project_target_variant}")
list(LENGTH project_target_variant_list project_target_variant_length)
if(project_target_variant_length EQUAL 0)
continue()
endif()
if(NOT project_target_variant_length EQUAL 3)
message(FATAL_ERROR "Invalid specificaiton of gems, expected 'project','target','variant' and got ${project_target_variant}")
endif()
list(POP_BACK project_target_variant_list variant)
list(POP_BACK project_target_variant_list target)
list(POP_BACK project_target_variant_list project)
get_property(gem_dependencies GLOBAL PROPERTY LY_DELAYED_ENABLE_GEMS_"${project_target_variant}")
if (NOT gem_dependencies)
continue()
endif()
if(${project} STREQUAL "__NOPROJECT__")
# special case, apply to all
unset(PREFIX_CLAUSE)
else()
set(PREFIX_CLAUSE "PREFIX;${project}")
endif()
if (NOT TARGET ${target})
message(FATAL_ERROR "ly_enable_gems specified TARGET '${target}' but no such target was found.")
endif()
# apply the list of gem targets. Adding a gem really just means adding the appropriate dependency.
foreach(gem_name ${gem_dependencies})
# the gem name may already have a namespace. If it does, we use that one
ly_strip_target_namespace(TARGET ${gem_name} OUTPUT_VARIABLE unaliased_gem_name)
if (${unaliased_gem_name} STREQUAL ${gem_name})
# if stripping a namespace had no effect, it had no namespace
# and we supply the default Gem:: namespace.
set(gem_name_with_namespace Gem::${gem_name})
else()
# if stripping the namespace had an effect then we use the original
# with the namespace, instead of assuming Gem::
set(gem_name_with_namespace ${gem_name})
endif()
# if the target exists, add it.
if (TARGET ${gem_name_with_namespace}.${variant})
ly_add_target_dependencies(
${PREFIX_CLAUSE}
TARGETS ${target}
DEPENDENT_TARGETS ${gem_name_with_namespace}.${variant}
)
endif()
endforeach()
endforeach()
endfunction()
+2 -1
View File
@@ -685,6 +685,7 @@ function(ly_de_alias_target target_name output_variable_name)
while(target_name)
set(de_aliased_target_name ${target_name})
get_target_property(target_name ${target_name} ALIASED_TARGET)
endwhile()
@@ -692,4 +693,4 @@ function(ly_de_alias_target target_name output_variable_name)
message(FATAL_ERROR "Empty de_aliased for ${target_name}")
endif()
set(${output_variable_name} ${de_aliased_target_name} PARENT_SCOPE)
endfunction()
endfunction()
+19 -4
View File
@@ -67,6 +67,7 @@ function(ly_get_gem_load_dependencies ly_GEM_LOAD_DEPENDENCIES ly_TARGET)
# Skip wrapping produced when targets are not created in the same directory
if(NOT ${load_dependency} MATCHES "^::@")
get_property(dependency_type TARGET ${load_dependency} PROPERTY TYPE)
get_property(is_gem_target TARGET ${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
@@ -121,12 +122,10 @@ endfunction()
# This can be used for example to determine which list of gems to load with an application
function(ly_delayed_generate_settings_registry)
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)
message(SEND_ERROR "Delayed load target is missing target name")
continue()
endif()
@@ -146,6 +145,14 @@ function(ly_delayed_generate_settings_registry)
endforeach()
list(REMOVE_DUPLICATES all_gem_dependencies)
# de-namespace them
foreach(gem_target ${all_gem_dependencies})
ly_de_alias_target(TARGET ${gem_target} OUTPUT_VARIABLE stripped_gem_target)
list(APPEND new_gem_dependencies ${stripped_gem_target})
endforeach()
set(all_gem_dependencies ${new_gem_dependencies})
list(REMOVE_DUPLICATES all_gem_dependencies)
unset(target_gem_dependencies_names)
foreach(gem_target ${all_gem_dependencies})
unset(gem_relative_source_dir)
@@ -154,11 +161,19 @@ function(ly_delayed_generate_settings_registry)
message(FATAL_ERROR "Dependency ${gem_target} from ${target} does not exist")
endif()
get_target_property(target_type ${gem_target} TYPE)
if (target_type STREQUAL "INTERFACE_LIBRARY")
# don't use interface libraries here, we only want ones which produce actual binaries.
# we have still already recursed into their dependencies - they'll show up later.
continue()
endif()
ly_get_gem_module_root(gem_module_root ${gem_target})
file(RELATIVE_PATH gem_module_root_relative_to_engine_root ${LY_ROOT_FOLDER} ${gem_module_root})
# Strip target namespace from gem targets before configuring them into the json template
ly_strip_target_namespace(TARGET ${gem_target} OUTPUT_VARIABLE stripped_gem_target)
# De-alias namespace from gem targets before configuring them into the json template
ly_de_alias_target(TARGET ${gem_target} OUTPUT_VARIABLE stripped_gem_target)
string(CONFIGURE ${gem_module_template} gem_module_json @ONLY)
list(APPEND target_gem_dependencies_names ${gem_module_json})
endforeach()