Set git commit hash as dll version number in visual studio

I am developing a project using visual studio 2013 and git.

I have to redistribute some project libraries, so I would like to set their version number with the current git commit hash, so I can be sure which version of the library they are using.

Is there a way to put the hash as the version number in an automatic way, Ie with a pre-build event, instead of doing it manually each time?

+5
source share
2 answers

Below are some fragments of a possible implementation for your own projects using resource files. The idea is to add a separate property page to the project, which has a pre-build event that creates a .res file based on the git commit hash code and which also adds this .res file as a resource. Here is a list of properties:

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros" /> <PropertyGroup> <VersionResourceOut>$(MSBuildProjectDirectory)\version.res</VersionResourceOut> </PropertyGroup> <ItemGroup> <Resource Include="$(VersionResourceOut)" /> </ItemGroup> <Import Project="$(BuildToolsDir)tools\versionrc.targets" /> <Target Name="CreateGitVersionResource" BeforeTargets="BuildGenerateSources"> <CallTarget Targets="CreateGitVersionResInBuild" /> <MakeSameWriteTime SourceFile="$(OutDir)$(TargetName)$(TargetExt)" DestFile="$(VersionResourceOut)"/> </Target> </Project> 

Tools $ (BuildToolsDir) \ versionrc.targets is the file in which the resource file is actually created. The full implementation is quite lengthy, because it also works for svn and allows a bunch of settings - a bit for publication here, so I just lay out her meat:

  • the commit hash is stored in the msbuild property, the command to get it

     git --work-tree=$(GitVersionDir) --git-dir=$(GitVersionDir)\.git rev-parse --short HEAD 

    where $ (GitVersionDir) is usually set to $ (MsbuildProjectDirectory), since we have most of the .vcxproj files in the original root.

  • I also like that the build date should be included, so the property that ends up in the FileDescription entry of the StringFileinfo block is

     <FileDesc>$(GitVersion) $([System.DateTime]::Now.ToString('HH:mm:ss dd/MM/yyyy'))</FileDesc> 
  • actual file / product version, company name and other fields are extracted from other sources. Usually we have a common header file that defines all the VRC_XXX macros needed for the RC file template (see below), and a header file for each project containing, for example, #define VRC_FILEDESC "Project Foo", and these headers are combined using tasks ReadLinesFromFile / WriteLinesToFile. In any case, the idea is to end up with a header file, e.g.

     #define VRC_FILEVERSION 4,4,1,0 #define VRC_PRODUCTVERSION 4.4.1.0 #define VRC_COMPANYNAME MyCompany #define VRC_PRODUCTNAME VRC_COMPANYNAME Libraries #define VRC_FILEDESC Project Foo #define VRC_FILEDESCRIPTION VRC_FILEDESC VRC_FILEDESCGIT 

    Which path is stored in the $ (VersionMainInclude) property.

  • all of this is sent to rc.exe to create the .res file. A complete team is something like

     rc /d VRC_INCLUDE=$(VersionMainInclude) /d VRC_ORIGINALFILENAME=$(TargetName)$(TargetExt) /d VRC_FILETYPE=$(FileType) /d VRC_FILEDESCGIT=$(FileDesc) /d VRC_COPYRIGHT=VRC_COMPANYNAME \251 $([System.DateTime]::Now.ToString(`yyyy`)) /fo $(VersionResourceOut) $(MsBuildThisFileDirectory)version.rc 
  • Note the MakeSameWriteTime trick to set the modified time of the .res file as well as the output file, to ensure that the prebuild event does not start new assemblies every time the .res file is created. There may be better ways to do this, but this works for me:

     <UsingTask TaskName="MakeSameWriteTime" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" > <ParameterGroup> <SourceFile Required="true" ParameterType="System.String"/> <DestFile Required="true" ParameterType="System.String"/> </ParameterGroup> <Task> <Code Type="Fragment" Language="cs"> <![CDATA[ System.IO.File.SetLastWriteTime( DestFile, System.IO.File.GetLastWriteTime( SourceFile ) );]]> </Code> </Task> </UsingTask> 

