addons\godot_gdk_packaging\ exposes Microsoft GDK PC packaging from
Godot — Microsoft Game Config, makepkg (genmap / pack / validate), wdapp
(register / install / launch / terminate / uninstall), XblPCSandbox, and
the GameConfigEditor / Store Association wizard. It works as a headless
runner you can drive from scripts and CI, with a top-level editor GDK menu
for Game Config, sandbox/package management, and documentation shortcuts.
This page is the headless-surface reference. For editor UI coverage, see
Godot Microsoft GDK Packaging — Editor GDK Menu.
Three equivalent invocations. Pick whichever fits your environment.
Works in every host, including before a --import pass:
godot --headless -s res://addons/godot_gdk_packaging/run.gd -- `
pack --source-dir Build\content --output-dir Build\out
# Direct form when you want Godot to target a different project root.
godot --path C:\Repos\MyGame --headless `
-s res://addons/godot_gdk_packaging/run.gd -- sandboxForm A is the fallback runner only. It does not replace the one-time
godot --headless --import step that form B needs to register
GdkPackagingRunner in that host.
Shortest official form. Requires a prior --headless --import against the
host project so the class_name GdkPackagingRunner registration is in
place:
godot --headless --import # one-time per host
godot --headless --main-loop GdkPackagingRunner -- `
pack --source-dir Build\content --output-dir Build\out
# The same form works with Godot's engine-level --path.
godot --path C:\Repos\MyGame --headless --import
godot --path C:\Repos\MyGame --headless --main-loop GdkPackagingRunner -- `
sandboxThe addon ships its own per-OS forwarders that auto-discover Godot and default the project path to the current working directory:
# Windows (cmd / PowerShell)
addons\godot_gdk_packaging\gdkpkg.cmd pack --source-dir Build\content --output-dir Build\out
# POSIX (bash / zsh)
addons/godot_gdk_packaging/gdkpkg.sh pack --source-dir Build/content --output-dir Build/outGodot discovery order in the forwarders:
GODOT_CONSOLEenv var (full path to a console-enabled Godot binary)GODOT_BINenv varGODOTenv var- Repo-local
sample\Godot*_console.exe/sample\Godot*.execandidates - Current-working-directory
Godot*_console.exe/Godot*.execandidates where godot/where godot4on Windows, orcommand -v godot/command -v godot4on POSIX shells (gdkpkg.shusescommand -vfor PATH lookup, notwhich)
Both forwarders accept --path <project_dir> to override the project
root (otherwise the current working directory is used). Pass --godot <exe> to override discovery. The Windows forwarder preserves each
forwarded argument as a separate token, so Godot paths and packaging flags
may contain spaces (for example under C:\Program Files (x86)\...).
The runner dispatches one verb per invocation. Common runner flags accepted
on every verb: --help (-h), --no-json, --config <path>,
--verbose (-v).
The export verb uses Godot's Windows Desktop exporter, so install the Godot
4.6.1 export templates under %APPDATA%\Godot\export_templates\ first.
MSIXVC and loose-registration flows also need the public Microsoft GDK toolchain on
PATH (makepkg.exe, wdapp.exe, XblPCSandbox.exe), or GDK_BIN pointing
at the Microsoft GDK bin\ directory.
| Verb | Required flags | Optional flags | Description |
|---|---|---|---|
pack |
--source-dir, --output-dir |
--map-file, --content-id, --product-id, --encrypt, --encrypt-key, --updcompat, --no-prepare |
makepkg pack. Auto-generates a map file when --map-file is omitted; --no-prepare only skips content prep. |
genmap |
--source-dir, --map-file |
(none) | makepkg genmap. |
validate |
--source-dir, --map-file |
--output-dir |
makepkg validate; --output-dir selects /pd, otherwise a validate-out sibling is created. |
prepare_content |
--content-dir |
(none) | Copies MicrosoftGame.config + logos into a content directory. |
export |
--preset, --output-dir |
--release, --no-prepare |
Godot Windows-Desktop export; --no-prepare skips post-export content preparation. |
register_loose |
--content-dir |
(none) | wdapp register (loose-files build). |
install |
--package |
(none) | wdapp install on an .msixvc file. |
uninstall |
--package-name |
(none) | wdapp uninstall by package full name. |
launch |
--package-name |
--aumid |
wdapp launch. run_launch() uses --aumid directly when present; otherwise it resolves the AUMID from wdapp list by matching --package-name. The current verb matrix in packaging_cli.gd still marks --package-name as required. |
terminate |
--package-name |
(none) | wdapp terminate; taskkill fallback is limited to the build's config-named .exe. |
sandbox |
(none) | --action {get,set,retail}, --sandbox-id |
Defaults to get; --action set also requires --sandbox-id. |
config_template |
(none) | --output, --overwrite |
Writes a starter MicrosoftGame.config; --output redirects the template path (relative paths resolve under the project root) and --overwrite replaces that same file. |
config_editor |
(none) | (none) | Detached GameConfigEditor.exe launch on the current config. |
store_wizard |
(none) | (none) | Detached GameConfigEditor.exe /StoreAssociation. |
--encrypt=key without a non-empty --encrypt-key fails with EXIT_CONFIG;
the pack verb never silently downgrades a key-encrypted build to unencrypted.
Per-verb help is always reachable as <verb> --help:
addons\godot_gdk_packaging\gdkpkg.cmd pack --helpEvery invocation prints a one-line human summary plus (by default) a
single line of JSON prefixed with PACKAGING_RESULT_JSON: so callers can
grep one canonical marker out of a log:
[packaging] pack ok in 6213ms: Packed C:\Build\content -> C:\Build\out
PACKAGING_RESULT_JSON:{"verb":"pack","exit_code":0,"ok":true,"message":"...","details":{...},"stdout":"...","stderr":"","duration_ms":6213}
Pass --no-json to suppress the marker line for terminal use. The
process exit code mirrors the exit_code field. Underlying tool diagnostics
are reported in stderr instead of being merged into stdout.
| Code | Constant | Meaning |
|---|---|---|
| 0 | EXIT_OK |
Success. |
| 1 | EXIT_FAIL |
Generic verb-ran-but-failed. |
| 2 | EXIT_USAGE |
Bad CLI arguments / unknown verb or flag. |
| 3 | EXIT_CONFIG |
Required config / env / file missing. |
| 4 | EXIT_TOOL |
Underlying tool (makepkg, wdapp, ...) failed. |
| 5 | EXIT_UNIMPLEMENTED |
Verb known but not yet implemented. |
packaging_config.gd collapses every source into a single flat dict
(highest precedence wins):
- CLI flags (kebab-case). E.g.
--source-dir C:\Build\content. res://.gdk_packaging.cfg— persisted editor settings. Empty strings here do not blow away values from lower layers. The settings file contains:[packaging]:source_dir,map_file,auto_genmap,output_dir,content_id,product_id,encrypt_option,encrypt_key,updcompat_option[sandbox]:sandbox_id,test_account[export]:preset_name,clean_build
MicrosoftGame.configat<project>\MicrosoftGame.config(override with the runner's--config <path>flag) — providesproduct_id, identity fields, and the executable name.project.godot— onlyapplication/config/nameandapplication/config/version.- Built-in defaults (
encrypt="none",updcompat=3,action="get").
Derived rules:
content_idfalls back toproduct_idwhen neither CLI nor settings supplied one.--encrypt=key:<ekb>is shorthand for--encrypt key --encrypt-key <ekb>.--config <path>is honored by the resolver and by content preparation, soprepare_content,pack, and post-export prep stage the selected config instead of implicitly readingres://MicrosoftGame.config.config_template --output <path>writes to that path; relative paths are resolved under the project root, and--overwriteremoves and recreates that same resolved file.auto_genmap,test_account, andclean_buildare persisted editor UI state. They are listed here for completeness, but the headless resolver does not treat them as CLI-equivalent overrides.
packaging_config.gd only pulls the identity, executable, and product fields
into the resolved dict, but game_config_manager.gd parses the wider set below.
These are the exact XML node and attribute paths the addon reads:
| Field | XML path |
|---|---|
config_version |
/Game@configVersion |
identity_name / name |
/Game/Identity@Name |
identity_publisher / publisher |
/Game/Identity@Publisher |
identity_version / version |
/Game/Identity@Version |
executable |
/Game/ExecutableList/Executable@Name |
product_id |
/Game/MSStore@ProductId |
display_name |
/Game/ShellVisuals@DefaultDisplayName |
description |
/Game/ShellVisuals@Description |
logo_480 |
/Game/ShellVisuals@Square480x480Logo |
logo_150 |
/Game/ShellVisuals@Square150x150Logo |
logo_44 |
/Game/ShellVisuals@Square44x44Logo |
store_logo |
/Game/ShellVisuals@StoreLogo |
splash_screen |
/Game/ShellVisuals@SplashScreenImage |
background_color |
/Game/ShellVisuals@BackgroundColor |
foreground_text |
/Game/ShellVisuals@ForegroundText |
title_id |
/Game/TitleId text node |
msa_app_id |
/Game/MSAAppId text node |
store_id |
/Game/StoreId text node |
config_template writes MicrosoftGame.config to res://MicrosoftGame.config
by default, or to the resolved --output path when supplied.
| Source | Output |
|---|---|
Derived from app_name |
Executable@Name="<app_name>.exe", ShellVisuals@DefaultDisplayName="<app_name>", and Identity@Name set to a sanitized app_name with spaces and underscores removed (falling back to MyGodotGame if that becomes empty). |
Derived from identity_publisher |
Identity@Publisher="CN=<identity_publisher>" (default CN=Publisher) and ShellVisuals@PublisherDisplayName with the leading CN= stripped. |
| Hardcoded | Game@configVersion="1", Identity@Version="1.0.0.0", Executable@Id="Game", Executable@TargetDeviceFamily="PC", StoreLogo="StoreLogo.png", Square150x150Logo="Square150x150Logo.png", Square44x44Logo="Square44x44Logo.png", Square480x480Logo="Square480x480Logo.png", SplashScreenImage="SplashScreenImage.png", Description="A Godot game packaged with GDK", BackgroundColor="#000000", ForegroundText="light", and <AdvancedUserModel>false</AdvancedUserModel>. Logos live at the project root (matching where GameConfigEditor writes a picked tile image) so editing the config never produces duplicate logos. |
| Best-effort side effect | After writing the XML, the addon tries to create placeholder *.png logos at the project root, next to the config file. That step only runs when <GDK bin>\GameConfigEditorDependencies\default480x480.png exists and loads successfully; otherwise the config is still created and the addon only warns. |
launch:run_launch()fails withEXIT_USAGEandEither --aumid or --package-name is requiredwhen both resolved values are empty. If it has a package name butwdapp listcannot resolve an AUMID, it fails withEXIT_CONFIGandCould not find AUMID for package '<package>'.sandbox:actiondefaults toget. Only--action setrequires--sandbox-id; otherwise the verb fails withEXIT_USAGEand--sandbox-id is required when --action=set.config_template: if the resolved output already exists and--overwriteis absent, the verb fails withEXIT_CONFIGand<path> already exists (pass --overwrite to replace it).
prepare_content, pack, and export validate every logo destination path
read from MicrosoftGame.config before copying logo bytes. Relative paths such
as Square150x150Logo.png are staged under the content directory;
absolute paths or paths that simplify outside the content directory (for
example ..\..\outside.png) are refused with an error before staging begins.
| Variable | Purpose |
|---|---|
GODOT_CONSOLE / GODOT_BIN / GODOT |
Shell-forwarder Godot discovery (see Invocation). |
GDK_BIN |
Override the Microsoft GDK install bin directory (otherwise C:\Program Files (x86)\Microsoft GDK\bin). |
GameDKCoreLatest |
Standard Microsoft GDK install marker; used to detect the Microsoft GDK version when present. |
gdk_toolchain.gd checks GDK_BIN first and falls back to
C:\Program Files (x86)\Microsoft GDK\bin. The toolchain is considered
available only when both makepkg.exe and GameConfigEditor.exe exist in
that bin directory.
XblPCSandbox.exeandXblDevAccount.exeare optional extras. Their paths are recorded only when the files exist, and sandbox/account features fail per-verb when those tools are missing.wdapp.exeis also resolved per verb from<bin>\wdapp.exe; it is not part of the initial availability gate.
# Drop a starter MicrosoftGame.config in the current project, or redirect it.
addons\godot_gdk_packaging\gdkpkg.cmd config_template
addons\godot_gdk_packaging\gdkpkg.cmd config_template --output Configs\Alt.config
# Direct-form runner examples with engine-level --path.
godot --path C:\Repos\MyGame --headless -s res://addons/godot_gdk_packaging/run.gd -- sandbox
godot --path C:\Repos\MyGame --headless --main-loop GdkPackagingRunner -- config_template --output Configs\Alt.config
# Get the current sandbox.
addons\godot_gdk_packaging\gdkpkg.cmd sandbox --action get
# Set the sandbox without ousting installed apps.
addons\godot_gdk_packaging\gdkpkg.cmd sandbox --action set --sandbox-id XDKS.1
# Export, prepare, and pack in three steps.
addons\godot_gdk_packaging\gdkpkg.cmd export --preset "Windows Desktop" --output-dir Build\content
addons\godot_gdk_packaging\gdkpkg.cmd prepare_content --content-dir Build\content --config Configs\Alt.config
addons\godot_gdk_packaging\gdkpkg.cmd pack --source-dir Build\content --output-dir Build\out --config Configs\Alt.config
# Register a loose-files build, launch, then terminate.
addons\godot_gdk_packaging\gdkpkg.cmd register_loose --content-dir Build\content
addons\godot_gdk_packaging\gdkpkg.cmd launch --package-name MyPublisher.MyGame_1.0.0.0_x64__abc123
addons\godot_gdk_packaging\gdkpkg.cmd terminate --package-name MyPublisher.MyGame_1.0.0.0_x64__abc123-
gdkpkg.cmd/gdkpkg.shcan't find Godot. Both forwarders exit with code3and print exactly these stderr lines:[gdkpkg] error: could not find a Godot 4 executable. [gdkpkg] set GODOT_CONSOLE / GODOT_BIN / GODOT, or pass --godot <path>.Set one of
GODOT_CONSOLE,GODOT_BIN, orGODOT, or pass--godot <path>. -
EXIT_CONFIG: wdapp.exe not found. SetGDK_BINto point at your Microsoft GDK install'sbin\directory, or install the Microsoft GDK to the default location. -
terminatefalls back towdappfailure instead oftaskkill. The fallback only targets the exact executable named byMicrosoftGame.configand only when that file exists in the build directory. The config value must be a bare.exefile name (no path separators, drive prefixes, quotes, or wildcards); extra.exefiles are intentionally ignored. -
PACKAGING_RESULT_JSON:line missing. You passed--no-json. Drop it to re-enable the marker. -
Form B (
--main-loop GdkPackagingRunner) reports unknown class. The host project hasn't been imported yet. Rungodot --headless --importonce against that host. Form A (-s ...) still works without prior import, but it does not perform the import or register the class for later form-B use. -
Microsoft GDK runtime warnings on every invocation (e.g. silent sign-in cancellation). Those come from the host project's autoloaded
GDKBootstrap. They are unrelated to the packaging verb result and can be ignored when inspectingPACKAGING_RESULT_JSON:.
- Godot Microsoft GDK Packaging — Editor
GDKMenu — what each editor menu item does and what prerequisites it needs. .github\instructions\godot-gdk-packaging.instructions.md— repo-wide rules for contributors editing the addon.docs\gdk\editor-tools.md— broader editor-tooling notes.