Skip to content

Commit

Permalink
[Mono.Android] Generate AssemblyInformationalVersionAttribute (#259)
Browse files Browse the repository at this point in the history
`Mono.Android.dll` is [supposed to contain][0] an
[`AssemblyInformationalVersionAttribute`][1] `assembly:`-level
attribute which contains the version number, git commit, and various
other bits of information related to which commit `Mono.Android.dll`
"came from."

	var attrs = (System.Reflection.AssemblyInformationalVersionAttribute[])
		typeof (Java.Lang.Object)
		.Assembly
		.GetCustomAttributes(typeof(System.Reflection.AssemblyInformationalVersionAttribute), inherit: true);
	string version = attrs [0].InformationalVersion;
	// version is like "7.0.99.113; git-rev-head:d02845e; git-branch:master"

Unfortunately, in the open-source migration this was lost, and the
above code would throw an `IndexOutOfRangeException`, as
`attrs.Length` would be 0. (Xamarin.Android 7.0 likewise doesn't
contain the `AssemblyInformationalVersionAttribute`. Oops!)

Add `<GitBlame/>`, `<GitCommitsInRange/>`, and
`<ReplaceFileContents/>` tasks, along with various bits of MSBuild-fu,
to use `src/Mono.Android/Properties/AssemblyInfo.cs.in` as a
"template" for the `AssemblyInfo.cs` to include in the
`Mono.Android.dll` build, so that an appropriate
`AssemblyInformationalVersionAttribute` value is present.

[0]: https://developer.xamarin.com/releases/android/xamarin.android_4/xamarin.android_4.14/#Xamarin.Android_4.14.0
[1]: https://msdn.microsoft.com/en-us/library/system.reflection.assemblyinformationalversionattribute(v=vs.110).aspx
  • Loading branch information
jonpryor authored and grendello committed Oct 11, 2016
1 parent a61abd0 commit b620689
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.IO;
using System.Collections.Generic;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.BuildTools.PrepTasks
{
public class GitBlame : Git
{
[Required]
public ITaskItem FileName { get; set; }

public string LineFilter { get; set; }

[Output]
public ITaskItem[] Commits { get; set; }


protected override bool LogTaskMessages {
get { return false; }
}

List<ITaskItem> commits = new List<ITaskItem> ();

public override bool Execute ()
{
Log.LogMessage (MessageImportance.Low, $"Task {nameof (GitBlame)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (FileName)}: {FileName.ItemSpec}");
Log.LogMessage (MessageImportance.Low, $" {nameof (LineFilter)}: {LineFilter}");
Log.LogMessage (MessageImportance.Low, $" {nameof (WorkingDirectory)}: {WorkingDirectory.ItemSpec}");

base.Execute ();

Commits = commits.ToArray ();

Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (Commits)}:");
foreach (var c in Commits) {
Log.LogMessage (MessageImportance.Low, $" [Output] {c.GetMetadata ("CommitHash")} '{c.GetMetadata ("Line")}'");
}

return !Log.HasLoggedErrors;
}

protected override string GenerateCommandLineCommands ()
{
return $"blame \"{Path.GetFullPath (FileName.ItemSpec)}\"";
}

protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
if (string.IsNullOrEmpty (singleLine))
return;
if (LineFilter != null && !singleLine.Contains (LineFilter))
return;
var commitHash = GetCommitHash (singleLine);
var commit = new TaskItem (commitHash);
commit.SetMetadata ("CommitHash", commitHash);
commit.SetMetadata ("Line", singleLine);
commits.Add (commit);
}

static string GetCommitHash (string line)
{
int i = line?.IndexOf (' ') ?? -1;
return i >= 0
? line?.Substring (0, i)
: line;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.BuildTools.PrepTasks
{
public class GitCommitsInRange : Git
{
[Output]
public int CommitCount { get; set; }

[Required]
public string StartCommit { get; set; }

public string EndCommit { get; set; }

protected override bool LogTaskMessages {
get { return false; }
}

public GitCommitsInRange ()
{
}

public override bool Execute ()
{
Log.LogMessage (MessageImportance.Low, $"Task {nameof (GitCommitsInRange)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (StartCommit)}: {StartCommit}");
Log.LogMessage (MessageImportance.Low, $" {nameof (EndCommit)}: {EndCommit}");
Log.LogMessage (MessageImportance.Low, $" {nameof (WorkingDirectory)}: {WorkingDirectory.ItemSpec}");

base.Execute ();

Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (CommitCount)}: {CommitCount}");

return !Log.HasLoggedErrors;
}

protected override string GenerateCommandLineCommands ()
{
string endCommit = string.IsNullOrEmpty (EndCommit)
? "HEAD"
: EndCommit;
return $"log {StartCommit}..{endCommit} --oneline";
}

protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
if (string.IsNullOrEmpty (singleLine))
return;
CommitCount++;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.BuildTools.PrepTasks
{
public class ReplaceFileContents : Task
{
[Required]
public ITaskItem SourceFile { get; set; }

[Required]
public ITaskItem DestinationFile { get; set; }

public string[] Replacements { get; set; }

public override bool Execute ()
{
Log.LogMessage (MessageImportance.Low, $"Task {nameof (ReplaceFileContents)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (SourceFile)}: {SourceFile.ItemSpec}");
Log.LogMessage (MessageImportance.Low, $" {nameof (DestinationFile)}: {DestinationFile.ItemSpec}");
Log.LogMessage (MessageImportance.Low, $" {nameof (Replacements)}:");
foreach (var replacement in Replacements) {
Log.LogMessage (MessageImportance.Low, $" {replacement}");
}

File.Delete (DestinationFile.ItemSpec);

var r = GetReplacementInfo (Replacements);
using (var i = File.OpenText (SourceFile.ItemSpec))
using (var o = File.CreateText (DestinationFile.ItemSpec)) {
string line;
while ((line = i.ReadLine ()) != null) {
foreach (var e in r) {
line = line.Replace (e.Key, e.Value);
}
o.WriteLine (line);
}
}

return !Log.HasLoggedErrors;
}

static readonly char[] Separator = new [] { '=' };

static Dictionary<string, string> GetReplacementInfo (string[] replacements)
{
var r = new Dictionary<string, string> (replacements?.Length ?? 0);
if (replacements == null)
return r;
foreach (var e in replacements) {
if (string.IsNullOrEmpty (e))
continue;
var kvp = e.Split (Separator, 2, StringSplitOptions.RemoveEmptyEntries);
r.Add (kvp [0], kvp.Length > 1 ? kvp [1] : "");
}
return r;
}
}
}
3 changes: 3 additions & 0 deletions build-tools/xa-prep-tasks/xa-prep-tasks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\GitCommitHash.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\SystemUnzip.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\Which.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\GitBlame.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\GitCommitsInRange.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\ReplaceFileContents.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="xa-prep-tasks.targets" />
Expand Down
46 changes: 46 additions & 0 deletions src/Mono.Android/Mono.Android.targets
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask AssemblyFile="..\..\bin\Build$(Configuration)\xa-prep-tasks.dll" TaskName="Xamarin.Android.BuildTools.PrepTasks.GitBlame" />
<UsingTask AssemblyFile="..\..\bin\Build$(Configuration)\xa-prep-tasks.dll" TaskName="Xamarin.Android.BuildTools.PrepTasks.GitBranch" />
<UsingTask AssemblyFile="..\..\bin\Build$(Configuration)\xa-prep-tasks.dll" TaskName="Xamarin.Android.BuildTools.PrepTasks.GitCommitHash" />
<UsingTask AssemblyFile="..\..\bin\Build$(Configuration)\xa-prep-tasks.dll" TaskName="Xamarin.Android.BuildTools.PrepTasks.GitCommitsInRange" />
<UsingTask AssemblyFile="..\..\bin\Build$(Configuration)\xa-prep-tasks.dll" TaskName="Xamarin.Android.BuildTools.PrepTasks.ReplaceFileContents" />
<ItemGroup>
<Compile Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
</ItemGroup>
<Target Name="_BuildJavaInterop"
BeforeTargets="BeforeResolveReferences"
Inputs="$(JavaInteropFullPath)\src\Java.Interop\Java.Interop.csproj"
Expand All @@ -16,6 +24,44 @@
DestinationFolder="$(OutputPath)\..\v1.0"
/>
</Target>
<Target Name="_BuildAssemblyInfo_cs"
BeforeTargets="CoreCompile"
Condition="!Exists ('$(IntermediateOutputPath)AssemblyInfo.cs')"
Inputs="Properties\AssemblyInfo.cs.in"
Outputs="$(IntermediateOutputPath)AssemblyInfo.cs">
<GitBlame
FileName="$(XamarinAndroidSourcePath)\Configuration.props"
LineFilter="&lt;ProductVersion&gt;"
WorkingDirectory="$(XamarinAndroidSourcePath)"
ToolPath="$(GitToolPath)"
ToolExe="$(GitToolExe)">
<Output TaskParameter="Commits" ItemName="_XAVersionCommit" />
</GitBlame>
<GitCommitsInRange
StartCommit="%(_XAVersionCommit.CommitHash)"
WorkingDirectory="$(XamarinAndroidSourcePath)"
ToolPath="$(GitToolPath)"
ToolExe="$(GitToolExe)">
<Output TaskParameter="CommitCount" PropertyName="_XACommitCount" />
</GitCommitsInRange>
<GitCommitHash
WorkingDirectory="$(XamarinAndroidSourcePath)"
ToolPath="$(GitToolPath)"
ToolExe="$(GitToolExe)">
<Output TaskParameter="AbbreviatedCommitHash" PropertyName="_XAHash" />
</GitCommitHash>
<GitBranch
WorkingDirectory="$(XamarinAndroidSourcePath)"
ToolPath="$(GitToolPath)"
ToolExe="$(GitToolExe)">
<Output TaskParameter="Branch" PropertyName="_XABranch" />
</GitBranch>
<ReplaceFileContents
SourceFile="Properties\AssemblyInfo.cs.in"
DestinationFile="$(IntermediateOutputPath)AssemblyInfo.cs"
Replacements="@PACKAGE_VERSION@=$(ProductVersion);@PACKAGE_VERSION_BUILD@=$(_XACommitCount);@PACKAGE_HEAD_REV@=$(_XAHash);@PACKAGE_HEAD_BRANCH@=$(_XABranch)">
</ReplaceFileContents>
</Target>
<Target Name="_BuildJNIEnv"
BeforeTargets="CoreCompile"
Inputs="..\..\bin\Build$(Configuration)\jnienv-gen.exe"
Expand Down
20 changes: 0 additions & 20 deletions src/Mono.Android/Properties/AssemblyInfo.cs

This file was deleted.

7 changes: 4 additions & 3 deletions src/Mono.Android/Properties/AssemblyInfo.cs.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
// Jonathan Pryor ([email protected])
//
// Copyright 2014 Xamarin, Inc.
// Copyright 2016 Microsoft Corporation.

using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: AssemblyInformationalVersion ("@PACKAGE_VERSION_MAJOR@.@PACKAGE_VERSION_MINOR@.@PACKAGE_VERSION_REV@.@PACKAGE_VERSION_BUILD@; git-rev-head:@PACKAGE_HEAD_REV@; git-branch:@PACKAGE_HEAD_BRANCH@")]
[assembly: AssemblyInformationalVersion ("@PACKAGE_VERSION@.@PACKAGE_VERSION_BUILD@; git-rev-head:@PACKAGE_HEAD_REV@; git-branch:@PACKAGE_HEAD_BRANCH@")]
[assembly: AssemblyTitle ("Mono.Android.dll")]
[assembly: AssemblyProduct ("@PACKAGE_LONG_NAME@")]
[assembly: AssemblyProduct ("Xamarin.Android")]
// FIXME: Probably need to add Copyright 2009-2011 Novell Inc.
// [assembly: AssemblyCopyright ("Copyright 2011-2014 Xamarin Inc.")]
[assembly: AssemblyCompany ("Xamarin Inc.")]
[assembly: AssemblyCompany ("Microsoft Corporation")]

// Required for System.Drawing.dll to be able to access System.Drawing.KnownColors
[assembly: InternalsVisibleTo ("System.Drawing, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]

0 comments on commit b620689

Please sign in to comment.