Open AMZN-alexpete opened 2 years ago
Relates to #https://github.com/o3de/o3de/issues/9669 This will be nice for detecting server and client mismatch.
I see the patch number changing quite often, like on a per PR level. As any new feature or bug fix goes into the build, it might be one that really matters when it comes to client/server being on the same page. Will devs remember to increase the version with each check-in? Can patch # be automatically incremented if a PR didn't ship with a major or minor change?
I wonder if patch numbers will be quickly meaningful upon seeing it. Suppose I see the patch number is different on both client and server, I'll likely still have to go and look in git to see if a particular change I want/need falls into the patch number. More often than not, the date of a build is quicker to digest. Example: "Oh, this build is from yesterday, and I definitely remember hearing about that fix last week, so I'm pretty sure I have the fix".
I sort of want a way to automatically update a file in git to store and lookup the last commit timestamp. Then in my client and server I can see major.minor.patch + timestamp. If I notice the time stamps on client and server are a week apart vs 1 month apart, I can start getting suspicious that I'm running two incompatible builds should there be any weird behavior.
@AMZN-Gene, re: using this for server/client mismatch, @kberg-amzn has some thoughts on why network or client/server versioning should not be tied to engine, project or gem versioning, let me know if that changes your feedback.
re: patch numbers changing often - that is certainly a possibility, but I would discourage bumping the patch number with every bug fix, minor feature or chore and only recommend patch changes for ones that are significant enough that a dependency needs to know about it - like security fixes.
Sounds like a good approach, I especially like the decision to use semver and the Python versioning scheme.
A few questions, more for understanding the proposal than real feedback:
compatible_engines
with values "o3de", "o3de-install", "o3de-sdk". What are the differences between those? From what I understand, "o3de" applies to everything, and the second line in the project.json examples doesn't do anything? What is the use-case for those other lines? What should we (Kythera) set?gem_dependencies
(e.g. for PhysX, which would be something like "physx~=2.1") and engine_api_dependencies
in a similar way.I am wondering if it's even necessary/recommended to set compatible_engines
, when gem_dependencies
and engine_api_dependencies
are setup carefully?
Thanks for the feedback @fabioanderegg,
- There are examples for
compatible_engines
with values "o3de", "o3de-install", "o3de-sdk". What are the differences between those?
The name of the engine in engine.json
is different in a couple places.
development
and main
branch the name is o3de
o3de-sdk
o3de-install
From what I understand, "o3de" applies to everything, and the second line in the project.json examples doesn't do anything? What is the use-case for those other lines? What should we (Kythera) set?
The engine
field in project.json
is set to the engine name of whatever engine the user registered the project with.
My recommendation for what you use in your sample project.json
and gem.json
depends on how often you intend to release updates and how many different versions you are going to support.
If you know what gem_dependencies
and engine_api_dependencies
your project and gem are compatible with then you can set those and leave compatible_engines
alone.
If you are not sure, but have tested your project and gem with specific engines, you can use the compatible_engines
field.
- The main issue we are dealing with is support for the development branch. From what I understand, this is nicely solved by setting
gem_dependencies
(e.g. for PhysX, which would be something like "physx~=2.1") andengine_api_dependencies
in a similar way.
Yes, adding support for gem_dependencies
and engine_api_dependencies
should allow you to better indicate to users what versions of the development
branch your project and gems have been tested with.
I am wondering if it's even necessary/recommended to set
compatible_engines
, whengem_dependencies
andengine_api_dependencies
are setup carefully?
In some cases you must use compatible_engines
to support older release engines that don't have gem or engine versions. It is also useful for more casual sample project and gem providers who are mainly targeting released versions of O3DE and will not be able to actively support development
.
In your example, the development version is not greater that the release version.
"engine_release_version":"22.05.1", // rename O3DEVersion field, set to 0.0.0 in development
"engine_development_version":"1.0.1", // use dev version when engine_release_version is 0.0.0, empty or missing
Will it be the case?
If that so, we will probably need a #define
added by CMake to determine if we are on the development version.
Because right now it seems the ENGINE_VERSION_<MAJOR/MINOR/PATCH>
will take either the value of engine_release_version
or engine_development_version
but without an additional define to tell if we are on the development version, it will be hard to make a gem compatible with both versions.
And in most of the cases, when handling multiple release versions in the code, the code of the latest release will need to be activated for the development version too. You can see an example here : https://github.com/PopcornFX/O3DEPopcornFXPlugin/blob/9ba771490535ab5f4f61d65ac1ba7024cb535db7/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.cpp#L133
I like the proposal and especially the tracking of fine-grained features with engine_api_versions
and gem_dependencies
.
I have one concern about using the engine name incompatible_engines
for gem.json
, since it is a user-editable value and it may become misleading for gem developers. I provide an example to explain better what I mean:
a developer defines that the gem is compatible with o3de>=22.05.00
, which is the simplest solution to avoid listing any specific API version (and thus, the one that could be used often for casual purposes). If I didn't misunderstand the proposal, this makes the gem incompatible with the pre-built installer (using o3de-sdk
) or any other custom installation of the same engine (using any alias name in the docs steps).
Although the first case is simple to fix (i.e. a developer must always define o3de
AND o3de-sdk
, and it could be written in the documentation or pre-filled by CLI), the second one it's more difficult to address from the point of view of the developer, becoming responsibility of users that use aliases to adjust gems to their engine installations.
I was thinking about the following suggestion, starting from the assumption that engine variants (e.g. source, sdk) with the same version should not provide different list of features if they are released by the same entity (e.g. O3DE, a game studio):
o3de
) from its installation one (o3de-src
, o3de-sdk
, my-pr-for-o3de
, etc.), using the former to check the version compatibility instead of the latter. The current behavior for registering different engine variants in O3DE manifesto and retrieving them by binaries can be kept the same using the latter value as-is.This allows users to customize their engine installation names (even if targeting the same engine version) without loosing the compatibility check for gems, whereas developers haven't to explicit all engine APIs if they don't want.
@ValPKFX Thank you for your feedback
Because right now it seems the
ENGINE_VERSION_<MAJOR/MINOR/PATCH>
will take either the value ofengine_release_version
orengine_development_version
but without an additional define to tell if we are on the development version, it will be hard to make a gem compatible with both versions.
Thanks for pointing that out, I'll update the design to include ENGINE_RELEASE_VERSION_MAJOR/MINOR/PATCH
and ENGINE_DEVELOPMENT_VERSION_MAJOR/MINOR/PATCH
to distinguish between development and releases. Perhaps some day in the future we can combine them somehow, but for now the release version is based on the release date, but in development versions are based on API changes.
@loherangrin thanks for pointing out the issue surrounding multiple engine names/versions.
If I didn't misunderstand the proposal, this makes the gem incompatible with the pre-built installer (using o3de-sdk) or any other custom installation of the same engine (using any alias name in the docs steps).
The compatible_engines
field only tells us what engines are known to work with a gem (or project). If an engine is not in the compatible_engines
list it does not mean that the gem is incompatible, just that it isn't known to be compatible. It'd be a little bold for a developer to suggest that their gem is forward compatible with all future unreleased versions of the engine, but I'm sure it will happen, so it is good to consider it :smiley:
In your example, if a developer wanted to indicate their gem was compatible with any engine, they could leave the compatible_engines
field empty. If they wanted to state that their gem is compatible with any engine past a certain known version of o3de then the best they could do with this new scheme would be to add o3de>=1.2.3
and o3de-sdk>=22.05.01
to compatible_engines
. I think if we wanted to let developers indicate that their custom SDK provides the same functionality as another engine, maybe we could support a compatible_engines
alias in the engine.json
like this
{
"engine_name" : "o3de-custom",
"engine_release_version" : "A.B.C",
"engine_development_version" : "1.2.3",
"compatible_engines": [
"o3de-sdk>=22.05.01", <-- this SDK provides the same functionality as o3de-sdk >= 22.05.01
"o3de==1.2.3" <-- this SDK provides the same functionality as o3de 1.2.34
],
...
Thoughts?
As you pointed out, if a gem developer wanted to make their gem compatible with multiple engine distributions from various providers (O3DE, game studios etc) they should use engine_api_versions
and gem_dependencies
because they are trying to support a wide variety of engines they have likely not tested.
That said, we will always let the user use any combination of engine and gems they want, but steer them toward compatible versions if there are any available, and otherwise point out to them when a gem/engine combination isn't known to be compatible.
I was thinking about the following suggestion, starting from the assumption that engine variants (e.g. source, sdk) with the same version should not provide different list of features if they are released by the same entity (e.g. O3DE, a game studio):
- split the engine distribution name (o3de) from its installation one (o3de-src, o3de-sdk, my-pr-for-o3de, etc.), using the former to check the version compatibility instead of the latter. The current behavior for registering different engine variants in O3DE manifesto and retrieving them by binaries can be kept the same using the latter value as-is.
So if I understand correctly, the engine.json
would contain a new field (engine_variant
) like this?
{
"engine_name" : "o3de",
"engine_variant" : "src/sdk/my-pr-for-o3de",
"engine_evelopment_version" : "1.2.3",
...
Changing what the engine_name
means is probably outside the scope of this RFC, but worth considering. We could probably keep the engine_name
field the same and add a new field for engine-engine similarity/compatibility to accomplish the same thing.
I think it would be good to say the engine and gems provided in a source and SDK variant of the engine are the same and they can be treated the same for version compatibility checks, but we can only guarantee that for the O3DE distributions.
Our documentation shows how to make an SDK and install it without making any changes to the provided Gems or engine, but I think the goal of making a custom SDK is to make changes for distributing and so in most cases users who make a custom SDK will have functionality that is different from what O3DE provides. That said, I'm sure you're right that they'll want to make it easy for their engine to be listed as compatible with gems that are known compatible with another engine.
If an engine is not in the compatible_engines list it does not mean that the gem is incompatible, just that it isn't known to be compatible
Thank @AMZN-alexpete for the explanation, I got the specification in the most strict way. So, when the compatibility status is unknown, is the user allowed to continue anyway showing some additional warning message (or nothing at all)?
I think if we wanted to let developers indicate that their custom SDK provides the same functionality as another engine, maybe we could support a compatible_engines alias in the engine.json like this [...] Thoughts?
It looks good to me, assuming that an alias cannot be expanded recursively (e.g. if my-engine
is compatible with your o3de-custom==1.2.3
, it doesn't inherit your two engine compatible definitions o3de==1.2.3
and o3de-sdk>=22.05.01
).
So if I understand correctly, the engine.json would contain a new field (engine_variant) like this?
Sorry for not having added an example. My proposal was limited to add a new field in engine.json
to identify who is releasing the engine, in order to minimize the impact on the current meaning of the engine_name
property. Something like:
{
"engine_name" : "o3de-sdk", # or, o3de-src, my-pr-for-o3de, ...
"engine_release_version" : "1.2.3",
"engine_distribution" : "o3de", # or, custom-engine, game-studio, ...
O3DE releases can keep the two different names in engine_name
(o3de
and o3de-sdk
), but use a single o3de
value for engine_distribution
(or any other similar term, like engine_vendor
, engine_owner
, engine_type
).
When looking for compatibility, the pair <engine_distribution>:<engine_release_version>
is used instead of <engine_name>:<engine_release_version>
.
However, your previous addition of compatible_engines
may already supersede this one.
So, when the compatibility status is unknown, is the user allowed to continue anyway showing some additional warning message (or nothing at all)?
Hi @loherangrin! A user will always be allowed to continue and add a gem even if it is not known to be compatible, but there will be some kind of visual indication to the user that the gem is not known compatible.
Thank you for providing an example of engine_distribution
use. I'm still thinking about it, but my initial thought is that currently the engine_name
is used for all the important stuff like registration, and it might be confusing to users not to use the name in the dependency field, however it is nice that an engine_distribution
field would give a way for users to say multiple engines that are packaged differently are compatible and come from the same distribution source.
@ValPKFX @fabioanderegg during the sig-core weekly meeting today we discussed how we could simplify the engine version fields and thought it best to make the following changes:
engine_development_version
rename to engine_version
- this will be the API version for the engine in any branch (development, release, stabilization etc). There are a few scenarios where we could get into a situation where the engine in two branches have the same engine version but have different code, however, the APIs should be compatible.engine_release_version
rename to engine_display_version
- this is really a branding name with an arbitrary version scheme that we shouldn't use for version compatibility checks because it is not tied to any API versions in the engine. It will be used for marketing purposes and as a user friendly version, but not in the compatible_engines
field.@loherangrin we discussed the engine_distribution
field and think it's best to not add that field at this time, and instead add it at a later date or add the compatible_engines
field to the engine.json
file at a later date when we have more alternate distributions of the engine and can discuss with those owners what is the best solution.
@AMZN-alexpete
Hey Alex, I think I agree with these changes over all. Trying to wrangle the display_version
in the actual compatibility logic would be too complex, especially since the nature of our release builds means these two version schemes are fundamentally asynchronous.
That being said, although the actual compatibility logic should be only tied to the engine_version
, do we also want to consider a mapping scheme (even hardcoded) between display_version
to one or more engine_versions
? From an API perspective we could include a helper function API for something roughly like List<Version> getEngineVersion( input displayVersion)
where the list returns either one, or more engine versions (I suspect we should strive to keep a 1:1 mapping, but I'm not aware if we have quirks where we have a single display version map over a range of engine versions)
..., do we also want to consider a mapping scheme (even hardcoded) between
display_version
to one or moreengine_versions
?
We certainly could have a helper function to return the engine version based on the display version - though maintaining a map may not be necessary because it's unlikely users will have many engines installed on their machine at a time. A simple way for users to discover the engine version would be for us to add that information to the Project Manager's Engine screen.
That's true, that would definitely be simpler. Depending on how we do it though, I would be concerned about it being error-prone with typos for a given engine screen.
A mapping structure can help us with validation, but if the use case is too simple it likely doesn't justify the effort into making that structure.
For the Feature Design Description section, step 4 mentions that o3de.py and Project Manager will need to be updated to handle the version specifications
The o3de.py CLI and Project Manager will take into account version and dependency specifications to display version information, determine compatibility and when a project needs to be re-compiled. The UX changes for these tools are not part of this RFC.
CMake should also be mentioned in that entry.
For the workflows sections, it says that the engine_version
patch field should be incremented, but I think that should be the engine version minor field.
Pretty much I imagine before the the stabilization branch is created the engine.json has the engine major and minor versions for the next release. i.e
"engine_version": "1.1.0"
When the stabilization branch is created they both have an engine_version of "1.1.0".
"engine_version": "1.1.0"
"engine_version": "1.1.0"
But right after the stabilization branch is created a commit can be made to the development to update the minor version to 1.2.0
"engine_version": "1.2.0"
"engine_version": "1.1.0"
Afterwards the workflow could specify that the the major and minor versions should NEVER be updated in the stabilization branch.
In the example, the the stabilization branch is only allowed to have versions 1.1.0
thru 1.1.x
While the development branch right after stabilization is cut will have versions 1.2.0
and above.
Now I agree with making the engine display version just a user friendly version for marketing purposes
Now on the topic I don't think we should try to make a mapping structure of engine_display_version
to engine_version
just yet.
I think we should first try just using the engine_version
field and see how that works.
And then if there are any customer request, we can decide then how to handle it.
I think it adds complexity that is not needed and can potentially be a flaw in the version system if we allow it, so I think we should let some time pass to handle it.
Furthermore users wanting to specify a dependency on a specific version would have to look in the engine.json determine the version , which has both fields anyway. So it is not like the user can have the excuse to say they only know the "marketing" version and not the actual version.
Finally the version information isn't targeting for novice users. It requires at least the ability to locate the "engine_version" field in the engine.json file.
@lumberyard-employee-dm Thanks for the feedback - I agree, a minor version update would be better than a patch change. I've made that change and updated the Feature Design Description to also mention CMake.
This RFC looks good with me and I am OK with signing off with the plan to implement this semantic version scheme as well as the mechanism for specifying dependencies on engine api versions, engine version and gem versions.
One consideration that was brought up was - do we need template.json support for version
, compatible_engines
and engine_api_dependencies
or can we rely on the project.json or gem.json within each template to provide that info? My thought is - we go with the version information inside the project.json or gem.json information. This is simpler and easier to maintain.
How would non-official/custom engine versioning work? One would want to fork the engine for their own work without conflating custom engine semver with official engine semver. In the gem world one could simply give the gem a new name to fork it. But in the engine world there is simply 'the engine' with a version without scope for renaming. One way to do this would be to prepend the engine versioning with a name that identifies the engine as 'official' or something user defined.
How would non-official/custom engine versioning work? One would want to fork the engine for their own work without conflating custom engine semver with official engine semver. In the gem world one could simply give the gem a new name to fork it. But in the engine world there is simply 'the engine' with a version without scope for renaming. One way to do this would be to prepend the engine versioning with a name that identifies the engine as 'official' or something user defined.
The engine
for a non-official/custom engine.json
would reflect the name of the custom engine (e.g. myengine
) and the engine_version
field would reflect the version of that custom engine. If a gem wanted to specify it was compatible with version 1.2.3
of myengine
it could have an compatible_engines
entry that looked like this:
"myengine==1.2.3"
A common example of this would be game teams that have a custom internal version of the engine. As soon as that game team starts to change the engine version to reflect changes they made to the engine, they would now be responsible for determining what gems are compatible with their engine and updating those gem.json
files to indicate compatibility.
@flappybirdace Did I understand your question correctly?
How would non-official/custom engine versioning work? One would want to fork the engine for their own work without conflating custom engine semver with official engine semver. In the gem world one could simply give the gem a new name to fork it. But in the engine world there is simply 'the engine' with a version without scope for renaming. One way to do this would be to prepend the engine versioning with a name that identifies the engine as 'official' or something user defined.
The
engine
for a non-official/customengine.json
would reflect the name of the custom engine (e.g.myengine
) and theengine_version
field would reflect the version of that custom engine. If a gem wanted to specify it was compatible with version1.2.3
ofmyengine
it could have ancompatible_engines
entry that looked like this:"myengine==1.2.3"
A common example of this would be game teams that have a custom internal version of the engine. As soon as that game team starts to change the engine version to reflect changes they made to the engine, they would now be responsible for determining what gems are compatible with their engine and updating those
gem.json
files to indicate compatibility.@flappybirdace Did I understand your question correctly?
Yes. My bad, I didn't read the conversation correctly.
A new field engine_path can be used to specify the (local or relative) path to the engine. This field is provided for users to explicitly set the path to the engine locally, which is especially useful if they have multiple copies of an engine with the same name and version.
@AMZN-alexpete It should be mentioned that the "engien_path" field is only read from the user/project.json
file, it is not part of the shared and potentially source controlled project.json
file. The issue would be adding machine specific paths that would cause break other users.
@AMZN-alexpete It should be mentioned that the "engine_path" field is only read from the
user/project.json
file, it is not part of the shared and potentially source controlledproject.json
file. The issue would be adding machine specific paths that would cause break other users.
@lumberyard-employee-dm I was actually just thinking of a common use-case where it might be good to support relative paths for the "engine_path" field in project.json
for teams that distribute the engine + projects + other files in a common folder structure via source control. They could put "engine_path":"../o3de"
in their project.json
. For example, this kind of layout:
/source-control-root
/o3de (the engine)
/project (the project)
... (other folders)
Thoughts?
The problem with that approach is that an individual user would have no way to override the engine using the "engine" key without modifying the project.json file itself which is against the entire purpose of having a user/project.json
.
Let's say as a common team user, they would like to use "custom-user-o3de" via the "engine"
key to debug the project against an older version of the engine.
Theu specify that key in their user/project.json
file, but because of the "engine_path" key in the project.json
, their registered engine would be ignored.
Let's say as a common team user, they would like to use "custom-user-o3de" via the "engine" key to debug the project against an older version of the engine. The specify that key in their
user/project.json
file, well because of the "engine_path" key in theproject.json
, their registered engine would be ignored.
I see what you mean. One option would be for them to unset the "engine_path" var by setting it to "" in their user/project.json
, and another would be for them to provide an actual path to the engine they are trying to target in "engine_path" on their local machine. But, I'd rather not make things any more complicated than they are while supporting the most common use cases, so I'm OK for now with ignoring "engine_path" in project.json
- users can customize their engine finder CMake or require their users to run a custom script to register the engine to accomplish the same thing.
:warning: UPDATE 1/27/2023
Summary:
A versioning scheme is needed to determine code compatibility between engines, projects and gems. Currently, only the engine has a version scheme tied to 6 month releases which is not granular enough.
Version and dependency information will be added inside
engine.json
,project.json
andgem.json
and relevant tools will be updated to use this information. Version information will be incremented to indicate API or other relevant changes.What is the relevance of this feature?
Versioning and dependency information will allow users and tools to make informed decisions regarding compatibility. Given the distributed nature of O3DE, an established version and dependency scheme is the only scalable way to allow de-centralized control over compatibility.
Feature design description:
The following changes will be made
<major>.<minor>.<patch>
(e.g. 1.21.9) will be added inengine.json
,project.json
andgem.json
<major>
is for API-breaking changes<minor>
is for non-API-breaking changes that add new APIs or change them in a non-breaking way<patch>
is for all other non-API-breaking changes, usually important fixesDependency fields containing lists of dependencies in the format
<name><version specifier>
(e.g. o3de >= 1.19.1) will be added inproject.json
andgem.json
where version specifiers are compatible with PEP 440 so we can use existing Python versioning functionality. If a version specifier is omitted for a gem dependency, the project's engine version will be used to determine the latest compatible gem version.*IMPORTANT* Version specifiers indicate "known compatibility". This means, there isn't a way with the proposed versioning system to specify "known incompatibility". We use the version specifiers to recommend the most compatible gem, but we warn users when they attempt to use a version that is not listed as compatible.
CMake will make #defines available with version information for compile-time compatibility control. e.g.
EDITOR_VERSION_MAJOR
,EDITOR_VERSION_MINOR
, etc.The o3de.py CLI and Project Manager and CMake will take into account version and dependency specifications to display version information, determine compatibility and when a project needs to be re-compiled. The UX changes for these tools are not part of this RFC.
Workflows:
development
branch, thegem_version
,engine_api_versions
andengine_version
will be updated as important changes are made.engine_version
. For example, if they change the minor version of a gem and zero out the patch version, they should also increase the minor version of theengine_version
and zero out the patch version.engine_version
, developers will no longer need to manually update that field.stabilization
branch is created in preparation for a release it should reflect version information that themain
branch will have whenstabilization
is merged tomain
.engine_version
minor version should be immediately incremented in development after creating thestabilization
branch so there is less time that the two branches share the sameengine_version
value.engine_display_version
in engine.json should be set to the appropriateYY.MM.XX
release version prior to merging tomain
, preferably the last change submitted to thestabilization
branch before merging tomain
to avoid accidentally merging this value back to development.stabilization
todevelopment
branches, developers should be careful not to bring theengine_display_version
orengine_version
fromstabilization
intodevelopment
.development
tostabilization
branches, developers should be careful to only include appropriate version changes. For example, if the major gem version was bumped indevelopment
but you're only merging over a patch fix for that gem into stabilization - do not bump the major gem version, just the patch.stabilization
branch should not change because only bug fixes should be merged to the branch which should never result in more than the patch version changing.stabilization
is merged tomain
it should have the correctengine_display_version
.Technical design description:
The versioning system will be backward compatible and optional. If there is no versioning or dependency information available the system will fallback to not enforcing compatibility, but will warn the user.
JSON file changes
engine.json
is modified so we have version fields for release and development and a newengine_api_versions
field is added so gems can depend on specific versions of APIs inside the core engine.project.json
will now include a project and engine version and fields for engine and gem dependencies. Also, acompatible_engines
field is added as a simple way for project maintainers to indicate known good versions of the engine (and gems) their project is compatible with.:warning: UPDATE 1/27/2023
project.json
anduser/project.json
<project>/user/project.json
can be used to overrideproject.json
settings locally. These properties can be set usingo3de edit-project-properties --user
. See O3DE CLI --user option changes for details.engine_finder_cmake
will be contain the relative path to the appropriate.cmake
file that will be used to find the engine for the project. Currently this file is hardcoded to becmake/EngineFinder.cmake
but we need the flexibility to easily update and revert this logic for future engines and projects.engine_path
can be used to specify the path to the engine. The path may be local or relative if inuser/project.json
but may only be relative in the sharedproject.json
. This field is provided for users to explicitly set the path to the engine, which is especially useful if they have multiple copies of an engine with the same name and version.gem.json
will now include a version field and fields for engine and gem dependencies. It will also have acompatible_engines
field as a simple way for gem maintainers to indicate known good versions of the engine their gem is compatible with.CLI tool changes
The
o3de.py
CLI tool will have the following updates:--force
param can be used to force the action.project.json
gem_dependencies
field using a version specifier of== <gem version>
if the gem has version information and the user selects the option to use a specific gem version:warning: UPDATE 1/27/2023
o3de.py
CLI changes--user
option will be added toregister
,edit-project-properties
andenable-gem
/disable-gem
to use theuser/project.json
and manipulate it. If--user
CLI operations fail the command does not fall back to just use theproject.json
.upgrade
command will be added that will be used to perform project upgrades. Initially this command will compare the project's engine version and the current engine version and execute Python commands to upgrade project files, outputting the list of files changed, where backups were stored, and letting the user know that, if they're using source control, they should check these files in.Project Manager changes
The Project Manager tool will have the following updates:
CMake changes
The following changes will be made to the CMake build scripts:
CMake scripts will be updated to surface the version information from each
.json
file as#defines
that can be used by code in one of the following formats:ENGINE_VERSION_<MAJOR/MINOR/PATCH>
ENGINE_<engine API>_API_VERSION_<MAJOR/MINOR/PATCH>
<PROJECT/GEM>_<project name/gem name>_VERSION_<MAJOR/MINOR/PATCH>
example
with version1.2.3
would have the following defines made available:framework
with version2.3.0
would have the following defines::warning: UPDATE 1/27/2023 EngineFinder CMake changes
CMakeList.txt
in projects will be updated to read theproject.json
and then theuser/project.json
for the "engine_finder_cmake" entry and theninclude()
that path.EngineFinder.cmake
file will be updated to check project <-> engine compatibility.Content updates
1.0.0
1.0.0
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?
This does not require any new libraries. It will expand on both C++ source code and o3de python CLI code.
Are there any alternatives to this feature?
Two other similar approaches were considered but not selected due to their reliance on git and not all customers will use git as source control.
Storing the version information in .h (header) files does not satisfy the requirement of being able to determine version information when the source isn't available.
GitHub Tags Utilize the git tag system to mark commits that increment version.
Pros:
Does not require editing a file
Cons:
Version Per Commit Each commit is considered a separate incremental version.
Pros:
Cons:
commit >=<sha1 hash>
buto3de>=23e38520e9f
could be after commit hasho3de>=a086bcbe0
How will users learn this feature?
Are there any open questions?
1.0.0
?gem_dependencies
when enabling a gem in a project?engine_version
?engine_api_versions
list - are there better ones than those proposed?Examples
Project using latest version of gems for an engine
When you intend to use the latest versions of gems that are compatible with whatever engine your project uses, you would leave the version specifier portion of the
gem_depencencies
blank and provide anengine_name
andengine_version
. This will likely be common for teams that use the pre-built SDK.The following example project will attempt to use the latest version of
PopcornFX
andKytheraAI
gems that are compatible with theo3de-sdk
engine with version1.2.3
, and because theLmbrCentral
gem is provided with the engine, no version specifier is necessary.project.json
Project requiring specific gem versions
Game studios with engineers dedicated to engine integrations may prefer to download all the necessary gems for a project and check them into source control and specify the exact version to use to discourage non-engineers from using other versions that may not be approved.
In this example, the project specifies a custom internal engine and version, and the exact versions of the
PopcornFX
andKytheraAI
gems to use. TheLmbrCentral
still does not need a version specifier because it is always provided with the engine, but the team could provide a version specifier if desired for consistency.project.json
Gem compatible with engine release versions
When you intend to provide a gem that only needs to be compatible with released engine versions you can specify those exact versions in the
compatible_engines
field. You will not be able to use a range because that would include development engine versions. The following example declares this gem is compatible with engines version1.2.3
and2.3.4
Gems\Example\1.2.3\gem.json
Gem depending on specific APIs
When you intend to provide a gem that should be compatible with any future engine so long as a core API doesn't change you can use the
engine_api_dependencies
andgem_dependencies
fields .The following example shows a gem that should be compatible with all versions of the engine containing the
framework
API major version2
Gems\Example\1.2.3\gem.json