소스 검색

Simplified the o3de package gem enable/disable logic
The add_gem_project and remove_gem project scripts, now just enables on
a gem name basis instead of a CMake target basis

Updated the ProjectManager code and scripts to account for the
add_gem_project and rmeove_gem_project script changes.

lumberyard-employee-dm 4 년 전
부모
커밋
922099050b

+ 0 - 2
Code/Tools/ProjectManager/Source/PythonBindings.cpp

@@ -591,7 +591,6 @@ namespace O3DE::ProjectManager
             m_addGemProject.attr("add_gem_to_project")(
                 pybind11::none(), // gem_name
                 pyGemPath,
-                pybind11::none(), // gem_target
                 pybind11::none(), // project_name
                 pyProjectPath
                 );
@@ -609,7 +608,6 @@ namespace O3DE::ProjectManager
             m_removeGemProject.attr("remove_gem_from_project")(
                 pybind11::none(), // gem_name
                 pyGemPath,
-                pybind11::none(), // gem_target
                 pybind11::none(), // project_name
                 pyProjectPath
                 );

+ 2 - 2
Gems/TextureAtlas/Code/CMakeLists.txt

@@ -62,10 +62,10 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
                 Gem::TextureAtlas.Static
                 Gem::ImageProcessingAtom.Headers
     )
+    ly_create_alias(NAME TextureAtlas.Builders NAMESPACE Gem TARGETS Gem::TextureAtlas.Editor)
+    ly_create_alias(NAME TextureAtlas.Tools    NAMESPACE Gem TARGETS Gem::TextureAtlas.Editor)
 endif()
 
 ly_create_alias(NAME TextureAtlas.Servers  NAMESPACE Gem TARGETS Gem::TextureAtlas)
 ly_create_alias(NAME TextureAtlas.Clients  NAMESPACE Gem TARGETS Gem::TextureAtlas)
-ly_create_alias(NAME TextureAtlas.Builders NAMESPACE Gem TARGETS Gem::TextureAtlas.Editor)
-ly_create_alias(NAME TextureAtlas.Tools    NAMESPACE Gem TARGETS Gem::TextureAtlas.Editor)
 

+ 71 - 170
scripts/o3de/o3de/add_gem_project.py

@@ -9,7 +9,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #
 """
-Contains command to add a gem to a project's cmake scripts
+Contains command to add a gem to a project's enabled_gem.cmake file
 """
 
 import argparse
@@ -24,55 +24,51 @@ from o3de import cmake, manifest, validation
 logger = logging.getLogger()
 logging.basicConfig()
 
-def add_gem_dependency(cmake_file: str or pathlib.Path,
-                       gem_target: str) -> int:
+def add_gem_dependency(cmake_file: pathlib.Path,
+                       gem_name: str) -> int:
     """
     adds a gem dependency to a cmake file
     :param cmake_file: path to the cmake file
-    :param gem_target: name of the cmake target
+    :param gem_name: name of the gem
     :return: 0 for success or non 0 failure code
     """
-    if not os.path.isfile(cmake_file):
-        logger.error(f'Failed to locate cmake file {cmake_file}')
+    if not cmake_file.is_file():
+        logger.error(f'Failed to locate cmake file {str(cmake_file)}')
         return 1
 
-    # on a line by basis, see if there already is Gem::{gem_name}
+    # on a line by basis, see if there already is {gem_name}
     # find the first occurrence of a gem, copy its formatting and replace
     # the gem name with the new one and append it
     # if the gem is already present fail
     t_data = []
     added = False
+    line_index_to_append = None
     with open(cmake_file, 'r') as s:
+        line_index = 0
         for line in s:
-            if f'Gem::{gem_target}' in line:
-                logger.warning(f'{gem_target} is already a gem dependency.')
+            if 'ENABLED_GEMS' in line:
+                line_index_to_append = line_index
+            if f'{gem_name}' == line.strip():
+                logger.warning(f'{gem_name} is already enabled in file {str(cmake_file)}.')
                 return 0
-            if not added and r'Gem::' in line:
-                new_gem = ' ' * line.find(r'Gem::') + f'Gem::{gem_target}\n'
-                t_data.append(new_gem)
-                added = True
             t_data.append(line)
+            line_index += 1
 
-    # if we didn't add it the set gem dependencies could be empty so
+
+    indent = 4
+    if line_index_to_append:
+        t_data[line_index_to_append] = f'{" "  * indent}{gem_name}\n'
+        added = True
+
+    # if we didn't add, then create a new set(ENABLED_GEMS) variable
     # add a new gem, if empty the correct format is 1 tab=4spaces
-    if not added:
-        index = 0
-        for line in t_data:
-            index = index + 1
-            if r'set(GEM_DEPENDENCIES' in line:
-                t_data.insert(index, f'    Gem::{gem_target}\n')
-                added = True
-                break
-
-    # if we didn't add it then it's not here, add a whole new one
     if not added:
         t_data.append('\n')
-        t_data.append('set(GEM_DEPENDENCIES\n')
-        t_data.append(f'    Gem::{gem_target}\n')
+        t_data.append('set(ENABLED_GEMS\n')
+        t_data.append(f'{" "  * indent}{gem_name}\n')
         t_data.append(')\n')
 
     # write the cmake
-    os.unlink(cmake_file)
     with open(cmake_file, 'w') as s:
         s.writelines(t_data)
 
@@ -80,29 +76,19 @@ def add_gem_dependency(cmake_file: str or pathlib.Path,
 
 
 def add_gem_to_project(gem_name: str = None,
-                       gem_path: str or pathlib.Path = None,
-                       gem_target: str = None,
+                       gem_path: pathlib.Path = None,
                        project_name: str = None,
-                       project_path: str or pathlib.Path = None,
-                       dependencies_file: str or pathlib.Path = None,
-                       runtime_dependency: bool = False,
-                       tool_dependency: bool = False,
-                       server_dependency: bool = False,
-                       platforms: str = 'Common',
-                       add_to_cmake: bool = True) -> int:
+                       project_path: pathlib.Path = None,
+                       enabled_gem_file: pathlib.Path = None,
+                       platforms: str = 'Common') -> int:
     """
     add a gem to a project
     :param gem_name: name of the gem to add
     :param gem_path: path to the gem to add
-    :param gem_target: the name of the cmake gem module
     :param project_name: name of to the project to add the gem to
     :param project_path: path to the project to add the gem to
-    :param dependencies_file: if this dependency goes/is in a specific file
-    :param runtime_dependency: bool to specify this is a runtime gem for the game
-    :param tool_dependency: bool to specify this is a tool gem for the editor
-    :param server_dependency: bool to specify this is a server gem for the server
+    :param enabled_gem_file_file: if this dependency goes/is in a specific file
     :param platforms: str to specify common or which specific platforms
-    :param add_to_cmake: bool to specify that this gem should be added to cmake
     :return: 0 for success or non 0 failure code
     """
     # we need either a project name or path
