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 SHAGIT_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:
- Check GitHub Actions environment variables (
GITHUB_HEAD_REF,GITHUB_REF) - Parse
git rev-parse --abbrev-ref HEADfor local builds - Detect pull request contexts and synthesize branch names as
pr-<num>-<ref> - 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_URLdoes not match the officialshadps4-emu/shadPS4repository, disable the updater - If
GIT_BRANCHis notmainor a release tag, disable the updater - Set
ENABLE_UPDATERtoOFFin 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-parseandgit describe. - Template generation: The build system processes
src/common/scm_rev.cpp.into create compile-time constants inscm_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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →