Build a game
A build turns the open project into a game that players run without the editor. It contains the native Feather player, a copy of the project and the assets it uses. The player runs the same scripts, Blueprints and physics as Play in the editor.
The player is the same program for every game, so a build compiles no game code. Building is mostly
copying and checking files, and takes seconds once a player is available. The editor, feather-cli
and GitHub Actions all use the same build pipeline.
Build from the editor
Section titled “Build from the editor”- Save any pending edits. A build validates the whole project and its scripts first, and stops on the first error.
- Open the Build window: choose File → Build game…, or Window → Build · Windows, macOS, Linux.
- Pick a platform. Each button shows This computer, Runtime ready or Needs a runtime; hover over it to see where its player comes from.
- Adjust the Settings section if you need to (see below). The window shows the output folder.
- Click Build <name> for <platform>. The Build log shows progress.
- When it finishes, the window shows the time, file count and size, with Show in folder, Run game (for this computer’s platform) and Copy path.
The Build button in the toolbar, and File → Build for this computer, build straight away for the platform selected in the Build window (this computer by default). Only one build runs at a time.
Build settings
Section titled “Build settings”Settings are stored in the project and are the same in the Build window and the build.get /
build.set commands.
| Setting | Default | Notes |
|---|---|---|
Game name (game_name) |
The project name | Name of the app and its executable. 1–64 characters, without / \ : * ? " < > |, not starting with a dot and not a reserved Windows name |
version |
0.1.0 |
Three numbers, such as 1.2.0 |
build_number |
1 |
1 to 1,000,000. Increase it with every release (macOS CFBundleVersion) |
Bundle id (bundle_id) |
com.feather-engine.<game> |
Reverse-DNS app id, such as com.studio.game |
profile |
release |
release is optimised for players. development compiles faster and runs slower |
Output folder (output_dir) |
builds |
A folder inside the workspace. In the editor, it is relative to the project’s folder |
Make a zip (archive) |
Off | Also write a .zip (.tar.gz for Linux) beside the build |
What a build contains
Section titled “What a build contains”Each build is written to <output folder>/<game>-<platform>, for example builds/my-game-windows.
Development builds add -dev.
| Platform | Layout |
|---|---|
| macOS | <Name>.app, with the project and assets/ inside Contents/Resources/game/ |
| Windows | <Name>.exe with project.feather.json and assets/ beside it. Release builds open no console window |
| Linux | <Name> with project.feather.json and assets/ beside it |
Every build also contains README.txt (how to launch it), licenses/, release-manifest.json
(every file with its size and SHA-256, plus the platform, profile and version) and SHA256SUMS. To
check a build, run shasum -a 256 -c SHA256SUMS inside its folder.
On a Mac, the macOS app is code-signed ad hoc. Pass a signing identity with sign_identity (or the
FEATHER_SIGN_IDENTITY environment variable) to sign with it; a named identity also turns on the
hardened runtime. A macOS app built on another platform is not signed.
How a build stays reliable:
- Every asset is hash-checked as it is copied. A standalone texture missing from the asset cache is left out with a warning instead of failing the build; import it again to include it.
- The player’s executable must match the target platform, so a Windows player can never end up in the Linux build.
- The build is assembled in a hidden folder and swapped in at the end. A failed build leaves the
previous one untouched. Only a previous Feather build (a folder with
release-manifest.json) is ever replaced; any other folder in the way is refused.
Where the player comes from
Section titled “Where the player comes from”The first source that applies is used. game.platforms and the Build window’s platform buttons show
which one each platform would use.
| Source | When |
|---|---|
| A player you supply | player (--player on the CLI). It must be inside the workspace |
| Built with Cargo | This computer’s platform, from a source checkout (cargo build --locked --no-default-features --bin feather-player, with --release for release builds). Only the first build takes minutes |
| The bundled player | This computer’s platform, with the editor app’s own player |
| A player runtime | Any platform: feather-player (or feather-player.exe) in runtimes/<platform>/ in the Feather data folder, or in $FEATHER_RUNTIMES/<platform>/ |
There is no cross-compiling. To build for another platform, put that platform’s player in the
runtimes folder; a feather-player-<platform> file from a Feather release works too. The Build
window’s Build on GitHub section shows the folder’s path.
Run the game
Section titled “Run the game”Players double-click <Name>.app, <Name>.exe or <Name>, and keep the whole folder together.
From a terminal you can also pass a project path to the player:
feather-player path/to/project.feather.jsonThe game starts in the project’s start level. Escape opens the pause menu, with Resume, Save game, Load game, Settings and Quit to desktop, unless the game draws its own menu. Settings, saves and crash reports are written to the Feather data folder, never into the game folder, so replacing a build keeps them. See Saves and settings.
Player options
Section titled “Player options”| Option | Effect |
|---|---|
PROJECT |
Run this project instead of the one beside the player |
--verify-run JSON |
Run, write a verification report and exit; see Profiler |
--screenshot PNG |
With --verify-run, also save a screenshot |
--record DIR |
Save every frame as a numbered JPEG in DIR |
--version |
Print the player version |
From a source checkout you can run any saved project with the player directly:
cargo run --no-default-features --bin feather-player -- examples/paper-shredder/project.feather.jsonBuild on GitHub
Section titled “Build on GitHub”A game can live in its own GitHub repository, without the engine source. GitHub downloads the prebuilt Feather tools and builds Windows, macOS and Linux versions; nothing is compiled.
- Save the project, then in the Build window’s Build on GitHub section click Set up GitHub
builds (or run
game.setup_github). It writes.github/workflows/feather-build.ymlat the repository root, the nearest folder with.git(otherwise the project’s folder: rungit initthere), and adds the build folders to.gitignore. - Commit the workflow with the project, including its
assets/folder, and push. The workflow checks out Git LFS files, so large models, textures and sounds can be stored in LFS. - While the engine repository is private, add a repository secret
FEATHER_ENGINE_TOKEN: a fine-grained token with Contents: read on the engine repository. - In GitHub, open Actions → Build game → Run workflow. You can choose the platforms, a version
and whether to upload to Steam. Each platform’s build is attached to the run as a
game-<platform>download. - Push a tag such as
v1.0.0to build that version and publish it as a GitHub release (and upload it to Steam, when Steam is set up).
The workflow is pinned to the Feather version of the editor that wrote it, so CI builds with what you
tested. Run Set up GitHub builds again after updating Feather; it refreshes a workflow Feather
wrote, and refuses to replace any other file unless you pass overwrite. Windows and Linux are
packaged on a Linux runner and macOS on a Mac runner, so the app is signed. Each runner checks the
downloaded tools against the release’s SHA256SUMS.
Any other CI can run the same build with feather-cli build; the Build window shows the exact
command.
Upload to Steam
Section titled “Upload to Steam”Set the ids from Steamworks (SteamPipe → Depots) in the Build window’s Steam section or with
steam.set. The GitHub workflow does the upload.
| Setting | Range | Default | Notes |
|---|---|---|---|
App ID (app_id) |
0 to 4,294,967,295 | 0 | 0 turns Steam uploads off |
Windows depot, macOS depot, Linux depot (depot_windows, depot_macos, depot_linux) |
0 to 4,294,967,295 | 0 | One depot per platform; 0 leaves that platform out. Each platform needs its own depot, and a depot id cannot be the app id |
Live branch (branch) |
Letters, digits, -, _; up to 64 |
beta |
Branch the upload goes live on. Empty only uploads. default and public are refused: set the default branch live in Steamworks yourself |
With an App ID set, at least one depot is required. The workflow also needs two repository secrets:
STEAM_USERNAME, a Steam account for builds with permission to edit and publish the app, and
STEAM_CONFIG_VDF, the base64 of an authorised steamcmd config/config.vdf, so CI never needs a
Steam Guard code. Tagged builds upload automatically when the App ID and both secrets are set;
without the secrets the upload is skipped with a warning. Run workflow with Upload to Steam
ticked uploads any build.
Limits
Section titled “Limits”- One build at a time in the editor.
- No cross-compiling: other platforms need a player runtime or a GitHub build.
- Builds have no app icons yet, and are not notarised (macOS) or Authenticode-signed (Windows).
- Steam support covers uploads only.
Automate it
Section titled “Automate it”# Which platforms can this machine build for, and where would each player come from?feather-cli --workspace ./my-game --project project.feather.json command game.platforms
# Name and version the game, then build it for this computer with a zip.feather-cli --workspace ./my-game --project project.feather.json command build.set \ --json '{"patch":{"game_name":"My Game","version":"1.0.0"}}' --save project.feather.jsonfeather-cli --workspace ./my-game --project project.feather.json build --archive
# Build for Windows with a Windows player you put inside the workspace.feather-cli --workspace ./my-game --project project.feather.json build \ --platform windows --player tools/feather-player-windows.exe --version 1.0.1
# Write the GitHub workflow and set up Steam.feather-cli --workspace ./my-game --project project.feather.json command steam.set \ --json '{"patch":{"app_id":480,"depot_windows":481,"depot_macos":482,"depot_linux":483}}' \ --save project.feather.jsonfeather-cli --workspace ./my-game --project project.feather.json command game.setup_githubbuild runs game.export, with --output, --profile and --sign-identity as its other options.
In a headless run, --version, --build-number and --name override the build settings for that
build only; they are not saved. Headless, game.export returns the report (path, player,
files, bytes, seconds, archive, warnings); in a live editor it returns a job_id to poll
with job.inspect, and build waits for it. To build from the editor binary without opening a
window, use --export; see Install.