# ============================================================================ # 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