diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 50e00e4c84..ca49542ccf 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -1,6 +1,6 @@ /* * 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 * */ @@ -23,6 +23,8 @@ #include #include +#include + namespace Platform { bool InsertPythonLibraryPath( @@ -42,7 +44,7 @@ namespace Platform return false; } - // Implemented in each different platform's PAL implentation files, as it differs per platform. + // Implemented in each different platform's PAL implementation files, as it differs per platform. AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot); } // namespace Platform @@ -843,11 +845,19 @@ namespace O3DE::ProjectManager templateInfo.m_canonicalTags.push_back(Py_To_String(tag)); } } - if (data.contains("included_gems")) + + QString templateProjectPath = QDir(templateInfo.m_path).filePath("Template"); + auto enabledGemNames = GetEnabledGemNames(templateProjectPath); + if (enabledGemNames) { - for (auto gem : data["included_gems"]) + for (auto gem : enabledGemNames.GetValue()) { - templateInfo.m_includedGems.push_back(Py_To_String(gem)); + // Exclude the template ${Name} placeholder for the list of included gems + // That Gem gets created with the project + if (!gem.contains("${Name}")) + { + templateInfo.m_includedGems.push_back(Py_To_String(gem.c_str())); + } } } } diff --git a/Gems/Atom/CMakeLists.txt b/Gems/Atom/CMakeLists.txt index 3c7a6951f6..8dc38ec7ad 100644 --- a/Gems/Atom/CMakeLists.txt +++ b/Gems/Atom/CMakeLists.txt @@ -14,3 +14,11 @@ add_subdirectory(RPI) add_subdirectory(Tools) add_subdirectory(Utils) +# The "Atom" Gem will alias the real Atom_AtomBridge target variants +# allows the enabling and disabling the "Atom" Gem to build the pre-requisite dependencies +ly_create_alias(NAME Atom.Clients NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Clients) +ly_create_alias(NAME Atom.Servers NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Servers) +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_create_alias(NAME Atom.Builders NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Builders) + ly_create_alias(NAME Atom.Tools NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Tools) +endif() diff --git a/Gems/AtomLyIntegration/CMakeLists.txt b/Gems/AtomLyIntegration/CMakeLists.txt index 798cacfb2e..35d4d388a6 100644 --- a/Gems/AtomLyIntegration/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CMakeLists.txt @@ -14,3 +14,12 @@ add_subdirectory(TechnicalArt) add_subdirectory(AtomBridge) add_subdirectory(AtomViewportDisplayInfo) add_subdirectory(AtomViewportDisplayIcons) + +# The "AtomLyIntegration" Gem will also alias the real Atom_AtomBridge target variants +# The Atom Gem does the same at the moment. +ly_create_alias(NAME AtomLyIntegration.Clients NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Clients) +ly_create_alias(NAME AtomLyIntegration.Servers NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Servers) +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_create_alias(NAME AtomLyIntegration.Builders NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Builders) + ly_create_alias(NAME AtomLyIntegration.Tools NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Tools) +endif() diff --git a/Templates/DefaultProject/Template/Code/enabled_gems.cmake b/Templates/DefaultProject/Template/Code/enabled_gems.cmake index 99c3b89895..9ccce2905c 100644 --- a/Templates/DefaultProject/Template/Code/enabled_gems.cmake +++ b/Templates/DefaultProject/Template/Code/enabled_gems.cmake @@ -7,7 +7,7 @@ set(ENABLED_GEMS ${Name} - Atom_AtomBridge + Atom AudioSystem AWSCore CameraFramework diff --git a/Templates/DefaultProject/template.json b/Templates/DefaultProject/template.json index fabfb0cf18..5eaf66e3af 100644 --- a/Templates/DefaultProject/template.json +++ b/Templates/DefaultProject/template.json @@ -6,7 +6,6 @@ "license": "What license DefaultProject uses goes here: i.e. https://opensource.org/licenses/MIT", "display_name": "Standard", "summary": "This template has everything you need to build a full online 3D game or application.", - "included_gems": ["Atom","Camera","EMotionFX","UI","Maestro","Input","ImGui"], "canonical_tags": [], "user_tags": [ "DefaultProject" diff --git a/Templates/MinimalProject/Template/Code/enabled_gems.cmake b/Templates/MinimalProject/Template/Code/enabled_gems.cmake index 13774c2831..db63d149ab 100644 --- a/Templates/MinimalProject/Template/Code/enabled_gems.cmake +++ b/Templates/MinimalProject/Template/Code/enabled_gems.cmake @@ -7,7 +7,7 @@ set(ENABLED_GEMS ${Name} - Atom_AtomBridge + Atom CameraFramework ImGui ) diff --git a/cmake/Gems.cmake b/cmake/Gems.cmake index 634e09f596..b120c28db3 100644 --- a/cmake/Gems.cmake +++ b/cmake/Gems.cmake @@ -31,25 +31,29 @@ function(ly_create_alias) "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, + # easy version - if its just one target and it exist at the time of this call, + # 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}) + if(TARGET ${ly_create_alias_TARGETS}) + 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() + # Store off the arguments needed used ly_create_alias into a DIRECTORY property + # This will be used to re-create the calls in the generated CMakeLists.txt in the INSTALL step + string(REPLACE ";" " " create_alias_args "${ly_create_alias_NAME},${ly_create_alias_NAMESPACE},${ly_create_alias_TARGETS}") + set_property(DIRECTORY APPEND PROPERTY LY_CREATE_ALIAS_ARGUMENTS "${ly_create_alias_NAME},${ly_create_alias_NAMESPACE},${ly_create_alias_TARGETS}") + return() endif() - # Store off the arguments needed used ly_create_alias into a DIRECTORY property - # This will be used to re-create the calls in the generated CMakeLists.txt in the INSTALL step - string(REPLACE ";" " " create_alias_args "${ly_create_alias_NAME},${ly_create_alias_NAMESPACE},${ly_create_alias_TARGETS}") - set_property(DIRECTORY APPEND PROPERTY LY_CREATE_ALIAS_ARGUMENTS "${ly_create_alias_NAME},${ly_create_alias_NAMESPACE},${ly_create_alias_TARGETS}") - 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. + # more complex version - one alias to multiple targets or the alias is being made to a TARGET that doesn't exist yet. + # 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" diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index c4a7cf8f36..3d78c990a2 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -212,6 +212,28 @@ def save_o3de_manifest(json_data: dict, manifest_path: pathlib.Path = None) -> b return False + +def get_gems_from_subdirectories(external_subdirs: list) -> list: + ''' + Helper Method for scanning a set of external subdirectories for gem.json files + ''' + def is_gem_subdirectory(subdir_files): + for name in files: + if name == 'gem.json': + return True + return False + + gem_directories = [] + # Locate all subfolders with gem.json files within them + if external_subdirs: + for subdirectory in external_subdirs: + for root, dirs, files in os.walk(pathlib.Path(subdirectory).resolve()): + if is_gem_subdirectory(files): + gem_directories.append(pathlib.PurePath(root).as_posix()) + + return gem_directories + + # Data query methods def get_this_engine() -> dict: json_data = load_o3de_manifest() @@ -230,11 +252,7 @@ def get_projects() -> list: def get_gems() -> list: - def is_gem_subdirectory(subdir): - return (pathlib.Path(subdir) / 'gem.json').exists() - - external_subdirs = get_external_subdirectories() - return list(filter(is_gem_subdirectory, external_subdirs)) if external_subdirs else [] + return get_gems_from_subdirectories(get_external_subdirectories()) def get_external_subdirectories() -> list: @@ -265,11 +283,7 @@ def get_engine_projects() -> list: def get_engine_gems() -> list: - def is_gem_subdirectory(subdir): - return (pathlib.Path(subdir) / 'gem.json').exists() - - external_subdirs = get_engine_external_subdirectories() - return list(filter(is_gem_subdirectory, external_subdirs)) if external_subdirs else [] + return get_gems_from_subdirectories(get_engine_external_subdirectories()) def get_engine_external_subdirectories() -> list: @@ -295,11 +309,7 @@ def get_engine_restricted() -> list: # project.json queries def get_project_gems(project_path: pathlib.Path) -> list: - def is_gem_subdirectory(subdir): - return (pathlib.Path(subdir) / 'gem.json').exists() - - external_subdirs = get_project_external_subdirectories(project_path) - return list(filter(is_gem_subdirectory, external_subdirs)) if external_subdirs else [] + return get_gems_from_subdirectories(get_project_external_subdirectories(project_path)) def get_project_external_subdirectories(project_path: pathlib.Path) -> list: