我正在使用visual studio 2013和git开发一个项目。
我必须分发项目的一些库,所以我想用当前的git commit hash设置它们的版本号,所以我可以确定它们正在使用哪个库版本。
有没有办法以自动方式将哈希作为版本号,即I.e。使用预构建事件,而不是每次都手动执行?
答案 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)\("([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?"\)"
ReplacementText="$1("$(Version).$(AdditionalCommits)")" />
<FileUpdate Files="$(EtcPath)\common\CommonAssemblyInfo.cs"
Multiline="true"
Singleline="false"
Regex="(AssemblyFileVersion)\("([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?"\)"
ReplacementText="$1("$(Version).$(AdditionalCommits)")" />
<FileUpdate Condition=" $(Release) == False "
Files="$(EtcPath)\common\CommonAssemblyInfo.cs"
Multiline="true"
Singleline="false"
Regex="(AssemblyInformationalVersion)\("([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?"\)"
ReplacementText="$1("$(Version).$(AdditionalCommits)-g$(Hash)")" />
<FileUpdate Condition=" $(Release) == True "
Files="$(EtcPath)\common\CommonAssemblyInfo.cs"
Multiline="true"
Singleline="false"
Regex="(AssemblyInformationalVersion)\("([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?"\)"
ReplacementText="$1("$(Version)")" />
</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>