o3de / sig-content

8 stars 12 forks source link

Proposed RFC Feature: Project Export CLI Framework #123

Closed tkothadev closed 1 year ago

tkothadev commented 1 year ago

Summary:

O3DE users don't have a straight-forward, accessible and customizable way to export their projects for release. This can make the process of preparing release packages of projects time consuming and error prone. This RFC proposes a new O3DE command line interface sub-command called export-project that simplifies the process by automating that work. The command is also setup to run custom Python scripts.

What is the relevance of this feature?

The current process in O3DE for creating and then exporting a project to share with others takes a minimum of 12 steps. O3DE users routinely struggle to find and follow these steps. A common piece of feedback from O3DE evaluators is the difficulty in sharing their work with others.

These 12 steps are outlined in the Example Usage section of the RFC. That section also demonstrates how the export-project command reduces the steps down to 5.

This RFC focuses on improving the following use cases for exporting:

It is also possible that a larger game development team requires their own build and deployment process. export-project should be flexible such that they are able to incorporate their requirements into the process. Some examples of this are:

When complete, a new CLI will be available that can be used to setup and automate the build steps for the project, and automate most of the repetitive tasks of building the project. This CLI can act as stepping stone to integrate a project export UI accessible from Project Manager, making the process easier for newcomers to the engine.

Feature design description:

Terminology

Command Overview

An export-project O3DE CLI command is added which runs an export script. Such a script can automate building, processing assets, bundling, and copying to an output folder. For export scripts provided with O3DE, these scripts will create the necessary release directory structure for each platform, but will not create archives nor deploy to external devices or services. That will be left to users to extend as needed.

export-project is a sub-command via o3de.bat or o3de.py because the task of exporting projects is logically grouped with other project related commands found in the CLI, benefiting from discoverability. It also helps with parameter management: o3de.py is setup to be aware of things like the engine folder.

export-project's main priority is a correct release directory structure. Archiving and deploying to devices and services will likely be separate CLI tools and are not covered here.

Example Usage

Suppose a game studio wants to make a game like Newspaper Delivery Game. That project has only 2 scenes, a main menu, and a game scene. It has one player character asset, a few models, such as cars, houses, trees, and roads, and 1 level file.

Before RFC Changes

As of January/February 2023 to get such a project ready for release with a standalone Game Launcher only, the user must manually do the following:

  1. Create the project, populate it with content and author the code to drive the project's logic.
  2. Build profile non-monolithic Editor & tools for the Host platform.
  3. Process assets for the project with the profile Asset Processor (GUI or Batch) for the Target platform.
  4. Generate or update seedlists if required (for more info see this article on the asset bundler).
  5. Bundle assets using seedlists for the project with the profile Asset Bundler (GUI or Batch).
  6. Build release monolithic game project launcher for the Target platform.
  7. Create the release layout folder directory.
  8. Place binaries in the directory layout.
  9. Place asset bundles in the directory layout.
  10. Place auxiliary files in the directory layout.
  11. Use an external archiving tool to create a zip file.
  12. Put the zipped archive on itch.io to share it with people who want to play their game jam game.
After RFC Changes

With the export-project command, the user would only need to do the following:

  1. Create the project, populate it with content and author the code to drive the project's logic
  2. Run an o3de project export command for a standalone monolithic release Windows build:
    cd <O3DE_INSTALL_DIR>
    scripts\o3de.bat export-project --export-script C:\workspace\projects\NewspaperDeliveryGame\ExportScripts\export_standalone_monolithic.py
  3. Get this release layout output image
  4. Use an external archiving tool to create a zip file.
  5. Put the zipped archive on itch.io to share it with people who want to play their game jam game.

Between both approaches, these steps remain the same:

Technical design description:

Parameters

The initial list of parameters for this iteration of the export-project command are:

These arguments are optional from the user's perspective but required for processing the export script, and export-project will attempt to infer a value if one is not given If not given, then a default is generated For any optional argument using nargs , this means that a list of arguments for a given toolchain (like CMake) can be passed along to the appropriate stage in the pipeline.

At a high level, the export_project.py script imports the export script via importlib as a module to execute, and adjusts the system path to include the O3DE CLI and the script's local directory. It also processes CLI arguments, and stores them in an o3de_export object which is accessible to the user by appropriate APIs.

Export Scripts

The end result of exporting a project will consist of a directory layout of game binaries and packaged game content (asset bundles). A project ready for release is this folder directory placed into the exporting structure used for the intended release method (IPA for iOS, APK for Android, etc). Further processing can be handled by users.

In order to use the project export tools, the user supplies an export script file. Helper APIs and CLI parameters are accessible to the user, with no setup code required.

To make this easier, this RFC proposes providing standard scripts, which both provide default engine export functionality, and reference code for users to adapt to their own needs. Export scripts in projects can be defined in the <project-root>/ExportScripts directory.

Similar to the My Documents folder on Windows, the ExportScripts folder is not strictly required for users, and they can place the scripts wherever they wish, but it comes with some conveniences. For instance, The Asset Processor should be provided an exclusion rule to not look at files in <project-root>/ExportScripts. For O3DE project templates, example scripts are placed in the ExportScripts directory, and it should be treated as common convention.

The following examples focus on use case 1 (Standalone release builds for windows specifically):

User scripts can import the export API regardless of folder location

import o3de.export_project as exp

User scripts can also access o3de default variables that are available before the script is run via o3de_export

exp.export_standalone_monolithic(platform= "Windows", build_mode = o3de_export.build_mode, project_path= o3de_export.project_path, engine_path = o3de_export.engine_path)

- This is an example of a slightly complex export script for standalone monolithic builds (useful for teams that need to tweak the build process):
```python
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
import sys
import os

# User scripts can import the export API regardless of folder location
import o3de.export_project as exp

# User scripts can also access o3de default variables that are available before the script is run, via o3de_export
# o3de_export stores all CLI arguments passed in to the export_project command

# This is currently needed to access necessary O3DE toolchain for rest of the export process
exp.build_engine_tools(cwd = o3de_export.engine_path, compiler = o3de_export.args.compiler)

exp.process_assets(platform = "pc", project_path = o3de_export.project_path)

exp.bundle_assets(seedlist = o3de_export.seedlist)

exp.prepare_project(cmake_build_mode = o3de_export.build_mode ,cmake_gen = o3de_export.args.cmake_gen, is_monolithic = True, third_party_path = o3de_export.third_party_path)

exp.build_project(target = "install", config = o3de_export.build_mode, build = "build\\mono")

exp.copy_release_dir(dest= o3de_export.output_path)

Helper API

Currently all API functions should reside in export_project.py.

This RFC proposes a hierarchical approach to API design, where larger composite functions are composed of smaller granular functions, but both kinds are available to users.

The simplest function is process_command , which is a wrapper for subprocess.Popen, and takes as input a string list of arguments. It should provide options for logging verbosity.

From there we can provide helper functions building on process_command , such as:

These in turn can be composed into larger composite functions, which can be used at a macro level for convenience, such as:

What are the advantages of the feature?

What are the disadvantages of the feature?

How will this be implemented or integrated into the O3DE environment?

We anticipate the following directory and file changes for O3DE Engine:

Providing these options for the scripts is convenient for new users with simpler projects to utilize project export features without needing to write their own.

When a user creates a new project, we should modify the project template such that it includes the following as well:

These example scripts will be annotated with helpful comments to guide the user on how to extend the script for their own usage.

Are there any alternatives to this feature?

How will users learn this feature?

Are there any open questions?

monroegm commented 1 year ago

Approved at sig-content triage meeting on March 29, 2023