@@ -113,35 +99,16 @@ def add_gem_to_project(gem_name: str = None,
     # if project name resolve it into a path
     if project_name and not project_path:
         project_path = manifest.get_registered(project_name=project_name)
+    if not project_path:
+        logger.error(f'Unable to locate project path from the registered manifest.json files:'
+                     f' {str(pathlib.Path.home() / ".o3de/manifest.json")}, engine.json')
+        return 1
+
     project_path = pathlib.Path(project_path).resolve()
     if not project_path.is_dir():
         logger.error(f'Project path {project_path} is not a folder.')
         return 1
 
-    # get the engine name this project is associated with
-    # and resolve that engines path
-    project_json = project_path / 'project.json'
-    if not validation.valid_o3de_project_json(project_json):
-        logger.error(f'Project json {project_json} is not valid.')
-        return 1
-    with project_json.open('r') as s:
-        try:
-            project_json_data = json.load(s)
-        except json.JSONDecodeError as e:
-            logger.error(f'Error loading Project json {project_json}: {str(e)}')
-            return 1
-        else:
-            try:
-                engine_name = project_json_data['engine']
-            except KeyError as e:
-                logger.error(f'Project json {project_json} "engine" not found: {str(e)}')
-                return 1
-            else:
-                engine_path = manifest.get_registered(engine_name=engine_name)
-                if not engine_path:
-                    logger.error(f'Engine {engine_name} is not registered.')
-                    return 1
-
     # we need either a gem name or path
     if not gem_name and not gem_path:
         logger.error(f'Must either specify a Gem path or Gem Name.')
@@ -150,94 +117,47 @@ def add_gem_to_project(gem_name: str = None,
     # if gem name resolve it into a path
     if gem_name and not gem_path:
         gem_path = manifest.get_registered(gem_name=gem_name)
+    if not gem_path:
+        logger.error(f'Unable to locate gem path from the registered manifest.json files:'
+                     f' {str(pathlib.Path.home() / ".o3de/manifest.json")},'
+                     f' {project_path / "project.json"}, engine.json')
+        return 1
+
     gem_path = pathlib.Path(gem_path).resolve()
     # make sure this gem already exists if we're adding.  We can always remove a gem.
     if not gem_path.is_dir():
         logger.error(f'Gem Path {gem_path} does not exist.')
         return 1
 
-    # if add to cmake, make sure the gem.json exists and valid before we proceed
-    if add_to_cmake:
-        gem_json = gem_path / 'gem.json'
-        if not gem_json.is_file():
-            logger.error(f'Gem json {gem_json} is not present.')
-            return 1
-        if not validation.valid_o3de_gem_json(gem_json):
-            logger.error(f'Gem json {gem_json} is not valid.')
-            return 1
-
-    # find all available modules in this gem_path
-    modules = cmake.get_gem_targets(gem_path=gem_path)
-    if len(modules) == 0:
-        logger.error(f'No gem modules found under {gem_path}.')
-        return 1
-
-    # if the gem has no modules and the user has specified a target fail
-    if gem_target and not modules:
-        logger.error(f'Gem has no targets, but gem target {gem_target} was specified.')
+    # Read gem.json from the gem path
+    gem_json_data = manifest.get_gem_json_data(gem_path=gem_path)
+    if not gem_json_data:
+        logger.error(f'Could not read gem.json content under {gem_path}.')
         return 1
 
-    # if the gem target is not in the modules
-    if gem_target not in modules:
-        logger.error(f'Gem target not in gem modules: {modules}')
-        return 1
 
-    if gem_target:
-        # if the user has not specified either we will assume they meant the most common which is runtime
-        if not runtime_dependency and not tool_dependency and not server_dependency and not dependencies_file:
-            logger.warning("Dependency type not specified: Assuming '--runtime-dependency'")
-            runtime_dependency = True
-
-        ret_val = 0
-
-        # if the user has specified the dependencies file then ignore the runtime_dependency and tool_dependency flags
-        if dependencies_file:
-            dependencies_file = pathlib.Path(dependencies_file).resolve()
-            # make sure this is a project has a dependencies_file
-            if not dependencies_file.is_file():
-                logger.error(f'Dependencies file {dependencies_file} is not present.')
-                return 1
-            # add the dependency
-            ret_val = add_gem_dependency(dependencies_file, gem_target)
+    ret_val = 0
+    if enabled_gem_file:
+        # make sure this is a project has a dependencies_file
+        if not enabled_gem_file.is_file():
+            logger.error(f'Enabled gem file {enabled_gem_file} is not present.')
+            return 1
+        # add the dependency
+        ret_val = add_gem_dependency(enabled_gem_file, gem_json_data['gem_name'])
 
+    else:
+        if ',' in platforms:
+            platforms = platforms.split(',')
         else:
-            if ',' in platforms:
-                platforms = platforms.split(',')
-            else:
-                platforms = [platforms]
-            for platform in platforms:
-                if runtime_dependency:
-                    # make sure this is a project has a runtime_dependencies.cmake file
-                    project_runtime_dependencies_file = pathlib.Path(
-                        cmake.get_dependencies_cmake_file(project_path=project_path, dependency_type='runtime',
-                                                    platform=platform)).resolve()
-                    if not project_runtime_dependencies_file.is_file():
-                        logger.error(f'Runtime dependencies file {project_runtime_dependencies_file} is not present.')
-                        return 1
-                    # add the dependency
-                    ret_val = add_gem_dependency(project_runtime_dependencies_file, gem_target)
-
-                if (ret_val == 0) and tool_dependency:
-                    # make sure this is a project has a tool_dependencies.cmake file
-                    project_tool_dependencies_file = pathlib.Path(
-                        cmake.get_dependencies_cmake_file(project_path=project_path, dependency_type='tool',
-                                                    platform=platform)).resolve()
-                    if not project_tool_dependencies_file.is_file():
-                        logger.error(f'Tool dependencies file {project_tool_dependencies_file} is not present.')
-                        return 1
-                    # add the dependency
-                    ret_val = add_gem_dependency(project_tool_dependencies_file, gem_target)
-
-                if (ret_val == 0) and server_dependency:
-                    # make sure this is a project has a tool_dependencies.cmake file
-                    project_server_dependencies_file = pathlib.Path(
-                        cmake.get_dependencies_cmake_file(project_path=project_path, dependency_type='server',
-                                                    platform=platform)).resolve()
-                    if not project_server_dependencies_file.is_file():
-                        logger.error(f'Server dependencies file {project_server_dependencies_file} is not present.')
-                        return 1
-                    # add the dependency
-                    ret_val = add_gem_dependency(project_server_dependencies_file, gem_target)
+            platforms = [platforms]
+        for platform in platforms:
+            # Find the path to enabled gem file.
+            # It will be created by add_gem_dependency if it doesn't exist
+            project_enabled_gem_file = cmake.get_enabled_gem_cmake_file(project_path=project_path, platform=platform)
+            if not project_enabled_gem_file.is_file():
+                project_enabled_gem_file.touch()
+            # add the dependency
+            ret_val = add_gem_dependency(project_enabled_gem_file, gem_json_data['gem_name'])
 
     return ret_val
 
@@ -248,15 +168,10 @@ def _run_add_gem_to_project(args: argparse) -> int:
 
     return add_gem_to_project(args.gem_name,
                               args.gem_path,
-                              args.gem_target,
                               args.project_name,
                               args.project_path,
-                              args.dependencies_file,
-                              args.runtime_dependency,
-                              args.tool_dependency,
-                              args.server_dependency,
-                              args.platforms,
-                              args.add_to_cmake)
+                              args.enabled_gem_file,
+                              args.platforms)
 
 
 def add_parser_args(parser):
@@ -267,38 +182,24 @@ def add_parser_args(parser):
     :param parser: the caller passes an argparse parser like instance to this method
     """
     group = parser.add_mutually_exclusive_group(required=True)
-    group.add_argument('-pp', '--project-path', type=str, required=False,
+    group.add_argument('-pp', '--project-path', type=pathlib.Path, required=False,
                        help='The path to the project.')
     group.add_argument('-pn', '--project-name', type=str, required=False,
                        help='The name of the project.')
     group = parser.add_mutually_exclusive_group(required=True)
-    group.add_argument('-gp', '--gem-path', type=str, required=False,
+    group.add_argument('-gp', '--gem-path', type=pathlib.Path, required=False,
                        help='The path to the gem.')
     group.add_argument('-gn', '--gem-name', type=str, required=False,
                        help='The name of the gem.')
-    parser.add_argument('-gt', '--gem-target', type=str, required=False,
-                                   help='The cmake target name to add. If not specified it will assume gem_name')
-    parser.add_argument('-df', '--dependencies-file', type=str, required=False,
-                                   help='The cmake dependencies file in which the gem dependencies are specified.'
-                                        'If not specified it will assume ')
-    parser.add_argument('-rd', '--runtime-dependency', action='store_true', required=False,
-                                   default=False,
-                                   help='Optional toggle if this gem should be added as a runtime dependency')
-    parser.add_argument('-td', '--tool-dependency', action='store_true', required=False,
-                                   default=False,
-                                   help='Optional toggle if this gem should be added as a tool dependency')
-    parser.add_argument('-sd', '--server-dependency', action='store_true', required=False,
-                                   default=False,
-                                   help='Optional toggle if this gem should be added as a server dependency')
+    parser.add_argument('-egf', '--enabled-gem-file', type=pathlib.Path, required=False,
+                                   help='The cmake enabled_gem file in which the gem dependencies are specified.'
+                                        'If not specified it will assume enabled_gems.cmake')
     parser.add_argument('-pl', '--platforms', type=str, required=False,
                                    default='Common',
                                    help='Optional list of platforms this gem should be added to.'
                                         ' Ex. --platforms Mac,Windows,Linux')
-    parser.add_argument('-a', '--add-to-cmake', type=bool, required=False,
-                                   default=True,
-                                   help='Automatically call add-gem-to-cmake.')
 
-    parser.add_argument('-ohf', '--override-home-folder', type=str, required=False,
+    parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False,
                                    help='By default the home folder is the user folder, override it to this folder.')
 
     parser.set_defaults(func=_run_add_gem_to_project)

+ 20 - 166
scripts/o3de/o3de/cmake.py

@@ -21,30 +21,12 @@ from o3de import manifest
 logger = logging.getLogger()
 logging.basicConfig()
 
-def get_project_runtime_gem_targets(project_path: str or pathlib.Path,
+def get_project_gems(project_path: pathlib.Path,
                             platform: str = 'Common') -> set:
-    return get_gem_targets_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='runtime', platform=platform))
+    return get_gems_from_cmake_file(get_enabled_gem_cmake_file(project_path=project_path, platform=platform))
 
 
-def get_project_tool_gem_targets(project_path: str or pathlib.Path,
-                            platform: str = 'Common') -> set:
-    return get_gem_targets_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='tool', platform=platform))
-
-
-def get_project_server_gem_targets(project_path: str or pathlib.Path,
-                            platform: str = 'Common') -> set:
-    return get_gem_targets_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='server', platform=platform))
-
-
-def get_project_gem_targets(project_path: str or pathlib.Path,
-                            platform: str = 'Common') -> set:
-    runtime_gems = get_gem_targets_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='runtime', platform=platform))
-    tool_gems = get_gem_targets_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='tool', platform=platform))
-    server_gems = get_gem_targets_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='server', platform=platform))
-    return runtime_gems.union(tool_gems.union(server_gems))
-
-
-def get_gem_targets_from_cmake_file(cmake_file: str or pathlib.Path) -> set:
+def get_gem_from_cmake_file(cmake_file: pathlib.Path) -> set:
     """
     Gets a list of declared gem targets dependencies of a cmake file
     :param cmake_file: path to the cmake file
@@ -59,102 +41,23 @@ def get_gem_targets_from_cmake_file(cmake_file: str or pathlib.Path) -> set:
     gem_target_set = set()
     with cmake_file.open('r') as s:
         for line in s:
-            gem_name = line.split('Gem::')
-            if len(gem_name) > 1:
-                # Only take the name as everything leading up to the first '.' if found
-                # Gem naming conventions will have GemName.Editor, GemName.Server, and GemName
-                # as different targets of the GemName Gem
-                gem_target_set.add(gem_name[1].replace('\n', ''))
+            gem_name = line.strip()
+            gem_target_set.add(gem_name)
     return gem_target_set
 
 
-def get_project_runtime_gem_names(project_path: str or pathlib.Path,
-                            platform: str = 'Common') -> set:
-    return get_gem_names_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='runtime', platform=platform))
-
-
-def get_project_tool_gem_names(project_path: str or pathlib.Path,
-                            platform: str = 'Common') -> set:
-    return get_gem_names_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='tool', platform=platform))
-
-
-def get_project_server_gem_names(project_path: str or pathlib.Path,
-                            platform: str = 'Common') -> set:
-    return get_gem_names_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='server', platform=platform))
-
-
-def get_project_gem_names(project_path: str or pathlib.Path,
-                     platform: str = 'Common') -> set:
-    runtime_gem_names = get_gem_names_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='runtime', platform=platform))
-    tool_gem_names = get_gem_names_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='tool', platform=platform))
-    server_gem_names = get_gem_names_from_cmake_file(get_dependencies_cmake_file(project_path=project_path, dependency_type='server', platform=platform))
-    return runtime_gem_names.union(tool_gem_names.union(server_gem_names))
-
-
-def get_gem_names_from_cmake_file(cmake_file: str or pathlib.Path) -> set:
-    """
-    Gets a list of declared gem dependencies of a cmake file
-    :param cmake_file: path to the cmake file
-    :return: set of gems found
-    """
-    cmake_file = pathlib.Path(cmake_file).resolve()
-
-    if not cmake_file.is_file():
-        logger.error(f'Failed to locate cmake file {cmake_file}')
-        return set()
-
-    gem_set = set()
-    with cmake_file.open('r') as s:
-        for line in s:
-            gem_name = line.split('Gem::')
-            if len(gem_name) > 1:
-                # Only take the name as everything leading up to the first '.' if found
-                # Gem naming conventions will have GemName.Editor, GemName.Server, and GemName
-                # as different targets of the GemName Gem
-                gem_set.add(gem_name[1].split('.')[0].replace('\n', ''))
-    return gem_set
-
-
-def get_project_runtime_gem_paths(project_path: str or pathlib.Path,
+def get_project_gem_paths(project_path:  pathlib.Path,
                           platform: str = 'Common') -> set:
-    gem_names = get_project_runtime_gem_names(project_path, platform)
+    gem_names = get_project_gems(project_path, platform)
     gem_paths = set()
     for gem_name in gem_names:
         gem_paths.add(manifest.get_registered(gem_name=gem_name))
     return gem_paths
 
 
-def get_project_tool_gem_paths(project_path: str or pathlib.Path,
-                          platform: str = 'Common') -> set:
-    gem_names = get_project_tool_gem_names(project_path, platform)
-    gem_paths = set()
-    for gem_name in gem_names:
-        gem_paths.add(manifest.get_registered(gem_name=gem_name))
-    return gem_paths
-
-
-def get_project_server_gem_paths(project_path: str or pathlib.Path,
-                          platform: str = 'Common') -> set:
-    gem_names = get_project_server_gem_names(project_path, platform)
-    gem_paths = set()
-    for gem_name in gem_names:
-        gem_paths.add(manifest.get_registered(gem_name=gem_name))
-    return gem_paths
-
-
-def get_project_gem_paths(project_path: str or pathlib.Path,
-                          platform: str = 'Common') -> set:
-    gem_names = get_project_gem_names(project_path, platform)
-    gem_paths = set()
-    for gem_name in gem_names:
-        gem_paths.add(manifest.get_registered(gem_name=gem_name))
-    return gem_paths
-
-
-def get_dependencies_cmake_file(project_name: str = None,
+def get_enabled_gem_cmake_file(project_name: str = None,
                                 project_path: str or pathlib.Path = None,
-                                dependency_type: str = 'runtime',
-                                platform: str = 'Common') -> str or None:
+                                platform: str = 'Common') -> pathlib.Path or None:
     """
     get the standard cmake file name for a particular type of dependency
     :param gem_name: name of the gem, resolves gem_path
@@ -169,66 +72,17 @@ def get_dependencies_cmake_file(project_name: str = None,
         project_path = manifest.get_registered(project_name=project_name)
 
     project_path = pathlib.Path(project_path).resolve()
+    enable_gem_filename = "enabled_gem.cmake"
 
     if platform == 'Common':
-        dependencies_file = f'{dependency_type}_dependencies.cmake'
-        dependencies_file_path = project_path / 'Gem/Code' / dependencies_file
-        if dependencies_file_path.is_file():
-            return dependencies_file_path
-        return project_path / 'Code' / dependencies_file
+        project_code_dir = project_path / 'Gem/Code'
+        if project_code_dir.is_dir():
+            dependencies_file_path = project_code_dir / enable_gem_filename
+            return dependencies_file_path.resolve()
+        return (project_path / 'Code' / enable_gem_filename).resolve()
     else:
-        dependencies_file = f'{platform.lower()}_{dependency_type}_dependencies.cmake'
-        dependencies_file_path = project_path / 'Gem/Code/Platform' / platform / dependencies_file
-        if dependencies_file_path.is_file():
-            return dependencies_file_path
-        return project_path / 'Code/Platform' / platform / dependencies_file
-
-
-def get_all_gem_targets() -> list:
-    modules = []
-    for gem_path in manifest.get_all_gems():
-        this_gems_targets = get_gem_targets(gem_path=gem_path)
-        modules.extend(this_gems_targets)
-    return modules
-
-
-def get_gem_targets(gem_name: str = None,
-                    gem_path: str or pathlib.Path = None) -> list:
-    """
-    Finds gem targets in a gem
-    :param gem_name: name of the gem, resolves gem_path
-    :param gem_path: path of the gem
-    :return: list of gem targets
-    """
-    if not gem_name and not gem_path:
-        return []
-
-    if gem_name and not gem_path:
-        gem_path = manifest.get_registered(gem_name=gem_name)
-
-    if not gem_path:
-        return []
-
-    gem_path = pathlib.Path(gem_path).resolve()
-    gem_json = gem_path / 'gem.json'
-    if not validation.valid_o3de_gem_json(gem_json):
-        return []
-
-    module_identifiers = [
-        'MODULE',
-        'GEM_MODULE',
-        '${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE}'
-    ]
-    modules = []
-    for root, dirs, files in os.walk(gem_path):
-        for file in files:
-            if file == 'CMakeLists.txt':
-                with open(os.path.join(root, file), 'r') as s:
-                    for line in s:
-                        trimmed = line.lstrip()
-                        if trimmed.startswith('NAME '):
-                            trimmed = trimmed.rstrip(' \n')
-                            split_trimmed = trimmed.split(' ')
-                            if len(split_trimmed) == 3 and split_trimmed[2] in module_identifiers:
-                                modules.append(split_trimmed[1])
-    return modules
+        project_code_dir = project_path / 'Gem/Code/Platform' / platform
+        if project_code_dir.is_dir():
+            dependencies_file_path = project_code_dir / enable_gem_filename
+            return dependencies_file_path.resolve()
+        return (project_path / 'Code/Platform' / platform / enable_gem_filename).resolve()

+ 1 - 3
scripts/o3de/o3de/manifest.py

@@ -574,9 +574,7 @@ def get_registered(engine_name: str = None,
                         return project_path
 
     elif isinstance(gem_name, str):
-        engine_gems = get_engine_gems()
-        gems = json_data['gems'].copy()
-        gems.extend(engine_gems)
+        gems = get_all_gems()
         for gem_path in gems:
             gem_path = pathlib.Path(gem_path).resolve()
             gem_json = gem_path / 'gem.json'

+ 52 - 115
scripts/o3de/o3de/remove_gem_project.py

@@ -9,7 +9,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #
 """
-Contains methods for removing a gem target from a project
+Contains methods for removing a gem from a project
 """
 
 import argparse
@@ -18,41 +18,40 @@ import os
 import pathlib
 import sys
 
-from o3de import cmake
+from o3de import cmake, manifest
 
 logger = logging.getLogger()
 logging.basicConfig()
 
 
-def remove_gem_dependency(cmake_file: str or pathlib.Path,
-                          gem_target: str) -> int:
+def remove_gem_dependency(cmake_file: pathlib.Path,
+                          gem_name: str) -> int:
     """
     removes a gem dependency from a cmake file
     :param cmake_file: path to the cmake file
-    :param gem_target: cmake target name
+    :param gem_name: name of the gem
     :return: 0 for success or non 0 failure code
     """
-    if not os.path.isfile(cmake_file):
+    if not cmake_file.is_file():
         logger.error(f'Failed to locate cmake file {cmake_file}')
         return 1
 
-    # on a line by basis, remove any line with Gem::{gem_name}
+    # on a line by basis, remove any line with {gem_name}
     t_data = []
-    # Remove the gem from the cmake_dependencies file by skipping the gem name entry
+    # Remove the gem from the enabled_gem file by skipping the gem name entry
     removed = False
     with open(cmake_file, 'r') as s:
         for line in s:
-            if f'Gem::{gem_target}' in line:
+            if gem_name == line.strip():
                 removed = True
             else:
                 t_data.append(line)
 
     if not removed:
-        logger.error(f'Failed to remove Gem::{gem_target} from cmake file {cmake_file}')
+        logger.error(f'Failed to remove {gem_name} from cmake file {cmake_file}')
         return 1
 
     # write the cmake
-    os.unlink(cmake_file)
     with open(cmake_file, 'w') as s:
         s.writelines(t_data)
 
@@ -60,29 +59,19 @@ def remove_gem_dependency(cmake_file: str or pathlib.Path,
 
 
 def remove_gem_from_project(gem_name: str = None,
-                            gem_path: str or pathlib.Path = None,
-                            gem_target: str = None,
+                            gem_path: pathlib.Path = None,
                             project_name: str = None,
-                            project_path: str or pathlib.Path = None,
-                            dependencies_file: str or pathlib.Path = None,
-                            runtime_dependency: bool = False,
-                            tool_dependency: bool = False,
-                            server_dependency: bool = False,
-                            platforms: str = 'Common',
-                            remove_from_cmake: bool = False) -> int:
+                            project_path: pathlib.Path = None,
+                            enabled_gem_file: pathlib.Path = None,
+                            platforms: str = 'Common') -> int:
     """
     remove a gem from a project
     :param gem_name: name of the gem to add
     :param gem_path: path to the gem to add
-    :param gem_target: the name of teh cmake gem module
     :param project_name: name of the project to add the gem to
     :param project_path: path to the project to add the gem to
-    :param dependencies_file: if this dependency goes/is in a specific file
-    :param runtime_dependency: bool to specify this is a runtime gem for the game
-    :param tool_dependency: bool to specify this is a tool gem for the editor
-    :param server_dependency: bool to specify this is a server gem for the server
+    :param enabled_gem_file: File to remove enabled gem from
     :param platforms: str to specify common or which specific platforms
-    :param remove_from_cmake: bool to specify that this gem should be removed from cmake
     :return: 0 for success or non 0 failure code
     """
 
@@ -94,6 +83,11 @@ def remove_gem_from_project(gem_name: str = None,
     # if project name resolve it into a path
     if project_name and not project_path:
         project_path = manifest.get_registered(project_name=project_name)
+    if not project_path:
+        logger.error(f'Unable to locate project path from the registered manifest.json files:'
+                     f' {str(pathlib.Path.home() / ".o3de/manifest.json")}, engine.json')
+        return 1
+
     project_path = pathlib.Path(project_path).resolve()
     if not project_path.is_dir():
         logger.error(f'Project path {project_path} is not a folder.')
@@ -107,48 +101,35 @@ def remove_gem_from_project(gem_name: str = None,
     # if gem name resolve it into a path
     if gem_name and not gem_path:
         gem_path = manifest.get_registered(gem_name=gem_name)
+    if not gem_path:
+        logger.error(f'Unable to locate gem path from the registered manifest.json files:'
+                     f' {str(pathlib.Path.home() / ".o3de/manifest.json")},'
+                     f' {project_path / "project.json"}, engine.json')
+        return 1
     gem_path = pathlib.Path(gem_path).resolve()
     # make sure this gem already exists if we're adding.  We can always remove a gem.
     if not gem_path.is_dir():
         logger.error(f'Gem Path {gem_path} does not exist.')
         return 1
 
-    # find all available modules in this gem_path
-    modules = cmake.get_gem_targets(gem_path=gem_path)
-    if len(modules) == 0:
-        logger.error(f'No gem modules found.')
-        return 1
-
-    # if the user has not set a specific gem target remove all of them
 
-    # if gem target not specified, see if there is only 1 module
-    if not gem_target:
-        if len(modules) == 1:
-            gem_target = modules[0]
-        else:
-            logger.error(f'Gem target not specified: {modules}')
-            return 1
-    elif gem_target not in modules:
-        logger.error(f'Gem target not in gem modules: {modules}')
+    # Read gem.json from the gem path
+    gem_json_data = manifest.get_gem_json_data(gem_path=gem_path)
+    if not gem_json_data:
+        logger.error(f'Could not read gem.json content under {gem_path}.')
         return 1
 
-    # if the user has not specified either we will assume they meant the most common which is runtime
-    if not runtime_dependency and not tool_dependency and not server_dependency and not dependencies_file:
-        logger.warning("Dependency type not specified: Assuming '--runtime-dependency'")
-        runtime_dependency = True
-
     # when removing we will try to do as much as possible even with failures so ret_val will be the last error code
     ret_val = 0
 
     # if the user has specified the dependencies file then ignore the runtime_dependency and tool_dependency flags
-    if dependencies_file:
-        dependencies_file = pathlib.Path(dependencies_file).resolve()
-        # make sure this is a project has a dependencies_file
-        if not dependencies_file.is_file():
-            logger.error(f'Dependencies file {dependencies_file} is not present.')
+    if enabled_gem_file:
+        # make sure this is a project has an enabled_gem file
+        if not enabled_gem_file.is_file():
+            logger.error(f'Enabled gem file {enabled_gem_file} is not present.')
             return 1
         # remove the dependency
-        error_code = remove_gem_dependency(dependencies_file, gem_target)
+        error_code = remove_gem_dependency(dependencies_file, gem_json_data['gem_name'])
         if error_code:
             ret_val = error_code
     else:
@@ -157,44 +138,16 @@ def remove_gem_from_project(gem_name: str = None,
         else:
             platforms = [platforms]
         for platform in platforms:
-            if runtime_dependency:
-                # make sure this is a project has a runtime_dependencies.cmake file
-                project_runtime_dependencies_file = pathlib.Path(
-                    cmake.get_dependencies_cmake_file(project_path=project_path, dependency_type='runtime',
-                                                platform=platform)).resolve()
-                if not project_runtime_dependencies_file.is_file():
-                    logger.error(f'Runtime dependencies file {project_runtime_dependencies_file} is not present.')
-                else:
-                    # remove the dependency
-                    error_code = remove_gem_dependency(project_runtime_dependencies_file, gem_target)
-                    if error_code:
-                        ret_val = error_code
-
-            if tool_dependency:
-                # make sure this is a project has a tool_dependencies.cmake file
-                project_tool_dependencies_file = pathlib.Path(
-                    cmake.get_dependencies_cmake_file(project_path=project_path, dependency_type='tool',
-                                                platform=platform)).resolve()
-                if not project_tool_dependencies_file.is_file():
-                    logger.error(f'Tool dependencies file {project_tool_dependencies_file} is not present.')
-                else:
-                    # remove the dependency
-                    error_code = remove_gem_dependency(project_tool_dependencies_file, gem_target)
-                    if error_code:
-                        ret_val = error_code
-
-            if server_dependency:
-                # make sure this is a project has a tool_dependencies.cmake file
-                project_server_dependencies_file = pathlib.Path(
-                    cmake.get_dependencies_cmake_file(project_path=project_path, dependency_type='server',
-                                                platform=platform)).resolve()
-                if not project_server_dependencies_file.is_file():
-                    logger.error(f'Server dependencies file {project_server_dependencies_file} is not present.')
-                else:
-                    # remove the dependency
-                    error_code = remove_gem_dependency(project_server_dependencies_file, gem_target)
-                    if error_code:
-                        ret_val = error_code
+                # make sure this is a project has a enabled_gem.cmake file
+            project_enabled_gem_file = cmake.get_enabled_gem_cmake_file(project_path=project_path, platform=platform)
+            if not project_enabled_gem_file.is_file():
+                logger.error(f'Enabled gem file {project_enabled_gem_file} is not present.')
+            else:
+                # remove the dependency
+                error_code = remove_gem_dependency(project_enabled_gem_file, gem_json_data['gem_name'])
+                if error_code:
+                    ret_val = error_code
+
 
     return ret_val
 
@@ -205,15 +158,10 @@ def _run_remove_gem_from_project(args: argparse) -> int:
 
     return remove_gem_from_project(args.gem_name,
                                    args.gem_path,
-                                   args.gem_target,
-                                   args.project_path,
                                    args.project_name,
-                                   args.dependencies_file,
-                                   args.runtime_dependency,
-                                   args.tool_dependency,
-                                   args.server_dependency,
-                                   args.platforms,
-                                   args.remove_from_cmake)
+                                   args.project_path,
+                                   args.enabled_gem_file,
+                                   args.platforms)
 
 
 def add_parser_args(parser):
@@ -224,35 +172,24 @@ def add_parser_args(parser):
     :param parser: the caller passes an argparse parser like instance to this method
     """
     group = parser.add_mutually_exclusive_group(required=True)
-    group.add_argument('-pp', '--project-path', type=str, required=False,
+    group.add_argument('-pp', '--project-path', type=pathlib.Path, required=False,
                        help='The path to the project.')
     group.add_argument('-pn', '--project-name', type=str, required=False,
                        help='The name of the project.')
     group = parser.add_mutually_exclusive_group(required=True)
-    group.add_argument('-gp', '--gem-path', type=str, required=False,
+    group.add_argument('-gp', '--gem-path', type=pathlib.Path, required=False,
                        help='The path to the gem.')
     group.add_argument('-gn', '--gem-name', type=str, required=False,
                        help='The name of the gem.')
-    parser.add_argument('-gt', '--gem-target', type=str, required=False,
-                                      help='The cmake target name to add. If not specified it will assume gem_name')
-    parser.add_argument('-df', '--dependencies-file', type=str, required=False,
-                                      help='The cmake dependencies file in which the gem dependencies are specified.'
+    parser.add_argument('-egf', '--enabled-gem-file', type=pathlib.Path, required=False,
+                                      help='The cmake enabled gem file in which gem dependencies are to be removed from.'
                                            'If not specified it will assume ')
-    parser.add_argument('-rd', '--runtime-dependency', action='store_true', required=False,
-                                      default=False,
-                                      help='Optional toggle if this gem should be removed as a runtime dependency')
-    parser.add_argument('-td', '--tool-dependency', action='store_true', required=False,
-                                      default=False,
-                                      help='Optional toggle if this gem should be removed as a server dependency')
-    parser.add_argument('-sd', '--server-dependency', action='store_true', required=False,
-                                      default=False,
-                                      help='Optional toggle if this gem should be removed as a server dependency')
     parser.add_argument('-pl', '--platforms', type=str, required=False,
                                       default='Common',
                                       help='Optional list of platforms this gem should be removed from'
                                            ' Ex. --platforms Mac,Windows,Linux')
 
-    parser.add_argument('-ohf', '--override-home-folder', type=str, required=False,
+    parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False,
                                       help='By default the home folder is the user folder, override it to this folder.')
 
     parser.set_defaults(func=_run_remove_gem_from_project)

+ 17 - 135
scripts/project_manager/projects.py

@@ -766,167 +766,49 @@ class ProjectManagerDialog(QObject):
         selected_items = self.enabled_gem_targets_list.selectionModel().selectedRows()
         return [(self.enabled_gem_targets_list.model().data(item)) for item in selected_items]
 
-    def add_runtime_project_gem_targets_handler(self) -> None:
+    def add_project_gem_targets_handler(self) -> None:
         gem_paths = manifest.get_all_gems()
         for gem_target in self.manage_project_gem_targets_get_selected_available_gems():
             for gem_path in gem_paths:
-                this_gems_targets = cmake.get_gem_targets(gem_path=gem_path)
-                for this_gem_target in this_gems_targets:
-                    if gem_target == this_gem_target:
-                        add_gem_project.add_gem_to_project(gem_path=gem_path,
-                                                        gem_target=gem_target,
-                                                        project_path=self.get_selected_project_path(),
-                                                        runtime_dependency=True)
-                        self.refresh_runtime_project_gem_targets_available_list()
-                        self.refresh_runtime_project_gem_targets_enabled_list()
-                        return
+                add_gem_project.add_gem_to_project(gem_path=gem_path,
+                                                   project_path=self.get_selected_project_path())
+                self.refresh_runtime_project_gem_targets_available_list()
+                self.refresh_runtime_project_gem_targets_enabled_list()
+                return
         self.refresh_runtime_project_gem_targets_available_list()
         self.refresh_runtime_project_gem_targets_enabled_list()
 
-    def remove_runtime_project_gem_targets_handler(self):
+    def remove_project_gem_targets_handler(self):
         gem_paths = manifest.get_all_gems()
         for gem_target in self.manage_project_gem_targets_get_selected_enabled_gems():
             for gem_path in gem_paths:
-                this_gems_targets = cmake.get_gem_targets(gem_path=gem_path)
-                for this_gem_target in this_gems_targets:
-                    if gem_target == this_gem_target:
-                        remove_gem_project.remove_gem_from_project(gem_path=gem_path,
-                                                             gem_target=gem_target,
-                                                             project_path=self.get_selected_project_path(),
-                                                             runtime_dependency=True)
-                        self.refresh_runtime_project_gem_targets_available_list()
-                        self.refresh_runtime_project_gem_targets_enabled_list()
-                        return
+                remove_gem_project.remove_gem_from_project(gem_path=gem_path,
+                                                           project_path=self.get_selected_project_path())
+                self.refresh_runtime_project_gem_targets_available_list()
+                self.refresh_runtime_project_gem_targets_enabled_list()
+                return
         self.refresh_runtime_project_gem_targets_available_list()
         self.refresh_runtime_project_gem_targets_enabled_list()
 
-    def add_tool_project_gem_targets_handler(self) -> None:
-        gem_paths = manifest.get_all_gems()
-        for gem_target in self.manage_project_gem_targets_get_selected_available_gems():
-            for gem_path in gem_paths:
-                this_gems_targets = cmake.get_gem_targets(gem_path=gem_path)
-                for this_gem_target in this_gems_targets:
-                    if gem_target == this_gem_target:
-                        add_gem_project.add_gem_to_project(gem_path=gem_path,
-                                                        gem_target=gem_target,
-                                                        project_path=self.get_selected_project_path(),
-                                                        tool_dependency=True)
-                        self.refresh_tool_project_gem_targets_available_list()
-                        self.refresh_tool_project_gem_targets_enabled_list()
-                        return
-        self.refresh_tool_project_gem_targets_available_list()
-        self.refresh_tool_project_gem_targets_enabled_list()
-
-    def remove_tool_project_gem_targets_handler(self):
-        gem_paths = manifest.get_all_gems()
-        for gem_target in self.manage_project_gem_targets_get_selected_enabled_gems():
-            for gem_path in gem_paths:
-                this_gems_targets = cmake.get_gem_targets(gem_path=gem_path)
-                for this_gem_target in this_gems_targets:
-                    if gem_target == this_gem_target:
-                        remove_gem_project.remove_gem_from_project(gem_path=gem_path,
-                                                             gem_target=gem_target,
-                                                             project_path=self.get_selected_project_path(),
-                                                             tool_dependency=True)
-                        self.refresh_tool_project_gem_targets_available_list()
-                        self.refresh_tool_project_gem_targets_enabled_list()
-                        return
-        self.refresh_tool_project_gem_targets_available_list()
-        self.refresh_tool_project_gem_targets_enabled_list()
-        
-    def add_server_project_gem_targets_handler(self) -> None:
-        gem_paths = manifest.get_all_gems()
-        for gem_target in self.manage_project_gem_targets_get_selected_available_gems():
-            for gem_path in gem_paths:
-                this_gems_targets = cmake.get_gem_targets(gem_path=gem_path)
-                for this_gem_target in this_gems_targets:
-                    if gem_target == this_gem_target:
-                        add_gem_project.add_gem_to_project(gem_path=gem_path,
-                                                        gem_target=gem_target,
-                                                        project_path=self.get_selected_project_path(),
-                                                        server_dependency=True)
-                        self.refresh_server_project_gem_targets_available_list()
-                        self.refresh_server_project_gem_targets_enabled_list()
-                        return
-        self.refresh_server_project_gem_targets_available_list()
-        self.refresh_server_project_gem_targets_enabled_list()
-
-    def remove_server_project_gem_targets_handler(self):
-        gem_paths = manifest.get_all_gems()
-        for gem_target in self.manage_project_gem_targets_get_selected_enabled_gems():
-            for gem_path in gem_paths:
-                this_gems_targets = cmake.get_gem_targets(gem_path=gem_path)
-                for this_gem_target in this_gems_targets:
-                    if gem_target == this_gem_target:
-                        remove_gem_project.remove_gem_from_project(gem_path=gem_path,
-                                                             gem_target=gem_target,
-                                                             project_path=self.get_selected_project_path(),
-                                                             server_dependency=True)
-                        self.refresh_server_project_gem_targets_available_list()
-                        self.refresh_server_project_gem_targets_enabled_list()
-                        return
-        self.refresh_server_project_gem_targets_available_list()
-        self.refresh_server_project_gem_targets_enabled_list()
-
     def refresh_runtime_project_gem_targets_enabled_list(self) -> None:
         enabled_project_gem_targets_model = QStandardItemModel()
-        enabled_project_gem_targets = cmake.get_project_runtime_gem_targets(
-            project_path=self.get_selected_project_path())
-        for gem_target in sorted(enabled_project_gem_targets):
+        enabled_project_gems = cmake.get_project_gems(project_path=self.get_selected_project_path())
+        for gem_target in sorted(enabled_project_gems):
             model_item = QStandardItem(gem_target)
             enabled_project_gem_targets_model.appendRow(model_item)
         self.enabled_gem_targets_list.setModel(enabled_project_gem_targets_model)
 
-    def refresh_runtime_project_gem_targets_available_list(self) -> None:
-        available_project_gem_targets_model = QStandardItemModel()
-        enabled_project_gem_targets = cmake.get_project_runtime_gem_targets(
-            project_path=self.get_selected_project_path())
-        all_gem_targets = cmake.get_all_gem_targets()
-        for gem_target in sorted(all_gem_targets):
-            if gem_target not in enabled_project_gem_targets:
-                model_item = QStandardItem(gem_target)
-                available_project_gem_targets_model.appendRow(model_item)
-        self.available_gem_targets_list.setModel(available_project_gem_targets_model)
-        
-    def refresh_tool_project_gem_targets_enabled_list(self) -> None:
-        enabled_project_gem_targets_model = QStandardItemModel()
-        enabled_project_gem_targets = cmake.get_project_tool_gem_targets(
-            project_path=self.get_selected_project_path())
-        for gem_target in sorted(enabled_project_gem_targets):
-            model_item = QStandardItem(gem_target)
-            enabled_project_gem_targets_model.appendRow(model_item)
-        self.enabled_gem_targets_list.setModel(enabled_project_gem_targets_model)
 
-    def refresh_tool_project_gem_targets_available_list(self) -> None:
+    def refresh_runtime_project_gem_targets_available_list(self) -> None:
         available_project_gem_targets_model = QStandardItemModel()
-        enabled_project_gem_targets = cmake.get_project_tool_gem_targets(
-            project_path=self.get_selected_project_path())
-        all_gem_targets = cmake.get_all_gem_targets()
+        enabled_project_gem_targets = cmake.get_project_gems(project_path=self.get_selected_project_path())
+        all_gem_targets = manifest.get_all_gems()
         for gem_target in sorted(all_gem_targets):
             if gem_target not in enabled_project_gem_targets:
                 model_item = QStandardItem(gem_target)
                 available_project_gem_targets_model.appendRow(model_item)
         self.available_gem_targets_list.setModel(available_project_gem_targets_model)
-        
-    def refresh_server_project_gem_targets_enabled_list(self) -> None:
-        enabled_project_gem_targets_model = QStandardItemModel()
-        enabled_project_gem_targets = cmake.get_project_server_gem_targets(
-            project_path=self.get_selected_project_path())
-        for gem_target in sorted(enabled_project_gem_targets):
-            model_item = QStandardItem(gem_target)
-            enabled_project_gem_targets_model.appendRow(model_item)
-        self.enabled_gem_targets_list.setModel(enabled_project_gem_targets_model)
 
-    def refresh_server_project_gem_targets_available_list(self) -> None:
-        available_project_gem_targets_model = QStandardItemModel()
-        enabled_project_gem_targets = cmake.get_project_server_gem_targets(
-            project_path=self.get_selected_project_path())
-        all_gem_targets = cmake.get_all_gem_targets()
-        for gem_target in sorted(all_gem_targets):
-            if gem_target not in enabled_project_gem_targets:
-                model_item = QStandardItem(gem_target)
-                available_project_gem_targets_model.appendRow(model_item)
-        self.available_gem_targets_list.setModel(available_project_gem_targets_model)
 
     def refresh_create_project_template_list(self) -> None:
         self.create_project_template_model = QStandardItemModel()