shadps4-emu Version Control Strategy: How shadPS4 Manages Git-Based Build Metadata

shadPS4 uses a Git-driven CMake configuration to automatically embed commit SHAs, branch names, and version metadata into every build, ensuring accurate version reporting across all platforms.

The shadps4-emu version control strategy eliminates manual version bumps by deriving build identity directly from Git state. This approach ensures that every binary—whether built by a developer locally or by CI pipelines—carries precise provenance information visible in the UI and crash logs.

How shadPS4 Implements Git-Driven Version Detection

The build system executes Git commands during the CMake configuration phase to capture repository state before compilation begins.

Extracting Commit Metadata with git rev-parse

In CMakeLists.txt (lines 107–112), the build system invokes git rev-parse and git describe to obtain two critical identifiers:

  • GIT_REV: The full 40-character commit SHA
  • GIT_DESC: A human-readable string combining the nearest tag, number of commits since that tag, and short SHA
execute_process(
    COMMAND git rev-parse HEAD
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    OUTPUT_VARIABLE GIT_REV
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

Resolving Remote and Branch Information

The strategy handles complex Git states including detached HEAD, shallow clones, and CI environments. Lines 116–184 of CMakeLists.txt implement a fallback chain:

  1. Check GitHub Actions environment variables (GITHUB_HEAD_REF, GITHUB_REF)
  2. Parse git rev-parse --abbrev-ref HEAD for local builds
  3. Detect pull request contexts and synthesize branch names as pr-<num>-<ref>
  4. Default to "origin" for remotes and "detached-head" for branch when Git metadata is unavailable

Generating Compile-Time Version Constants

Once CMake captures the Git metadata, it injects these values into the source code through template generation.

The scm_rev.cpp.in Template System

The file src/common/scm_rev.cpp.in serves as a template containing placeholders like @APP_VERSION@, @GIT_REV@, and @GIT_BRANCH@. During configuration, CMake processes this template into src/common/scm_rev.cpp (lines 10–18), replacing placeholders with actual values:

constexpr char g_version[] = "@APP_VERSION@";
constexpr char g_scm_rev[] = "@GIT_REV@";
constexpr char g_scm_branch[] = "@GIT_BRANCH@";
constexpr char g_scm_desc[] = "@GIT_DESC@";
constexpr bool g_is_release = @IS_RELEASE@;

The generated scm_rev.cpp is excluded from version control (via .gitignore) to prevent stale metadata from being committed.

Windows Resource File Integration

For Windows builds, the three-part semantic version (EMULATOR_VERSION_MAJOR, MINOR, PATCH) defined in CMake (lines 200–210) propagates into src/shadps4.rc. This embeds version information into the Windows executable properties dialog, ensuring consistency between the application's internal version API and the operating system's file metadata.

Conditional Updater Logic Based on Repository Origin

The shadps4-emu version control strategy includes safety mechanisms to prevent auto-updates from unofficial forks. Lines 176–180 of CMakeLists.txt implement the following logic:

  • If GIT_REMOTE_URL does not match the official shadps4-emu/shadPS4 repository, disable the updater
  • If GIT_BRANCH is not main or a release tag, disable the updater
  • Set ENABLE_UPDATER to OFF in these cases to prevent builds from non-standard sources from attempting to auto-update

This ensures that development builds from feature branches or personal forks do not accidentally overwrite themselves with upstream binaries.

Accessing Version Data at Runtime

Applications and developers can query the embedded metadata through the Common namespace defined in src/common/scm_rev.h.

Reading Version Information

#include "common/scm_rev.h"
#include <iostream>

void print_build_info() {
    std::cout << "Version: " << Common::g_version << '\n';
    std::cout << "Commit: " << Common::g_scm_rev << '\n';
    std::cout << "Branch: " << Common::g_scm_branch << '\n';
    std::cout << "Description: " << Common::g_scm_desc << '\n';
    std::cout << "Release build: " << (Common::g_is_release ? "Yes" : "No") << '\n';
}

Conditional Compilation Based on Updater Availability

#if defined(ENABLE_UPDATER) && ENABLE_UPDATER
    // Safe to call auto-update logic
    Updater::CheckForUpdates();
#else
    LOG_WARNING(Updater, "Auto-updater disabled for this build configuration.");
#endif

Summary

  • Git-driven metadata: shadPS4 extracts commit SHAs, branch names, and tags during CMake configuration using git rev-parse and git describe.
  • Template generation: The build system processes src/common/scm_rev.cpp.in to create compile-time constants in scm_rev.cpp, ensuring version data is embedded without manual editing.
  • Cross-platform consistency: Windows resource files (shadps4.rc) receive the same semantic version defined in CMake, aligning OS-level metadata with application internals.
  • Safety mechanisms: The updater automatically disables itself when building from unofficial remotes or non-main branches, preventing accidental updates from development forks.

Frequently Asked Questions

How does shadPS4 handle version information when building from a shallow clone?

When Git history is limited (shallow clone), the git describe command may fail to find tags. The CMake logic in CMakeLists.txt (lines 107–112) still captures the commit SHA via git rev-parse, ensuring GIT_REV is always accurate even if GIT_DESC falls back to a short SHA without tag information.

Can I override the automatic version detection in shadPS4 builds?

Yes. While the build system automatically populates src/common/scm_rev.cpp from the template, you can manually define the CMake variables (GIT_REV, GIT_BRANCH, APP_VERSION) before configuration to override the Git-driven values. However, this is discouraged for official builds as it breaks the single-source-of-truth principle.

Why does shadPS4 disable the updater on non-main branches?

The conditional logic in CMakeLists.txt (lines 176–180) sets ENABLE_UPDATER=OFF when the detected branch is not main or a release tag. This prevents development builds, feature branches, and pull request artifacts from attempting to auto-update to upstream releases, which could overwrite unstable test builds with incompatible stable binaries.

Where does shadPS4 store the generated version constants for runtime access?

The CMake configuration generates src/common/scm_rev.cpp from the template src/common/scm_rev.cpp.in. This generated file defines constexpr constants in the Common namespace (such as g_version, g_scm_rev, and g_scm_branch) which are declared in src/common/scm_rev.h and accessible throughout the codebase at runtime.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →