BuildGraph

  • Project Details 

  • Role: Build Engineer
  • Engine: Unreal Engine 4/5
  • Software: Unreal Automation Tool
  • Language: BuildGraph
  • Platform: Jenkins
  • Topic: CI/CD Automation

Introduction

Unreal Engine's BuildGraph language is a not very well-known scripting language, but is surprisingly powerful for accelerating and automating your build process. I have used this language to create a build pipeline that would automatically build and package any amount of projects for any target platform needed. This script was then integrated as a pipeline into Jenkins, which would build the game regularly on a schedule, and on demand.  

In essence, BuildGraph is used to take a large command (such as packaging a game) and break it up into steps. These steps also define dependencies on each other, so that a step can only be executed once all of its dependencies have been completed. And when multiple steps have their dependencies satisfied, they can be distributed across multiple physical machines to increase the speed of the build process.
This is what makes BuildGraph so powerful, as it allows you to parallelize your build process across multiple machines, and even across multiple platforms. And all of this is done through a single script.  

It's taken me quite a while to understand this scripting language, because it is sadly sparsely documented and comes with a few engine bugs in this rarely-used feature. To the point that for certain searches, Google couldn't even return a page worth of search results.  

One of the greatest challenges I've had was getting BuildGraph to execute the BuildCookRun command for the final stage and package step. This is because BuildCookRun is a command that has to be called through Unreal's AutomationTool (UAT). And UAT is set up in such a way to only every allow a single instance of itself to be executed on a single machine, exiting on startup if it detects another UAT instance running.
This meant that I needed one UAT process to run BuildGraph, and another to run BuildCookRun. The solution for this was concealed in undocumented environment variables. Since apparently UAT has a built in way to run multiple instances of itself, so long as the machine it's being run on has a certain environment variable set.  

This environment variable is called: 'uebp_UATMutexNoWait=1'. And when this variable is set, UAT will not check for other instances of itself, and will instead run the command it was given alongside any other instances of UAT. This allowed me to run BuildGraph and BuildCookRun in parallel.  

But after a lot of trial and error, I have managed to create a script that can build any amount of projects for any target platform, and can even distribute the build process across multiple machines.

Functionality