在Visual Studio中将git commit hash设置为dll版本号

时间:2016-01-12 08:25:07

标签: git visual-studio versioning

我正在使用visual studio 2013和git开发一个项目。

我必须分发项目的一些库,所以我想用当前的git commit hash设置它们的版本号,所以我可以确定它们正在使用哪个库版本。

有没有办法以自动方式将哈希作为版本号,即I.e。使用预构建事件,而不是每次都手动执行?

2 个答案:

答案 0 :(得分:3)

https://github.com/Bitrete/msbuildtasks查看我对MSBuild社区任务项目的修改。我添加了一个名为SemanticVersionGitDescribe的任务。请参阅下面的使用示例。

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

并且不要忘记将带有哈希的版本字符串仅放在AssemblyInformalVersion属性中。因为AssemblyVersion属性只接受以句点分隔的数字。

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

答案 1 :(得分:2)

以下是使用资源文件的本机项目的可能实现的一些片段。这个想法是向项目添加一个属性表,该属性表有一个prebuild事件,它根据git commit hash创建一个.res文件,并且还将此.res文件作为资源添加。这是属性表:

<?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>

$(BuildToolsDir)工具\ versionrc.targets文件是完成资源文件的实际创建的位置。完整的实现是相当冗长的,因为它也适用于svn,并允许一堆定制 - 有点多发布在这里所以我只是布置它的肉:

  • 提交哈希存储在msbuild属性中,获取它的命令是

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

    其中$(GitVersionDir)通常设置为$(MsbuildProjectDirectory),因为我们在源根目录中有大多数.vcxproj文件。

  • 我也喜欢要包含的构建日期,因此最终进入StringFileinfo块的FileDescription条目的属性是

    <FileDesc>$(GitVersion) $([System.DateTime]::Now.ToString('HH:mm:ss dd/MM/yyyy'))</FileDesc>
    
  • 从其他地方获取实际文件/产品版本,公司名称和其他字段。通常我们有一个公共头文件,用于定义RC文件模板所需的所有VRC_XXX宏(见下文),以及一个包含例如文件的每个项目头文件。 #define VRC_FILEDESC“Project Foo”,并使用ReadLinesFromFile / WriteLinesToFile任务合并这些头文件。无论如何,这个想法最终会得到像

    这样的头文件
    #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
    

    whos路径存储在$(VersionMainInclude)属性中。

  • 所有这些都被送到rc.exe以创建.res文件。完整命令类似于

    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
    
  • 请注意{。{1}}技巧将.res文件的修改时间设置为与输出文件相同,以确保预建事件每次在.res文件中都不会触发新构建产生。可能有更好的方法来做到这一点,但这个对我有用:

    MakeSameWriteTime

这是使用的完整.rc模板:

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