From 922099050b319c387e6fc5097a99f2bc31c9681c Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Wed, 26 May 2021 04:46:16 -0500 Subject: [PATCH] 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. --- .../ProjectManager/Source/PythonBindings.cpp | 2 - Gems/TextureAtlas/Code/CMakeLists.txt | 4 +- scripts/o3de/o3de/add_gem_project.py | 241 ++++++------------ scripts/o3de/o3de/cmake.py | 186 ++------------ scripts/o3de/o3de/manifest.py | 4 +- scripts/o3de/o3de/remove_gem_project.py | 167 ++++-------- scripts/project_manager/projects.py | 152 ++--------- 7 files changed, 163 insertions(+), 593 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index efec83bc39..c1e62f9c04 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/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 ); diff --git a/Gems/TextureAtlas/Code/CMakeLists.txt b/Gems/TextureAtlas/Code/CMakeLists.txt index 45b9549d10..d67601235d 100644 --- a/Gems/TextureAtlas/Code/CMakeLists.txt +++ b/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) diff --git a/scripts/o3de/o3de/add_gem_project.py b/scripts/o3de/o3de/add_gem_project.py index 8eb1468485..42db0a97bd 100644 --- a/scripts/o3de/o3de/add_gem_project.py +++ b/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) diff --git a/scripts/o3de/o3de/cmake.py b/scripts/o3de/o3de/cmake.py index 7e95a9c2fe..eb8e3957ad 100644 --- a/scripts/o3de/o3de/cmake.py +++ b/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() diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index 241f6ecbee..c3b327641c 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/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' diff --git a/scripts/o3de/o3de/remove_gem_project.py b/scripts/o3de/o3de/remove_gem_project.py index 463cc69961..72c51f0e2c 100644 --- a/scripts/o3de/o3de/remove_gem_project.py +++ b/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) diff --git a/scripts/project_manager/projects.py b/scripts/project_manager/projects.py index 704b7c5f9a..71d0d11b2c 100755 --- a/scripts/project_manager/projects.py +++ b/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()