Add SharedFramework MSI Authoring

This commit is contained in:
Matt Ellis 2016-03-08 19:32:31 -08:00
parent 04d21e6693
commit e6bcfee4a4
12 changed files with 413 additions and 3 deletions

View file

@ -28,6 +28,8 @@ namespace Microsoft.DotNet.Cli.Build
private static string SharedHostMsi { get; set; }
private static string SharedFrameworkMsi { get; set; }
private static string Engine { get; set; }
private static string MsiVersion { get; set; }
@ -67,6 +69,7 @@ namespace Microsoft.DotNet.Cli.Build
Engine = Path.Combine(Path.GetDirectoryName(SdkBundle), ENGINE);
SharedHostMsi = Path.ChangeExtension(c.BuildContext.Get<string>("SharedHostInstallerFile"), "msi");
SharedFrameworkMsi = Path.ChangeExtension(c.BuildContext.Get<string>("SharedFrameworkInstallerFile"), "msi");
var buildVersion = c.BuildContext.Get<BuildVersion>("BuildVersion");
MsiVersion = buildVersion.GenerateMsiVersion();
@ -79,7 +82,7 @@ namespace Microsoft.DotNet.Cli.Build
[Target(nameof(MsiTargets.InitMsi),
nameof(GenerateDotnetSharedHostMsi),
nameof(GenerateDotnetSharedFxMsi),
nameof(GenerateDotnetSharedFrameworkMsi),
nameof(GenerateCliSdkMsi))]
[BuildPlatforms(BuildPlatform.Windows)]
public static BuildTargetResult GenerateMsis(BuildTargetContext c)
@ -121,10 +124,28 @@ namespace Microsoft.DotNet.Cli.Build
return c.Success();
}
[Target]
[Target(nameof(SharedFrameworkTargets.PublishSharedFramework))]
[BuildPlatforms(BuildPlatform.Windows)]
public static BuildTargetResult GenerateDotnetSharedFxMsi(BuildTargetContext c)
public static BuildTargetResult GenerateDotnetSharedFrameworkMsi(BuildTargetContext c)
{
var inputDir = c.BuildContext.Get<string>("SharedFrameworkPublishRoot");
var sharedFrameworkNuGetName = SharedFrameworkTargets.SharedFrameworkName;
var sharedFrameworkNuGetVersion = c.BuildContext.Get<string>("SharedFrameworkNugetVersion");
var upgradeCode = Utils.GenerateGuidFromName($"{sharedFrameworkNuGetName}-{sharedFrameworkNuGetVersion}-{Arch}").ToString().ToUpper();
var wixObjRoot = Path.Combine(Dirs.Output, "obj", "wix", "sharedframework");
if (Directory.Exists(wixObjRoot))
{
Directory.Delete(wixObjRoot, true);
}
Directory.CreateDirectory(wixObjRoot);
Cmd("powershell", "-NoProfile", "-NoLogo",
Path.Combine(Dirs.RepoRoot, "packaging", "sharedframework", "windows", "generatemsi.ps1"),
inputDir, SharedFrameworkMsi, WixRoot, MsiVersion, sharedFrameworkNuGetName, sharedFrameworkNuGetVersion, upgradeCode, Arch, wixObjRoot)
.Execute()
.EnsureSuccessful();
return c.Success();
}

View file

@ -114,6 +114,7 @@ namespace Microsoft.DotNet.Cli.Build
AddInstallerArtifactToContext(c, "dotnet", "Sdk");
AddInstallerArtifactToContext(c, "dotnet-host", "SharedHost");
AddInstallerArtifactToContext(c, "dotnet-sharedframework", "SharedFramework");
return c.Success();
}

