IN THIS ARTICLE
Adding C++ Code to a Lumberyard Game with Gems
Adding C++ Code to a Lumberyard Game with Gems
To add C++ code or assets to your Lumberyard game, use a gem. This document shows you how to create a gem and the various techniques that you can use to add code to it.
Creating and Configuring Gems
Creating a gem is straightforward. To create or enable a gem for your game project, follow the steps in the
Add modular features and assets with Gems. The gem that you create or enable is located in the \dev\Gems\<gem name> directory. The gem’s directory structure is similar to the following example. Your gem might not have all the directories listed.
\3rdParty
\Assets
\Code
\Include
\Source
\Tests
\External
3rdParty– Contains third-party definition files that are specific to the gem.Assets– Contains assets to include in the game project that are specific to the gem.Code\Include– An additional header include path to add to a game project that uses the gem.Code\Source– Contains the source code for the gem.Code\Tests– Contains unit testing source code for projects that are built in a test configuration.External– Contains external libraries on which the gem depends that are specific to the gem.
Code Directory Contents
The \dev\Gems\<gem name>\Code subdirectory has the following items that Lumberyard creates by default:
| Item | Location |
|---|---|
| An empty EBus include file that is named after the gem. | \Include\ |
| The AZ module for the gem | \Source\ |
| The default systems component files | \Source\<gem name>SystemComponent.h \Source\<gem name>SystemComponent.cpp |
| Standard precompiled header files | \Source\StdAfx.h \Source\StdAfx.cpp |
| Skeleton unit test source file | \Tests\ |
Lumberyard also creates certain
Waf–related files in the \dev\Gems\<gem name>\Code subdirectory. These files specify the source code content and how the gem is defined and built.
| Item | Location |
|---|---|
| Manifest file for the Waf build of the gem | |
| Manifest file that lists additional files to for test configuration builds \(for example, Tests/ | |
| Waf build script file that defines the gem | wscript |
The manifest file that manages the source code uses the Lumberyard Waf waf_files schema to define the source files, their Microsoft Visual Studio filter, and
uber file grouping. The default <gem name>.waf_files that the Project Configurator generates looks like the following:
{
"none": {
"Source": [
"Source/StdAfx.cpp",
"Source/StdAfx.h"
]
},
"auto": {
"Include": [
"Include/<gem name>/<gem name>Bus.h"
],
"Source": [
"Source/<gem name>Module.cpp",
"Source/<gem name>SystemComponent.cpp",
"Source/<gem name>SystemComponent.h"
]
}
}
The .waf_files file contains the following three levels of indentation:
- The first level contains the uber file mapping for uber file–enabled builds.
nonespecifies files to be excluded from the uber file. Precompiled headers must be listed here.autospecifies files that are automatically combined into modules that are optimized for compile time by Waf.- You can also specify a fixed uber file name \(for example, `my_gem_uber_0.cpp`\) at this level to specially group a set of files. All of the files in the grouping are combined into
my_gem_uber_0.cpp. This technique is useful to restrict which files are combined, like operating system-specific code.
- The second level represents the Visual Studio filters that determine how the files are organized in the Visual Studio solution that Waf generates.
- A special value called
Rootrepresents the root node of the project explorer in Microsoft Visual Studio \(that is, the file is not placed in any subdirectory\).
- A special value called
- The third level contains paths to the source files relative to the location of the
waf_filesfile itself.
Updating Gem Code
To update code in your gem, add a third-party library, new source code files, system components, or dependencies on other gems or Lumberyard modules.
Adding an External Third-Party Library to a Gem
A gem can use any Lumberyard third-party library, including its own private third-party library. To register a private third-party library for a gem, create a third-party configuration file in the \3rdParty directory of the gem. For more information, see
Adding Third-Party Libraries.
When you set the configuration file to an external third-party library, the library can be added as a gem dependency through the Waf dependency mechanism. For information about third-party library configuration files, see Creating Third-Party Library Configuration Files for Waf.
Waf uses two conventions to add dependencies to third-party libraries: uselib and use. The convention uselib is a wscript keyword that configures a module to link to a library’s include path, library path, and library. If a gem uses uselib to consume its gem-specific library, then that library is available to the gem only for compiling and linking.
The convention use is similar to the uselib keyword, except that the library’s dependencies are recursively propagated to the module that adds the dependency. If a gem uses use to consume its gem-specific library, then the library can be used recursively. This means that if the gem is enabled, the gem–specific third-party library is also available to the game project or dependent gems.
Adding New Source C++ Files to Gems
To add source code \(for example, C\+\+ or Qt\) to a gem, use the Lumberyard
Using the Waf Build System. Place internal source files \(that is, files not meant to be exposed outside of the gem\) under the \Code\Source directory. Place header files that can be included in projects or other gems in the \Code\Include\<gem name>\ directory. Place additional unit tests in the \Code\Tests directory.
To add code files to a gem
Add the files to the target location. For consistency, we recommend that you place the source files somewhere in the
\Codedirectory.Add the source files to the Waf manifest
waf_filesfile. Following the format described earlier, add the source file paths to either the<gem name>.waf_filesfile and/or the<gem name>_test.waf_filesfile.From a command prompt window, run
lmbr_waf configureto configure Waf and regenerate the Microsoft Visual Studio solution.
Adding System Components
New gems come with a default system component called **
Adding Dependencies to a Gem
In addition to adding dependencies to gem-specific third-party libraries, your gem can specify dependencies on Lumberyard Engine modules, other gems, or third-party libraries for Lumberyard.
Adding a Dependency on a Lumberyard Module
Any gem can be configured to depend on any of the following Lumberyard framework modules:
AzCoreAzFrameworkAzGameFrameworkAzQtComponentsAzToolsFrameworkGridMateGridMateForTools
To declare a dependency on one of these Lumberyard modules, use the Waf use mechanism. The following example wscript file specifies a dependency on AzFramework.
def build(bld):
bld.DefineGem(
# Add custom build options here
includes = [bld.Path('Code/CryEngine/CryAction'),
use = ['AzFramework'],
)
Adding a Dependency on Another Gem
You can configure gem A to depend on gem B by modifying gem A’s gem.json and wscript files. The following example shows how the Twitch gem, included with Lumberyard, declares a dependency on the
HttpRequestor gem . This gems.json file is located in the lumberyard_installation\dev\Gems\Twitch\ directory.
{
"GemFormatVersion": 3,
"Uuid": "b63e64141fab40b791211ba257632e84",
"Name": "Twitch",
"DisplayName": "Twitch",
"Version": "1.0.0",
"LinkType": "Dynamic",
"Summary": "Provides access to the Twitch Commerce SDK, social functions, login, chat, and other APIs.",
"Tags": ["Twitch","Commerce","SDK","Social"],
"IconPath": "preview.png",
"Dependencies": [
{
"Uuid": "28479e255bde466e91fc34eec808d9c7",
"VersionConstraints": [ "~>1.0" ],
"_comment": "HttpRequestor"
}
]
}
The Twitch gem specifies the HttpRequestor gem in the Dependencies section. The Dependencies section also has a VersionConstraints section that you can use to specify versioning requirements.
The Twitch gem’s wscript file uses the use keyword to declare a dependency on HttpRequestor:
def build(bld):
import lumberyard_sdks
file_list = []
if lumberyard_sdks.does_platform_support_aws_native_sdk(bld):
file_list.append('twitch.waf_files')
else:
file_list.append('lmbraws_unsupported.waf_files')
bld.DefineGem(
use = [ 'HttpRequestor',
'LmbrAWS'
],
uselib = [ 'TWITCHFSDK',
'AWS_CPP_SDK_CORE'
],
includes = [],
file_list = file_list,
win_file_list = ['twitch_win.waf_files']
)
Adding a Dependency on a Third-Party Library for Lumberyard
You can define a gem that uses a third-party library for Lumberyard that another module is also using. To do so, use the Waf uselib mechanism to add the dependency to the gem, as in the following example wscript file.
def build(bld):
bld.DefineGem(
# Add custom build options here
includes = [bld.Path('Code/CryEngine/CryAction'),
use = ['AzFramework'],
uselib = ['AWS_CPP_SDK']
)
For more information, see Adding Third-Party Libraries and Creating Third-Party Library Configuration Files for Waf.
Note
Because the recursive nature of use can lead to linker errors, especially duplicate symbol errors, uselib is a better choice.