Get SpatialOS

Sites

Menu

Worker build configuration

You can use the build scripts generated by SpatialOS, or write custom ones.

The worker build configuration is designed to provide flexibility in the way sources are structured and built. Some canonical examples are the Unity, C# and Java generated build scripts which rely on different build systems for projects with a different structure. Regardless of the language or game engine used the ultimate goal of a worker build is to:

  1. Create a worker binary from the worker sources, schema-generated code, and worker dependencies (worker SDK, external libraries, etc.).
  2. Create a zip file containing the worker binary with a name matching the value for the artifact_name specified in the worker launch configuration for each platform the binary supports. By convention zip files for artifacts are named <WorkerType>@<Platform>.zip.
  3. Place the zip file in the build/assembly/worker directory relative to the root of your SpatialOS application.

It’s best to use the generated build scripts to get started quickly and when you need something that just works. However, if you prefer a different build system or need to integrate your SpatialOS project with an existing build pipeline, you should consider using custom build scripts.

Using generated build scripts

The build field of a worker configuration file specifies how to build the worker. You can use default, generated build scripts for the following worker types: unity, csharp and java.

The generated build scripts contain the steps needed to build the worker for each platform (Windows, macOS and Linux), executed when you run spatial worker build.

You can reduce build times by only building for a specific platform (for example spatial worker build --target=Windows, or macOS, or Linux), or for a specific target (for example, using the Unity build scripts, spatial worker build --target=development for local deployments, or --target=deployment for cloud deployments).

The script names are:

  • C#: spatialos.csharp.build.json.
  • Java: spatialos.java.build.json.
  • UnityWorker: spatialos.unity.worker.build.json.
  • UnityClient: spatialos.unity.client.build.json.
  • UnrealWorker: Game/Intermediate/Improbable/spatialos.unreal.worker.build.json.
  • UnrealClient: Game/Intermediate/Improbable/spatialos.unreal.client.build.json.

To use the generated build scripts for one of the supported worker types, set the generated_build_scripts_type field. For example, to build a UnityWorker using the generated build scripts:

{
  "build": {
    "generated_build_scripts_type": "unity",
    "tasks_filename": "spatialos.unity.worker.build.json"
  }
}

If you have two workers in the same directory, note that:

  • If they both use generated build scripts, they must use the same value for generated_build_scripts_type.
  • If one worker uses generated build scripts and the other a custom one, the custom build script’s name should be different from those of the spatialos.*.build.json files specified above. Otherwise, it might be overwritten.

Using custom build scripts

The worker configuration file build field can specify either a set of tasks to be run (which must include Build, Codegen, and Clean) in a tasks list field, or the name of a file containing this task list.

For example, to define a set of tasks directly, use a build file with the following structure:

{
  "build": {
    "tasks": [
      {
        "name": "Clean",
        "steps": [
          {
            "name": "Run make clean",
            "command": "make",
            "arguments": ["clean"]
          }
          ...
        ]
      }
      ...
    ]
  }
}

Alternatively, you can define a set of tasks in a standalone file, named for example build.json:

{
  "tasks": [
    {
      "name": "Clean",
      "steps": [
        {
          "name": "Run make clean",
          "command": "make",
          "arguments": ["clean"]
        }
        ...
      ]
    }
    ...
  ]
}

And add a reference to it in the main build file by using the tasks_filename field:

{
  "build": {
    "tasks_filename": "build.json"
  }
}

Tasks

Each task has a name and a set of steps which are performed in the order they are defined when the task is run. A task can also have an optional description. In turn each step must contain a name and a list of arguments. Optional fields are:

  • A command that should be used to run this step.
  • A working_path that specifies the directory in which the step will be executed. Default is the worker’s directory.
  • An env map that allows you to specify environment variables that should be set with specific values for this stop to run. The mapping is from string to string.
  • A target that specifies for which target this should be run (default: any target). It should be used together with the --target=<string> option of the spatial worker build command. Targets are arbitrary, case-insensitive, strings.
  • A description with a string telling what this step does.

If no command is specified the arguments are interpreted as a command (i.e worker_package, process_schema, etc.) of spatial and its parameters. The first argument can also be invoke, invoke-task whose effects are described below.

Defining invoke-task steps

invoke-task causes another task in this configuration to be run. For example, the canonical Build task invokes Codegen as its first step:

...
"steps": [
  {
    "name": "Codegen",
    "arguments": ["invoke-task", "Codegen"]
  },
]
...

Defining invoke steps

invoke provides a user-friendly, cross-platform way to invoke specific external tools, such as unity-csharp- compiler. For a complete list of the supported commands, run spatial invoke --help.

Defining custom steps

When a command is present the contents of arguments is appended to it and the resulting string is executed. This is done outside of a shell so you will need to use bash as command in order to access tools like cp and mv.

...
"steps": [
  {
    "name": "Clean",
    "command": "make",
    "arguments": ["clean"]
  },
]
...

Common spatial commands for build tasks

In cases not covered by the generated build scripts it’s up to you to decide what works best for your project. Examples of tools commonly used for these steps are MSBuild, CMake, Bazel and Gradle. Some projects will even use multiple different build systems for different workers. There are some spatial commands which are often useful when writing custom build scripts:

  • spatial schema generate generates schema output for different target languages. For example:
  ...
  {
    "name": "Codegen",
    "steps": [
      {
        "name": "C++",
        "arguments": [
          "process_schema",
          "generate",
          "--cachePath=.spatialos/schema_codegen_cache",
          "--output=generated",
          "--language=cpp"
        ]
      }
    ]
  }
  ...
  ...
  {
    "name": "Build",
    "steps": [
      {
        "name": "Codegen",
        "arguments": [
          "invoke-task",
          "Codegen"
        ]
      },
      {
        "name": "Install dependencies",
        "arguments": [
          "worker_package",
          "unpack"
        ]
      }
      ...
    ]
  }
  ...
  • spatial file zip is a portable zip archiver. It is usually used for a build target in a specific build system:
  <!-- Inside CsharpWorker.targets -->
  <Target Name="AfterBuild">
    <PropertyGroup>
      <OutputArtifact>&quot;../../build/assembly/worker/$(AssemblyName)&quot;</OutputArtifact>
      <!-- Avoiding shell globbing on *nix -->
      <InputGlob>&quot;*&quot;</InputGlob>
      <WorkerPackageCommand>spatial</WorkerPackageCommand>
    </PropertyGroup>
    <Exec Command="$(WorkerPackageCommand) file zip --basePath=&quot;$(TargetDir.Replace('\', '/'))&quot; --output=$(OutputArtifact) --worker_platform=$(WorkerPlatform) $(InputGlob)" />
  </Target>
  // Inside build.gradle
  task linux_assembly(type: Exec, dependsOn: 'jar') {
    executable 'spatial'
    args('file', 'zip', '--basePath=build/libs', '--output=../../build/assembly/worker/' + rootProject.name,
            '--worker_platform=linux', '--log_level=debug', rootProject.name + '.jar')
  }

The benefit of defining build tasks is being able to use the standard spatial codegen, spatial build, and spatial clean commands to perform common operations. However, you have the flexibility to keep your builds decoupled from the spatial CLI as long as the required targets are produced at the end. An example of this are the generated project and targets files for C# which allow MSBuild and Visual Studio to take full control of the builds.

Was this page helpful?

Thanks for letting us know!

Thanks for your feedback

Need more help? Ask on the forums