Skip to content

Commit

Permalink
Version 2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
MircoBabin committed Feb 22, 2024
1 parent 468b263 commit 2a0bcbc
Show file tree
Hide file tree
Showing 26 changed files with 1,040 additions and 186 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# BuildStamp changelog

## Version 2.2
Release date: 22 february 2024

* add: "stamp-versioninfo" command for adjusting VersionInfo.rc file.

## Version 2.1
Release date: 6 april 2023

Expand Down
73 changes: 69 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/MircoBabin/BuildStamp/blob/master/LICENSE.md)

# BuildStamp
BuildStamp is a compilation tool. It stamps the compilation date/time into a source file. Use BuildStamp in the Pre-build event to inject compilation date/time. It can also digitally sign any executable. The codesign certificate can be on disk or in [KeePass](https://keepass.info/ "KeePass").
BuildStamp is a compilation tool. Use BuildStamp in the Pre-build event to inject compilation date/time and adjust the versionumber in the VersionInfo resource file.

- It stamps the compilation date/time into a source file
- It updates the VersionInfo.rc resource file with a versionumber listed in a sourcefile.
- It can also digitally sign any executable. The codesign certificate can be on disk or in [KeePass](https://keepass.info/ "KeePass").

# Download binary
For Windows (.NET framework 4), [the latest version can be found here](https://github.com/MircoBabin/BuildStamp/releases/latest "Latest Version").
Expand All @@ -19,7 +23,7 @@ The minimum .NET framework required is 4.0.
Execute **BuildStamp.exe** without parameters to view the help.

```
BuildStamp version 2.0
BuildStamp version 2.2
https://github.com/MircoBabin/BuildStamp - MIT license
BuildStamp is a compilation tool.
Expand Down Expand Up @@ -69,6 +73,66 @@ end.
It is recommended for the <source-filename> to only contain BuildStamp metadata.
And no other metadata like versionnumber, buildnumber, copyright, etc.
Because adding other metadata does not play well with version control (Git).
----------------------------------------------------
----------------------------------------------------
--- ---
--- Stamp VersionInfo resource file (.rc) ---
--- ---
----------------------------------------------------
----------------------------------------------------
Syntax: BuildStamp.exe stamp-versioninfo --versionfilename <versionSource-filename> --language <language>
--filename <ResourceCompiler-filename.rc>
{--outputfilename <output-filename>}
{--launchdebugger}
- With --language the programming language of <versionSource-filename> is specified.
- When --outputfilename is ommitted, the <ResourceCompiler-filename.rc> will be overwritten.
- When the debug switch --launchdebugger is encountered, a request to launch the debugger is started.
<versionSource-filename> has to contain the version string between 2 markers. E.g. for Pascal source:
unit Version;
interface
const VersionString =
{<BUILDSTAMP:BEGINVERSION>}
'4.076'
{<BUILDSTAMP:ENDVERSION>};
implementation
end.
<ResourceCompiler-filename.rc> has to contain the version number.
// <BUILDSTAMP:BEGINSTAMP>
Inside <BUILDSTAMP:VERSION_4PARTS_COMMA_SEPARATED> is replaced with "major,minor,patch,build".
Inside <BUILDSTAMP:VERSION_4PARTS_POINT_SEPARATED> is replaced with "major.minor.patch.build".
Inside <BUILDSTAMP:VERSION_FULL> is replaced with the full version inside <versionSource-filename>.
// <BUILDSTAMP:ENDSTAMP>
e.g. for Pascal resource file: BuildStamp.exe stamp-versioninfo --versionfilename c:\...\Version.pas --language pascal --filename c:\...\VersionInfo.rc
VersionInfo.rc contents:
// <BUILDSTAMP:BEGINSTAMP>
1 VERSIONINFO
FILEVERSION <BUILDSTAMP:VERSION_4PARTS_COMMA_SEPARATED>
PRODUCTVERSION <BUILDSTAMP:VERSION_4PARTS_COMMA_SEPARATED>
FILEOS 0x4
FILETYPE 0x1
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE L"CompanyName", L"My Company\000"
VALUE L"FileDescription", L"My Program\000"
VALUE L"FileVersion", L"<BUILDSTAMP:VERSION_4PARTS_POINT_SEPARATED>>\000"
VALUE L"LegalCopyright", L"(c) My Company\000"
VALUE L"ProductName", L"My Program\000"
VALUE L"ProductVersion", L"<BUILDSTAMP:VERSION_FULL>\000"
VALUE L"ProgramID", L"MyProgram\000" // Delphi specific. Must be the projectname, e.g. MyProgram.dproj
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409 0x04E4
}
}
// <BUILDSTAMP:ENDSTAMP>
Expand Down Expand Up @@ -140,9 +204,10 @@ OTHER DEALINGS IN THE SOFTWARE.
- [Digitally sign documentation](docs/DigitallySign.md "Digitally sign documentation")

# Why
Delphi doesn't have a good way to embed the compilation date/time into the executable. There is a solution reading the linker timestamp from the PE Header of the executable. But that PE Header solution is too complex and low-level in my opinion.
Delphi doesn't have a good way to embed the compilation date/time into the executable. There is a solution reading the linker timestamp from the PE Header of the executable. But that PE Header solution is too complex and low-level in my opinion.
Delphi also lacks updating the Version Info resource in a usable way, when the versionnumber is already present in a sourcefile.

So I wrote BuildStamp for injecting the compilation date/time via Pre-build event into a source file. The modified source file is then compiled into the executable.
So I wrote BuildStamp for injecting the compilation date/time and adjusting the Version Info via Pre-build event. The modified source file is then compiled into the executable.

The Microsoft provided [signtool.exe](https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool "signtool.exe") can only be officially installed with the "Microsoft Windows Software Development Kit (SDK)".
I wanted a standalone executable that can be distributed standalone. And I wanted the ability to store the code signing certificate in [KeePass](https://keepass.info/ "KeePass"). That's why I added the "sign" command.
Expand Down
Binary file removed assets/Release/BuildStamp-2.1-debugpack.zip
Binary file not shown.
Binary file removed assets/Release/BuildStamp-2.1.zip
Binary file not shown.
Binary file added assets/Release/BuildStamp-2.2-debugpack.zip
Binary file not shown.
Binary file added assets/Release/BuildStamp-2.2.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion assets/Release/release.download.zip.url-location
Original file line number Diff line number Diff line change
@@ -1 +1 @@
https://github.com/MircoBabin/BuildStamp/releases/download/2.1/BuildStamp-2.1.zip
https://github.com/MircoBabin/BuildStamp/releases/download/2.2/BuildStamp-2.2.zip
218 changes: 207 additions & 11 deletions docs/Delphi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,166 @@ c:\...\prebuild.bat "$(Config)" "$(OUTPUTPATH)"

![Screenshot](BuildEvents.png)

* Second: install ```c:\...\prebuild.bat```. Adjust BuildStampExe and BuildStampSrc vars.
* Second: install ```c:\...\prebuild.bat```. Adjust the BuildStampExe var.

```bat
@echo off
setlocal
rem ---------------------
rem Adjust these two vars
rem ---------------------
rem -----------------
rem Adjust these vars
rem -----------------
set "BuildStampExe=%~dp0..\..\bin\BuildStamp\BuildStamp.exe"
set "BuildStampSrc=%~dp0MyProject\Compiled.pas"
rem ---------------------
rem set "BuildRsvarsBat=C:\Program Files (x86)\Embarcadero\Studio\22.0\bin\rsvars.bat"
rem set "BuildStampSrc=%~dp0MyProject\Compiled.pas"
rem set "BuildVersionSrc=%~dp0MyProject\Version.pas"
rem set "BuildVersionRc=%~dp0MyProject\Resources\ApplicationVersionInfo\VersionInfo.rc"
rem -----------------
set "ProjectConfig=%~1"
set "ProjectOutputFilename=%~2"
call :getPath "ProjectOutputPath" "%ProjectOutputFilename%"
set "LogFile=%~dp0prebuild.log"
echo --- PREBUILD.BAT > "%LogFile%"
set "LogFile=%~dp0AadresPrebuild.log"
echo --- > "%LogFile%"
echo --- PREBUILD.BAT begin >> "%LogFile%"
echo --- >> "%LogFile%"
echo Configuration: >> "%LogFile%"
echo %ProjectConfig% >> "%LogFile%"
echo. >> "%LogFile%"
echo Output filename: >> "%LogFile%"
echo %ProjectOutputFilename% >> "%LogFile%"
echo. >> "%LogFile%"
echo Output path: >> "%LogFile%"
echo %ProjectOutputPath% >> "%LogFile%"
echo. >> "%LogFile%"
echo BuildStamp.exe: >> "%LogFile%"
echo %BuildStampExe% >> "%LogFile%"
echo. >> "%LogFile%"
:stepCompilationTime
if "%BuildStampSrc%" == "" goto stepVersionInfo
rem ---------------------
rem Compilation time
rem ---------------------
echo --- >> "%LogFile%"
echo --- Stamp compilation time >> "%LogFile%"
echo --- >> "%LogFile%"
echo BuildStamp source file: >> "%LogFile%"
echo %BuildStampSrc% >> "%LogFile%"
echo. >> "%LogFile%"
echo "%BuildStampExe%" stamp --filename "%BuildStampSrc%" --language pascal >> "%LogFile%"
"%BuildStampExe%" stamp --filename "%BuildStampSrc%" --language pascal >> "%LogFile%" 2>&1
if errorlevel 1 exit /b 1
echo. >> "%LogFile%"
:stepVersionInfo
if "%BuildVersionRc%" == "" goto stepEnd
rem ---------------------
rem VersionInfo.rc
rem ---------------------
echo --- >> "%LogFile%"
echo --- Stamp versioninfo >> "%LogFile%"
echo --- >> "%LogFile%"
echo BuildStamp version source file: >> "%LogFile%"
echo %BuildVersionSrc% >> "%LogFile%"
echo. >> "%LogFile%"
echo BuildStamp resource file: >> "%LogFile%"
echo %BuildVersionRc% >> "%LogFile%"
echo. >> "%LogFile%"
echo "%BuildStampExe%" stamp-versioninfo --versionfilename "%BuildVersionSrc%" --language pascal --filename "%BuildVersionRc%" >> "%LogFile%"
"%BuildStampExe%" stamp-versioninfo --versionfilename "%BuildVersionSrc%" --language pascal --filename "%BuildVersionRc%" >> "%LogFile%" 2>&1
if errorlevel 1 exit /b 1
call :getPath "BuildVersionRcPath" "%BuildVersionRc%"
call :getOnlyFilenameWithoutExtension "BuildVersionRcFilenameWithoutExtension" "%BuildVersionRc%"
call :rcBuild "%BuildRsvarsBat%" "%BuildVersionRcPath%" "%BuildVersionRcFilenameWithoutExtension%"
if errorlevel 1 exit /b 1
echo. >> "%LogFile%"
:stepEnd
rem ---------------------
rem End
rem ---------------------
echo --- >> "%LogFile%"
echo --- PREBUILD.BAT ended >> "%LogFile%"
echo --- >> "%LogFile%"
exit /b 0
:getPath
set "%~1=%~dp2"
goto :eof
:getOnlyFilenameWithoutExtension
set "%~1=%~n2"
goto :eof
:rcBuild
rem %1 = full path to rsvars.bat (C:\Program Files (x86)\Embarcadero\Studio\22.0\bin\rsvars.bat)
rem %2 = path (c:\...\Resources)
rem %3 = filename only without extension (VersionInfo)
echo. >> "%LogFile%"
echo --- [BEGIN] Compile resource %~3.rc >> "%LogFile%"
echo .. rsvars.bat = %~1 >> "%LogFile%"
echo .. .rc filename-path-only = %~2 >> "%LogFile%"
echo .. .rc filename-only-without-path-and-extension = %~3 >> "%LogFile%"
setlocal
pushd
rem
rem Rad Studio Command Prompt
rem
echo .. [BEGIN] MSBUILD setup >> "%LogFile%"
echo .. call "%~1" >> "%LogFile%"
if exist "%~1" goto rcBuild1
echo File does not exist. >> "%LogFile%"
goto rcBuildError
:rcBuild1
call "%~1" >> "%LogFile%" 2>&1
echo .. [END] MSBUILD setup >> "%LogFile%"
echo .. Directory: %~2 >> "%LogFile%"
echo .. Resource file: %~3.rc >> "%LogFile%"
echo .. Compiled resource: %~3.res >> "%LogFile%"
echo .. [BEGIN] MSBUILD >> "%LogFile%"
cd /d "%~2"
echo .. Current directory: %CD% >> "%LogFile%"
del /q "%~3.res" >nul 2>&1
echo .. rc /v "%~3.rc" >> "%LogFile%"
rc /v "%~3.rc" >> "%LogFile%" 2>&1
echo .. [END] MSBUILD >> "%LogFile%"
if exist "%BuildVersionRcFilenameWithoutExtension%.res" goto rcBuildOk
:rcBuildError
echo --- [ERROR] Compiling resource %~3.rc failed >> "%LogFile%"
echo. >> "%LogFile%"
popd
exit /b 1
:rcBuildOk
echo --- [SUCCESS] Compiled resource %~3.rc >> "%LogFile%"
echo. >> "%LogFile%"
popd
exit /b 0
```

## Stamping the timestamp of compilation into a sourcefile

* Third: add Compiled.pas to the project.

```pas
Expand All @@ -70,6 +186,86 @@ end.
```

* Fourth: Commit prebuild.bat and Compiled.pas into version control (Git).
* Fourth: adjust the prebuild.bat file created in the second step. Uncomment and adjust the BuildStampSrc var.

* Fifth: Commit prebuild.bat and Compiled.pas into version control (Git).

* Sixth: Build the project from the Delphi IDE. And check the stamped compilation date/time.

## Automatic updating of VersionInfo resource

* Third: add Version.pas to the project.

```pas
unit Version;
interface
const VersionString =
{<BUILDSTAMP:BEGINVERSION>}
'4.076'
{<BUILDSTAMP:ENDVERSION>};
implementation
end.
```

* Fourth: add file Resources\ApplicationVersionInfo\VersionInfo.pas, but don't include in the Delphi project.

```rc
// <BUILDSTAMP:BEGINSTAMP>
1 VERSIONINFO
FILEVERSION <BUILDSTAMP:VERSION_4PARTS_COMMA_SEPARATED>
PRODUCTVERSION <BUILDSTAMP:VERSION_4PARTS_COMMA_SEPARATED>
FILEOS 0x4
FILETYPE 0x1
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE L"CompanyName", L"My Company\000"
VALUE L"FileDescription", L"My Program\000"
VALUE L"FileVersion", L"<BUILDSTAMP:VERSION_4PARTS_POINT_SEPARATED>>\000"
VALUE L"LegalCopyright", L"(c) My Company\000"
VALUE L"ProductName", L"My Program\000"
VALUE L"ProductVersion", L"<BUILDSTAMP:VERSION_FULL>\000"
VALUE L"ProgramID", L"MyProgram\000" // Delphi specific. Must be the projectname, e.g. MyProgam.dproj
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409 0x04E4
}
}
// <BUILDSTAMP:ENDSTAMP>
```

* Fifth: adjust the prebuild.bat file created in the second step. Uncomment and adjust the BuildRsvarsBat, BuildVersionSrc and BuildVersionRc vars.

* Sixth: adjust the project sourcefile (e.g. MyProgram.dpr), include ```{$R Resources\ApplicationVersionInfo\VersionInfo.res}```.

```pas
program MyProgram;
{$R Resources\ApplicationVersionInfo\VersionInfo.res}
uses ...;
{$R *.res}
begin
end.
```


* Seventh: disable Version Info in the project options.

![Screenshot](VersionInfo.png)

* Eighth: Commit prebuild.bat, Version.pas, VersionInfo.rc and MyProgram.dpr into version control (Git).

* Fifth: Build the project from the Delphi IDE. And check the stamped compilation date/time.
* Ninth: Build the project from the Delphi IDE. And check the details of the produced executable.
Binary file added docs/Delphi/VersionInfo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 2a0bcbc

Please sign in to comment.