From: Andrew Udvare <audvare@gmail.com>
Date: Mon, 9 Feb 2026 02:00:00 -0500
Subject: [PATCH] Allow version to be specified via env for tarball builds

When XENIA_BUILD_BRANCH, XENIA_BUILD_COMMIT, XENIA_BUILD_COMMIT_SHORT or
XENIA_BUILD_VERSION are set (e.g. by an ebuild), use those values instead
of git and do not warn about unversioned source tree. generate_version_h()
reads the env vars first so tarball builds get version info in binaries.

---
 xenia-build.py | 51 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 9 deletions(-)

diff --git a/xenia-build.py b/xenia-build.py
--- a/xenia-build.py
+++ b/xenia-build.py
@@ -163,11 +163,14 @@ def main():
         os.path.abspath(os.path.join("tools", "build")),
         ])
 
-    # Check git exists.
-    if not has_bin("git"):
-        print_warning("Git should be installed and on PATH. Version info will be omitted from all binaries!\n")
-    elif not git_is_repository():
-        print_warning("The source tree is unversioned. Version info will be omitted from all binaries!\n")
+    # Check git exists (or version overrides are set, e.g. by ebuild).
+    version_override = any(os.environ.get(k) for k in (
+        "XENIA_BUILD_BRANCH", "XENIA_BUILD_COMMIT", "XENIA_BUILD_COMMIT_SHORT", "XENIA_BUILD_VERSION"))
+    if not version_override:
+        if not has_bin("git"):
+            print_warning("Git should be installed and on PATH. Version info will be omitted from all binaries!\n")
+        elif not git_is_repository():
+            print_warning("The source tree is unversioned. Version info will be omitted from all binaries!\n")
 
     # Check python version.
     python_minimum_ver = 3,10
@@ -297,19 +300,43 @@ def shell_call(command, throw_on_error=True, stdout_path=None, stderr_path=None,
 
 def generate_version_h():
     """Generates a build/version.h file that contains current git info.
+    When XENIA_BUILD_BRANCH, XENIA_BUILD_COMMIT, XENIA_BUILD_COMMIT_SHORT or
+    XENIA_BUILD_VERSION are set (e.g. by an ebuild), those values are used
+    instead of git so tarball builds get version info.
     """
     header_file = "build/version.h"
     pr_number = None
 
-    if git_is_repository():
-        (branch_name, commit, commit_short) = git_get_head_info()
-
-        if is_pull_request():
-            pr_number = get_pr_number()
-    else:
-        branch_name = "tarball"
-        commit = ":(-dont-do-this"
-        commit_short = ":("
+    branch_name = os.environ.get("XENIA_BUILD_BRANCH")
+    commit = os.environ.get("XENIA_BUILD_COMMIT")
+    commit_short = os.environ.get("XENIA_BUILD_COMMIT_SHORT")
+    if os.environ.get("XENIA_BUILD_VERSION"):
+        v = os.environ.get("XENIA_BUILD_VERSION").strip()
+        if v and not commit_short:
+            commit_short = v[:12] if len(v) > 12 else v
+        if v and not commit:
+            commit = v
+        if v and not branch_name:
+            branch_name = v
+
+    if branch_name is None or commit is None or commit_short is None:
+        if git_is_repository():
+            (git_branch, git_commit, git_commit_short) = git_get_head_info()
+            if branch_name is None:
+                branch_name = git_branch
+            if commit is None:
+                commit = git_commit
+            if commit_short is None:
+                commit_short = git_commit_short
+            if is_pull_request():
+                pr_number = get_pr_number()
+        else:
+            if branch_name is None:
+                branch_name = "tarball"
+            if commit is None:
+                commit = ":(-dont-do-this"
+            if commit_short is None:
+                commit_short = ":("
 
     # header
     contents_new = f"""// Autogenerated by `xb premake`.
