The patch number is the commit count
A hand-maintained version says what somebody remembered to type. Pinning it to the repository means a binary always names the commit it came from, so a log from a test machine settles which changes are in it. stamp-version.ps1 runs as RP_L4's pre-build step and writes the generated RP_L4\rpl4build.h: #define RP412_VERSION "4.12.96" #define RP412_VERSION_LONG "4.12.96 (a1b2c3d)" The hash beside the number names the commit exactly; a trailing '+' means the tree had uncommitted changes to TRACKED files when it was built, which is the state a puzzling bug report usually comes from. Untracked files do not count - one scratch document in the tree would otherwise mark every build dirty and the marker would stop meaning anything. Generated rather than committed, and gitignored, because a hardcoded number cannot work: the commit that records "4.12.96" is itself commit 96, so the file is stale the moment it lands. The header is rewritten only when the stamp changes, so ordinary rebuilds do not drag RPL4.CPP through a recompile. pack-dist.ps1 reads that header instead of asking git again - a commit between building and packing would otherwise have the zip claiming a version the binary inside it does not report - and warns when the build it is packing came from a modified tree. The README banner, the zip name and the shipped CONTROLS.html all take the same number. Numbering stays ordered: 95 commits so far, so 4.12.95 follows 4.12.7 and every future build sorts after it. Only the "4.12" line is set by hand, at the top of the script. Two things the wiring turned up: Windows PowerShell turns a native command's stderr into ErrorRecords, so with $ErrorActionPreference = 'Stop' git's routine "LF will be replaced by CRLF" warning threw straight past the dirty check and stamped a modified tree as clean. Every git call now goes through cmd, which keeps stderr out of PowerShell's error stream entirely. The script ended on "git diff --quiet", which exits 1 to mean "there are changes" - as a pre-build step that failed the build on exactly the tree a developer builds in. It exits 0 explicitly now. Verified: deleting the header and building recreates it; a second build reports "(unchanged)" and leaves the timestamp alone; a build on a modified tree succeeds and stamps 4.12.95 (c1729e4+); and the packed game logs "Red Planet 4.12.95 (c1729e4+)" on its first line while README.txt and CONTROLS.html in the same package both read 4.12.95. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,11 @@ mfd_layout.cfg
|
||||
# at this machine, which is not the repo's business.
|
||||
pilot.cfg
|
||||
|
||||
# Generated by stamp-version.ps1 as RP_L4's pre-build step. The patch
|
||||
# number in it IS this repository's commit count, so a committed copy
|
||||
# would be stale the moment it was committed.
|
||||
/RP_L4/rpl4build.h
|
||||
|
||||
# Build-output static libs that land in lib/ (the two committed dependency
|
||||
# libs, OpenAL32.lib and libsndfile-1.lib, stay tracked).
|
||||
/lib/Munga_L4.lib
|
||||
|
||||
@@ -50,10 +50,36 @@ The solution is [WinTesla.sln](WinTesla.sln) with four v143 projects:
|
||||
Build order is resolved by `ProjectReference` (RP_L4 and RPL4TOOL both reference
|
||||
Munga_L4).
|
||||
|
||||
**Versioning:** the patch number *is* the repository's commit count, so a
|
||||
build always names the commit it came from and there is no question about
|
||||
which changes a given binary contains.
|
||||
[stamp-version.ps1](stamp-version.ps1) runs as RP_L4's pre-build step and
|
||||
writes the generated, uncommitted `RP_L4\rpl4build.h`:
|
||||
|
||||
```
|
||||
#define RP412_VERSION "4.12.96"
|
||||
#define RP412_VERSION_LONG "4.12.96 (a1b2c3d)"
|
||||
```
|
||||
|
||||
The game logs the long form on its first line. A trailing `+` on the hash
|
||||
means the tree had uncommitted changes to tracked files when it was built —
|
||||
useful when a test machine reports something a clean build cannot reproduce.
|
||||
Only the `4.12` product line is set by hand, at the top of the script.
|
||||
|
||||
The header is deliberately not committed: the commit that recorded a
|
||||
hardcoded number would itself change the count, so the file would be stale
|
||||
the moment it landed. It is rewritten only when the stamp actually changes,
|
||||
so ordinary rebuilds do not recompile `RPL4.CPP` for nothing. Building
|
||||
outside a git checkout stamps `4.12.x (no repository)` rather than inventing
|
||||
a number that would sort against real ones.
|
||||
|
||||
**Packaging:** [pack-dist.ps1](pack-dist.ps1) assembles a runnable game into
|
||||
`dist\` (exe + PDB, game data, OpenAL/libsndfile runtimes, desktop
|
||||
`environ.ini`, `start-windowed.bat`, README). Pass `-Zip` to also produce
|
||||
`dist\RedPlanet412-prototype.zip` for handing to someone else.
|
||||
`RedPlanet-<version>.zip` for handing to someone else. It reads the version
|
||||
from `rpl4build.h` rather than asking git again, so the package and the
|
||||
binary inside it cannot disagree, and it warns if the build it is packing
|
||||
came from a modified tree.
|
||||
|
||||
## 3. VS2022 migration notes (what changed and why)
|
||||
|
||||
|
||||
+8
-1
@@ -29,6 +29,7 @@
|
||||
#include "..\munga_l4\l4mfdview.h" // RPWindowLayout_*
|
||||
#include "..\munga_l4\l4joy.h" // RPJoyConfigWizard
|
||||
#include "rpl4ver.h"
|
||||
#include "rpl4build.h" // generated: RP412_VERSION / RP412_VERSION_LONG
|
||||
#include "..\munga\resver.h"
|
||||
#include "..\munga\resource.h"
|
||||
// added for game status drawing support
|
||||
@@ -188,7 +189,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
DEBUG_STREAM << "Red Planet 4.12.7" << std::endl << std::flush;
|
||||
//
|
||||
// The patch number is this repository's commit count and the hash beside
|
||||
// it names the commit, so a log from a test machine says exactly which
|
||||
// build it came from. A trailing '+' means the tree had uncommitted
|
||||
// changes when it was built. See stamp-version.ps1.
|
||||
//
|
||||
DEBUG_STREAM << "Red Planet " << RP412_VERSION_LONG << std::endl << std::flush;
|
||||
DEBUG_STREAM << "L4CONTROLS=" << getenv("L4CONTROLS") << std::endl << std::flush;
|
||||
|
||||
#ifdef RP412_STEAM
|
||||
|
||||
@@ -70,6 +70,15 @@
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<!-- rpl4build.h is generated, not committed: the patch number is the
|
||||
repository's commit count, so a hardcoded one would be stale the
|
||||
moment it was committed. The script rewrites the header only when
|
||||
the stamp actually changes, so this does not drag RPL4.CPP through
|
||||
a recompile on every build. -->
|
||||
<PreBuildEvent>
|
||||
<Command>powershell -NoProfile -ExecutionPolicy Bypass -File "$(ProjectDir)..\stamp-version.ps1"</Command>
|
||||
<Message>Stamping the build version from git</Message>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
|
||||
+23
-2
@@ -27,6 +27,23 @@ if (-not (Test-Path $exe)) {
|
||||
throw "Release\rpl4opt.exe not found - build first (see BUILD.md 2)."
|
||||
}
|
||||
|
||||
# --- version ---------------------------------------------------------------
|
||||
# Read the stamp the exe was BUILT with rather than asking git again: a
|
||||
# commit between the build and the pack would otherwise have the package
|
||||
# claiming a version the binary inside it does not report.
|
||||
$buildHeader = Join-Path $root 'RP_L4\rpl4build.h'
|
||||
if (-not (Test-Path $buildHeader)) {
|
||||
throw "RP_L4\rpl4build.h not found - build first, or run stamp-version.ps1."
|
||||
}
|
||||
$stamp = Get-Content $buildHeader -Raw
|
||||
$version = ([regex]::Match($stamp, '#define\s+RP412_VERSION\s+"([^"]+)"')).Groups[1].Value
|
||||
$versionLong = ([regex]::Match($stamp, '#define\s+RP412_VERSION_LONG\s+"([^"]+)"')).Groups[1].Value
|
||||
if (-not $version) { throw "could not read RP412_VERSION from $buildHeader" }
|
||||
if ($stamp -match '#define\s+RP412_BUILD_DIRTY\s+1') {
|
||||
Write-Warning "packing a build made from a modified tree ($versionLong)"
|
||||
}
|
||||
Write-Host "Version $versionLong"
|
||||
|
||||
# Refuse to touch a dist the game is currently running from.
|
||||
$running = Get-Process rpl4opt -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Path -like "$dist\*" }
|
||||
@@ -83,6 +100,10 @@ Set-Content -Path "$dist\CONTROLS.txt" -Encoding ascii -Value $controls
|
||||
# without a charset the typography arrives as mojibake. Written without a
|
||||
# BOM so the charset declaration is the only thing speaking.
|
||||
$controlsPage = Get-Content (Join-Path $root 'docs\rp412-controls.html') -Raw -Encoding UTF8
|
||||
# Stamp the shipped copy with the build's own version. The source keeps a
|
||||
# readable one for publishing; only "4.12.<n>" is touched, which on this
|
||||
# page is always the version and never anything else.
|
||||
$controlsPage = [regex]::Replace($controlsPage, '4\.12\.\d+', $version)
|
||||
$page = @"
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@@ -401,7 +422,7 @@ set RP412JOYCONFIG=
|
||||
"@
|
||||
|
||||
Set-Content -Path "$dist\README.txt" -Encoding ascii -Value @"
|
||||
Red Planet 4.12.7
|
||||
Red Planet $version
|
||||
=================
|
||||
|
||||
Run start-fullscreen.bat for borderless over the whole monitor, or
|
||||
@@ -471,7 +492,7 @@ $size = (Get-ChildItem $dist -Recurse | Measure-Object Length -Sum).Sum
|
||||
Write-Host ("dist ready: {0:N1} MB" -f ($size / 1MB))
|
||||
|
||||
if ($Zip) {
|
||||
$zipPath = Join-Path $root 'RedPlanet-4.12.7.zip'
|
||||
$zipPath = Join-Path $root "RedPlanet-$version.zip"
|
||||
Write-Host "zipping to $zipPath..."
|
||||
|
||||
# Everything lives under a single RP412\ folder inside the zip, so
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
# ============================================================================
|
||||
# stamp-version.ps1 - write RP_L4\rpl4build.h from the repository's own state
|
||||
# ============================================================================
|
||||
#
|
||||
# The patch number IS the commit count, so a build names the commit it came
|
||||
# from and there is never a question about which changes are in a binary
|
||||
# somebody is holding. Run as RP_L4's pre-build step; also readable by
|
||||
# pack-dist.ps1, so the package and the exe cannot disagree.
|
||||
#
|
||||
# A hardcoded version could not do this: the commit that records "4.12.96"
|
||||
# is itself commit 96, so the file is stale the moment it is committed.
|
||||
#
|
||||
# Usage: powershell -ExecutionPolicy Bypass -File stamp-version.ps1
|
||||
#
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# The product line. Bump this by hand when the line moves; the patch
|
||||
# number after it looks after itself.
|
||||
$line = '4.12'
|
||||
|
||||
$root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$header = Join-Path $root 'RP_L4\rpl4build.h'
|
||||
|
||||
$count = 0
|
||||
$commit = 'nogit'
|
||||
$dirty = 0
|
||||
|
||||
#
|
||||
# Every git call goes through cmd so that stderr never reaches PowerShell's
|
||||
# error stream. Windows PowerShell turns a native command's stderr into
|
||||
# ErrorRecords, and with $ErrorActionPreference = 'Stop' git's routine
|
||||
# "LF will be replaced by CRLF" warning is enough to throw - which silently
|
||||
# skipped the dirty check and stamped every modified build as clean.
|
||||
#
|
||||
try {
|
||||
Push-Location $root
|
||||
$c = cmd /c "git rev-list --count HEAD 2>NUL"
|
||||
if ($LASTEXITCODE -eq 0 -and $c) {
|
||||
$count = [int]$c
|
||||
$commit = (cmd /c "git rev-parse --short HEAD 2>NUL").Trim()
|
||||
#
|
||||
# Tracked modifications only. An untracked scratch file in the tree
|
||||
# is not in the binary, and marking every build dirty for one would
|
||||
# make the marker mean nothing.
|
||||
#
|
||||
cmd /c "git diff --quiet HEAD -- 2>NUL"
|
||||
if ($LASTEXITCODE -ne 0) { $dirty = 1 }
|
||||
}
|
||||
} catch {
|
||||
# no git, or not a repository: fall through to the placeholder below
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
if ($count -eq 0) {
|
||||
# Built outside the repository (a source drop, say). Say so plainly
|
||||
# rather than inventing a number that would sort against real ones.
|
||||
$version = "$line.x"
|
||||
$long = "$line.x (no repository)"
|
||||
} else {
|
||||
$version = "$line.$count"
|
||||
$long = "$version ($commit$(if ($dirty) { '+' } else { '' }))"
|
||||
}
|
||||
|
||||
$content = @"
|
||||
//===========================================================================//
|
||||
// File: rpl4build.h GENERATED - do not edit, do not commit //
|
||||
//---------------------------------------------------------------------------//
|
||||
// Written by stamp-version.ps1 as RP_L4's pre-build step. The patch number //
|
||||
// is the repository's commit count and the hash beside it names the exact //
|
||||
// commit, so a running build always says where it came from. A trailing '+' //
|
||||
// means the tree had uncommitted changes to tracked files when it was built. //
|
||||
//===========================================================================//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define RP412_BUILD_COUNT $count
|
||||
#define RP412_BUILD_COMMIT "$commit"
|
||||
#define RP412_BUILD_DIRTY $dirty
|
||||
#define RP412_VERSION "$version"
|
||||
#define RP412_VERSION_LONG "$long"
|
||||
"@
|
||||
|
||||
#
|
||||
# Only rewrite when something actually changed: an unconditional write
|
||||
# would touch the header on every build and drag RPL4.CPP through a
|
||||
# recompile each time.
|
||||
#
|
||||
$existing = if (Test-Path $header) { [IO.File]::ReadAllText($header) } else { '' }
|
||||
if ($existing -ne $content) {
|
||||
[IO.File]::WriteAllText($header, $content, (New-Object System.Text.ASCIIEncoding))
|
||||
Write-Host "stamp-version: $long"
|
||||
} else {
|
||||
Write-Host "stamp-version: $long (unchanged)"
|
||||
}
|
||||
|
||||
#
|
||||
# Explicitly: this runs as a pre-build step, and the last thing above it is
|
||||
# "git diff --quiet", which exits 1 to mean "there are changes". Letting that
|
||||
# escape would fail the build on every modified tree - the exact case a
|
||||
# developer builds in.
|
||||
#
|
||||
exit 0
|
||||
Reference in New Issue
Block a user