View file

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli.Build.Framework;
using Microsoft.Extensions.PlatformAbstractions;
@ -12,8 +13,47 @@ namespace Microsoft.DotNet.Cli.Build
{
public class SharedFrameworkTargets
{
public const string SharedFrameworkName = "NETStandard.Library";
private const string CoreHostBaseName = "corehost";
[Target]
public static BuildTargetResult PublishSharedFramework(BuildTargetContext c)
{
string SharedFrameworkPublishRoot = Path.Combine(Dirs.Output, "obj", "sharedframework");
string SharedFrameworkSourceRoot = Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework");
string SharedFrameworkNugetVersion = GetVersionFromProjectJson(Path.Combine(Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework"), "project.json"));
if (Directory.Exists(SharedFrameworkPublishRoot))
{
Directory.Delete(SharedFrameworkPublishRoot, true);
}
// We publish to a sub folder of the PublishRoot so tools like heat and zip can generate folder structures easier.
string SharedFrameworkNameAndVersionRoot = Path.Combine(SharedFrameworkPublishRoot, "shared", SharedFrameworkName, SharedFrameworkNugetVersion);
DotNetCli.Stage0.Publish("--output", SharedFrameworkNameAndVersionRoot, SharedFrameworkSourceRoot).Execute().EnsureSuccessful();
c.BuildContext["SharedFrameworkPublishRoot"] = SharedFrameworkPublishRoot;
c.BuildContext["SharedFrameworkNugetVersion"] = SharedFrameworkNugetVersion;
// Clean up artifacts that dotnet-publish generates which we don't need
File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, $"framework{Constants.ExeSuffix}"));
File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.dll"));
File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.pdb"));
// Rename the .deps file
File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps"), Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps"));
// corehost will be renamed to dotnet at some point and then this can be removed.
File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, $"{CoreHostBaseName}{Constants.ExeSuffix}"), Path.Combine(SharedFrameworkNameAndVersionRoot, $"dotnet{Constants.ExeSuffix}"));
// hostpolicy will be renamed to dotnet at some point and then this can be removed.
File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), Path.Combine(SharedFrameworkNameAndVersionRoot, $"{Constants.DynamicLibPrefix}dotnethostimpl{Constants.DynamicLibSuffix}"));
return c.Success();
}
[Target]
public static BuildTargetResult PublishSharedHost(BuildTargetContext c)
{
@ -42,5 +82,22 @@ namespace Microsoft.DotNet.Cli.Build
return c.Success();
}
private static string GetVersionFromProjectJson(string pathToProjectJson)
{
Regex r = new Regex($"\"{Regex.Escape(SharedFrameworkName)}\"\\s*:\\s*\"(?'version'[^\"]*)\"");
foreach(var line in File.ReadAllLines(pathToProjectJson))
{
var m = r.Match(line);
if (m.Success)
{
return m.Groups["version"].Value;
}
}
return null;
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
namespace Microsoft.DotNet.Cli.Build
{
@ -34,5 +35,55 @@ namespace Microsoft.DotNet.Cli.Build
throw new PlatformNotSupportedException();
}
}
// Generate a Version 5 (SHA1 Name Based) Guid from a name.
public static Guid GenerateGuidFromName(string name)
{
// Any fixed GUID will do for a namespace.
Guid namespaceId = new Guid("28F1468D-672B-489A-8E0C-7C5B3030630C");
using (SHA1 hasher = SHA1.Create())
{
var nameBytes = System.Text.Encoding.UTF8.GetBytes(name ?? string.Empty);
var namespaceBytes = namespaceId.ToByteArray();
SwapGuidByteOrder(namespaceBytes);
var streamToHash = new byte[namespaceBytes.Length + nameBytes.Length];
Array.Copy(namespaceBytes, streamToHash, namespaceBytes.Length);
Array.Copy(nameBytes, 0, streamToHash, namespaceBytes.Length, nameBytes.Length);
var hashResult = hasher.ComputeHash(streamToHash);
var res = new byte[16];
Array.Copy(hashResult, res, res.Length);
unchecked { res[6] = (byte)(0x50 | (res[6] & 0x0F)); }
unchecked { res[8] = (byte)(0x40 | (res[8] & 0x3F)); }
SwapGuidByteOrder(res);
return new Guid(res);
}
}
// Do a byte order swap, .NET GUIDs store multi byte components in little
// endian.
private static void SwapGuidByteOrder(byte[] b)
{
Swap(b, 0, 3);
Swap(b, 1, 2);
Swap(b, 5, 6);
Swap(b, 7, 8);
}
private static void Swap(byte[] b, int x, int y)
{
byte t = b[x];
b[x] = b[y];
b[y] = t;
}
}
}

View file

@ -8,6 +8,7 @@
"dependencies": {
"NETStandard.Library": "1.0.0-rc2-23901",
"System.IO.Compression.ZipFile": "4.0.1-rc2-23901",
"System.Security.Cryptography.Algorithms": "4.0.0-rc2-23901",
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537",
"Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*",
"WindowsAzure.Storage" : "6.2.2-preview"