Repository navigation
Game Packaging
The Game Packaging code provides a local staging pipeline that can copy engine output, game DLLs, and raw assets into a package directory. Its output is not a release artifact: stable-v1 is blocked and has no same-commit package/install/run/signing/attestation certification. The current implementation supports target selectors, optional .pdb removal, and a size-only manifest; it does not cook asset formats, calculate checksums, or create SparkPak archives.
Source: SparkEngine/Source/Core/GamePackager.h
Current readiness boundary: the repository asset-integrity check is a blocking preflight, but
GamePackagerdoes not yet consume an immutable handle-based snapshot produced by that verification. A passingAssets/assets.integrity.jsoncheck must not be described as proof of the packaged input. RDY-020 remains open until the in-profile package smoke and verified-input handoff are implemented.
| Class | Responsibility |
|---|---|
GamePackager |
Singleton orchestrating local staging: config validation, raw asset/binary copying, optional .pdb removal, and size-only manifest generation |
PackageConfig |
Configuration struct controlling output directory, platform, build config, and feature toggles |
PackageResult |
Result struct describing pipeline outcome: success flag, output path, file counts, errors, and warnings |
Selects the target platform for the packaged build. The packager detects native platforms at initialization and adds cross-compilation targets automatically.
enum class TargetPlatform : uint8_t
{
Windows,
Linux,
macOS
};Controls whether the output is a debug or release build, which affects binary selection and symbol stripping behavior.
enum class PackageBuildConfig : uint8_t
{
Debug,
Release
};struct PackageConfig
{
std::string outputDir = "Build/Package"; // Root output directory
std::string projectName = "SparkGame"; // Project name (used in folder/manifest)
TargetPlatform platform = TargetPlatform::Windows;
PackageBuildConfig buildConfig = PackageBuildConfig::Release;
bool stripDebugSymbols = true; // Remove .pdb files only
bool compressAssets = true; // Invokes the current inspection/counting hook; no archive is created
bool includeEditor = false; // Include editor binaries (rarely wanted)
};struct PackageResult
{
bool success = false; // Overall success flag
std::string outputPath; // Absolute path to the packaged output
float totalSizeMB = 0.0f; // Total size of output in megabytes
std::vector<std::string> errors; // Fatal errors that prevented completion
std::vector<std::string> warnings; // Non-fatal warnings
uint32_t assetCount = 0; // Number of assets included
uint32_t dllCount = 0; // Number of DLLs/shared libraries copied
};#include "Core/GamePackager.h"
void PackageMyGame()
{
auto& packager = Spark::GamePackager::GetInstance();
packager.Initialize();
Spark::PackageConfig cfg;
cfg.outputDir = "Build/Package";
cfg.projectName = "MyGame";
cfg.platform = Spark::TargetPlatform::Windows;
cfg.buildConfig = Spark::PackageBuildConfig::Release;
cfg.compressAssets = true; // Current hook validates/counts only; it does not create SparkPak output
auto result = packager.Package(cfg);
if (!result.success)
{
for (const auto& err : result.errors)
Log::Error("Packaging", err);
}
else
{
Log::Info("Packaging", "Output: {} ({:.1f} MB, {} assets, {} DLLs)",
result.outputPath, result.totalSizeMB,
result.assetCount, result.dllCount);
}
}You can dry-run a configuration check without executing the pipeline:
auto errors = packager.ValidateConfig(cfg);
if (!errors.empty())
{
for (const auto& e : errors)
Log::Error("PackageConfig", e);
return; // Do not proceed
}Validation catches: empty output directory, empty project name, invalid filesystem characters in the project name, and uninitialized packager state.
Cross-platform target selectors are available because the packager copies files regardless of host platform. Linux selection is experimental and outside stable-v1; a selected target does not prove a runnable package:
Spark::PackageConfig cfg;
cfg.platform = Spark::TargetPlatform::Linux;
cfg.projectName = "MyGame";
cfg.buildConfig = Spark::PackageBuildConfig::Release;
cfg.stripDebugSymbols = false; // .pdb stripping is Windows-specific
auto result = packager.Package(cfg);Spark::PackageConfig cfg;
cfg.buildConfig = Spark::PackageBuildConfig::Debug;
cfg.stripDebugSymbols = false; // Keep .pdb files for debugging
cfg.includeEditor = true; // Include SparkEditor binaries
cfg.compressAssets = false; // Disable the current inspection/counting hook
auto result = packager.Package(cfg);
// Debug packages include .pdb files alongside DLLs| Field | Default | Notes |
|---|---|---|
outputDir |
"Build/Package" |
Root output directory, created automatically |
projectName |
"SparkGame" |
Used in output folder name and manifest header |
platform |
Windows |
Target platform for binary selection |
buildConfig |
Release |
Controls binary source path and symbol stripping |
stripDebugSymbols |
true |
Only applies when buildConfig == Release
|
compressAssets |
true |
Invokes a validation/counting hook; no .spk archive is currently created |
includeEditor |
false |
Excludes editor binaries and editor-only assets |
The packager creates the following layout under the output root:
Build/Package/MyGame_Windows_Release/
Bin/ -- Engine executable + game DLLs
SparkEngine.exe
SparkGame.dll
SparkGameFPS.dll
Assets/ -- Raw copied assets; no .spk archive is currently produced
Textures/
Models/
Shaders/
Config/ -- Configuration files
manifest.txt -- File listing with sizes only; no checksums
The folder name follows the pattern {projectName}_{platform}_{config}.
At runtime the packaged game does not write inside this tree. Saves/, Logs/
(rotating SparkEngine_<timestamp>.log), spark_trace.json, and ShaderCache/
live under %LOCALAPPDATA%/SparkEngine (POSIX: $XDG_DATA_HOME or
~/.local/share/SparkEngine), and settings.ini resolves to
%LOCALAPPDATA%/SparkEngine/Config/settings.ini ($XDG_CONFIG_HOME or
~/.config/SparkEngine) whenever a user copy exists or the install's Config/ is
not writable. Data/*.spk is resolved beside the executable first. Engine shaders
are no longer flattened on install: Shaders/ForwardPlus/*.hlsl ships as a
subdirectory and no prebuilt Basic*.cso is shipped.
The packager exposes a console status command:
| Command | Description |
|---|---|
Console_GetStatus() |
Returns initialization state, supported platform count, and last package result details |
Example output from Console_GetStatus():
GamePackager: initialized, 3 supported platform(s)
Last package: /abs/path/Build/Package/MyGame_Windows_Release (success)
Assets: 247, DLLs: 5, Size: 142.3 MB
The Package() method executes these steps in order:
- Validate configuration -- Checks for empty fields, invalid characters, initialization state
-
Copy assets --
CookAssets()recursively copies rawAssets/files, skippingEditor/assets unlessincludeEditoris set; it performs no format cooking -
Copy binaries -- Copies
.dll/.so/.dyliband.exefiles frombuild/{Config}/toBin/; skips editor binaries unless requested -
Strip debug symbols -- In Release mode with
stripDebugSymbols, removes.pdbfiles from the outputBin/directory -
Generate manifest -- Writes
manifest.txtwith project metadata, timestamp, and a listing of all files with sizes -
Inspect compression input -- When
compressAssetsis enabled,CompressOutput()counts regular files and may emit warnings; it currently writes no archive - Calculate total size -- Walks the output tree and sums file sizes for the result
If any step produces fatal errors, the pipeline returns early with success = false.
cmake --preset windows-release
cmake --build build --config Releaseauto& packager = Spark::GamePackager::GetInstance();
packager.Initialize();
Spark::PackageConfig cfg;
cfg.outputDir = "Dist";
cfg.projectName = "MyShooter";
cfg.platform = Spark::TargetPlatform::Windows;
cfg.compressAssets = true;
cfg.stripDebugSymbols = true;
auto result = packager.Package(cfg);
// Check warnings even on success
for (const auto& w : result.warnings)
Log::Warn("Packaging", w);
if (result.success)
Log::Info("Packaging", "Package generated for local validation (not release-certified): {}", result.outputPath);The generated manifest.txt contains:
# SparkEngine Package Manifest
# Project: MyShooter
# Platform: Windows
# Config: Release
# Timestamp: 1743724800
# Assets: 312
# DLLs: 6
Bin/SparkEngine.exe 4521984
Bin/SparkGame.dll 1048576
Assets/Textures/player.dds 2097152
...
The output may be used for local validation. Do not distribute it as a certified release until the same-commit packaging, signing, attestation, install, upgrade, and rollback gates pass.
Run asset validation before packaging to catch broken references:
auto& validator = Spark::AssetValidator::GetInstance();
auto report = validator.ValidateAll();
if (report.failCount > 0)
{
Log::Error("Package", "Fix {} asset errors before packaging", report.failCount);
return;
}
// Proceed with packagingRegister the packager at engine startup:
auto& packager = Spark::GamePackager::GetInstance();
packager.Initialize();
// Packager is available via GetInstance() throughout the engine lifetimeGame module DLLs (SparkGame, SparkGameFPS, etc.) are automatically discovered in the build output directory and copied to the package Bin/ folder. Editor module binaries are excluded unless includeEditor is set.
| Method | Signature | Description |
|---|---|---|
GetInstance |
static GamePackager& GetInstance() |
Get the singleton instance |
Initialize |
void Initialize() |
Scan for available tools and supported platforms |
Shutdown |
void Shutdown() |
Release resources |
Package |
PackageResult Package(const PackageConfig& config) |
Execute the full packaging pipeline |
ValidateConfig |
std::vector<std::string> ValidateConfig(const PackageConfig& config) const |
Validate config without executing |
GetSupportedPlatforms |
std::vector<TargetPlatform> GetSupportedPlatforms() const |
List platforms this host can target |
Console_GetStatus |
std::string Console_GetStatus() const |
Human-readable status string |
| Method | Description |
|---|---|
PlatformToString |
Convert TargetPlatform enum to display string |
GetDllExtension |
Get binary extension for target (.dll, .so, .dylib) |
GetExeExtension |
Get executable extension (.exe or empty) |
CookAssets |
Copy raw assets to output; no format cooking |
CopyBinaries |
Copy engine and game binaries to Bin/
|
StripSymbols |
Remove .pdb files from output directory |
CreateManifest |
Write manifest.txt with file names and sizes; no checksums |
CompressOutput |
Count assets and emit warnings; no compression output |
GamePackager is not thread-safe. The Package() method performs extensive filesystem I/O and should be called from a single thread (typically the main thread or a dedicated packaging thread). Do not call Package() concurrently from multiple threads.
The singleton instance (GetInstance()) uses a function-local static and is safe to access from any thread after initialization, but all mutating operations must be serialized by the caller.
- Asset-Validation -- Validate assets before packaging
- Asset-Migration -- Migrate asset formats between versions
- ECS-Architecture -- Entity Component System overview
- Build-System -- CMake presets and build configuration
Published from 2b03dc797148. Edit the canonical source in wiki/.
- Documentation
- Docs route
- Wiki index
- Guides
- Tutorials
- Samples
- Examples
- API Reference
- API route
- Reference
- Build Guide
- Dependencies
- FAQ
- Changelog
- Roadmap
- Contributing
- Code of Conduct
- Home
- FAQ
- Getting Started
- Quick-Start Tutorial
- Making Your First Game
- Making Your First Multiplayer Game
- Artist Workflow Guide
- Editor Walkthrough
- Migration Guide
- How SparkEngine Works
- Architecture Overview
- Engine Architecture Flowchart
- Creating a Game Module
- Game Modules (catalog)
- Entity Component System
- Rendering and Graphics
- Physics
- Cloth Simulation
- Audio
- Input System
- Camera System
- Scripting with AngelScript
- Visual Scripting
- AI and Navigation
- Animation
- 2D Systems
- Networking
- Dedicated Server
- Multiplayer Quick Start
- Area Server Architecture
- Scene Management
- Large World Support
- Collaborative Editing
- Coroutine System
- Event System
- Event Response System
- Job System
- UI System
- UI Layout Extensions
- Localization
- Dialogue System
- Destruction System
- Replay System
- Achievement System
- Loading System
- Mod System
- Content Delivery
- Tween System
- Memory Integrity
- Gameplay Systems
- Terrain and Procedural Generation
- Save System
- Persistence System
- Day Night Cycle and Weather
- Cinematic Sequencer
- Runtime Prefabs
- SparkEditor
- Editor Tutorials
- SparkConsole
- SparkDaemon
- Shader Pipeline
- Asset Pipeline
- Asset Validation
- Asset Migration
- Game Packaging
- Online Services
- DataTable System
- Loot and Crafting System
- CSG System
- Font System
- Timer Manager
- Movie Render Pipeline
- HLOD and World Partition
- Remote Debug System
- Selection Manager
- Asset Dependency Graph
- Editor Automation
- File Watcher
- Project Templates
- System Requirements
- VR Support
- Mobile Platform
- Accessibility
- Platform Input
- Platform Certification
- Cross-Compilation: Wine Testing
- RHI Abstraction Layer
- D3D11 Backend
- D3D12 Backend
- Vulkan Backend
- OpenGL Backend
- Metal Backend
- DXR Raytracing
- Hybrid Ray Tracing
- Upscaling (DLSS/FSR)
- Render Graph
- Shader Graph
- GPU Particles
- GPU-Driven Rendering
- Volumetric Fog
- Volumetric Clouds
- Global Illumination
- Virtual Texturing
- Water Rendering
- Clustered Lighting
- Material System
- Post-Processing
- Shadow System
- Particle System
- Decal System
- Sky and Atmosphere
- Foliage System
- Mesh Shaders
- Neural Rendering
- Configuration Reference
- Performance Tips
- Benchmark Framework
- Threading Model
- Fuzz Policy and Parser Security
- Memory Safety
- Memory Management Patterns
- Build System and CMake Modules
- Profiler and Debugging
- Performance Profiling Guide
- Telemetry System
- Crash Reporting
- Golden Image Testing
- Utilities
- Testing
- Fuzz Policy and Parser Security
- Codebase Statistics
- Codebase Health
- Error Handling Patterns
- Hot Reload Overview
- Troubleshooting
- Contributing
- Workflow Patterns
- Build Optimizations
- CI Reproducible Builds
- GitHub API and PR Checks
- Git Rebase Conflicts
- Clang-Format
- Code Quality Violations
- AI Bloat Pattern
- MinGW + Wine Cross-Compilation
- Live Editor Testing
- Engine & Renderer Landscape
- DuetOS Portability Catalog
- Five-Engine Analysis
- Eleven-Engine Analysis
- ThorVG / Unity Graphics Analysis
- Advanced Techniques Catalog
- Third-Party Library Evaluation
- Engine Viability Evaluation
- Engine Feature Recommendations
- Project Recommendations
- Mac Compatibility Analysis
- Codebase Observations
- Codebase Bloat Audit
- Test Suite Audit
- Documentation Coverage Audit
- ThirdParty Dependencies Audit
- Load Test Baseline
- Gameplay Systems Status
- SparkGame Module Status
- Stub and Abandoned Features
- Memory Integrity System
- Memory Safety Evaluation
- Hardware Acceleration Systems
- Jolt Physics Integration
- GPU/CPU Separation Plan
- Daemon Services Architecture
- Reflection & Polymorphism Refactoring Plan
- SparkBuild In-Tree
- Wine No-JobSystem Breakthrough
- Wine Role and Fallback Tiers