This is the complete .rc template:

 #include <winver.h> #define stringize( x ) stringizei( x ) #define stringizei( x ) #x #ifdef VRC_INCLUDE #include stringize( VRC_INCLUDE ) #endif #ifdef _WIN32 LANGUAGE 0x9,0x1 #pragma code_page( 1252 ) #endif 1 VERSIONINFO FILEVERSION VRC_FILEVERSION PRODUCTVERSION VRC_PRODUCTVERSION FILEFLAGSMASK 0x1L FILEFLAGS VS_FF_DEBUG FILEOS VOS__WINDOWS32 FILETYPE VRC_FILETYPE BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", stringize( VRC_COMPANYNAME ) VALUE "FileDescription", stringize( VRC_FILEDESCRIPTION ) VALUE "FileVersion", stringize( VRC_FILEVERSION ) VALUE "LegalCopyright", stringize( VRC_COPYRIGHT ) VALUE "InternalName", stringize( VRC_ORIGINALFILENAME ) VALUE "OriginalFilename", stringize( VRC_ORIGINALFILENAME ) VALUE "ProductName", stringize( VRC_PRODUCTNAME ) VALUE "ProductVersion", stringize( VRC_PRODUCTVERSION ) END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END 
+2
source

Take a look at my modification of the MSBuild Community Tasks project at https://github.com/Bitrete/msbuildtasks . I added a task called SemanticVersionGitDescribe. See a usage example below.

 <SemanticVersionGitDescribe LocalPath="$(MSBuildProjectDirectory)"> <Output TaskParameter="SemanticVersion" PropertyName="Version"/> <Output TaskParameter="IsRelease" PropertyName="Release"/> <Output TaskParameter="AdditionalCommitsCount" PropertyName="AdditionalCommits"/> <Output TaskParameter="Hash" PropertyName="Hash"/> </SemanticVersionGitDescribe> 

And don't forget to put the version string with the hash only in AssemblyInformalVersion . Because the AssemblyVersion property accepts only numbers limited to periods.

  <Target Name="UpdateAssemblyInfoVersion" DependsOnTargets="Prepare; GetGitVersion"> <Copy SourceFiles="$(EtcPath)\common\CommonAssemblyInfo.cs" DestinationFiles="$(OutputPath)\CommonAssemblyInfo.cs"/> <FileUpdate Files="$(EtcPath)\common\CommonAssemblyInfo.cs" Multiline="true" Singleline="false" Regex="(AssemblyVersion)\(&quot;([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?&quot;\)" ReplacementText="$1(&quot;$(Version).$(AdditionalCommits)&quot;)" /> <FileUpdate Files="$(EtcPath)\common\CommonAssemblyInfo.cs" Multiline="true" Singleline="false" Regex="(AssemblyFileVersion)\(&quot;([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?&quot;\)" ReplacementText="$1(&quot;$(Version).$(AdditionalCommits)&quot;)" /> <FileUpdate Condition=" $(Release) == False " Files="$(EtcPath)\common\CommonAssemblyInfo.cs" Multiline="true" Singleline="false" Regex="(AssemblyInformationalVersion)\(&quot;([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?&quot;\)" ReplacementText="$1(&quot;$(Version).$(AdditionalCommits)-g$(Hash)&quot;)" /> <FileUpdate Condition=" $(Release) == True " Files="$(EtcPath)\common\CommonAssemblyInfo.cs" Multiline="true" Singleline="false" Regex="(AssemblyInformationalVersion)\(&quot;([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?&quot;\)" ReplacementText="$1(&quot;$(Version)&quot;)" /> </Target> 
+3
source

Source: https://habr.com/ru/post/1240412/


All Articles