2016-03-08 23:22:33 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.IO.Compression;
|
2016-03-09 03:32:31 +00:00
|
|
|
using System.Text.RegularExpressions;
|
2016-03-10 11:19:00 +00:00
|
|
|
using System.Reflection.PortableExecutable;
|
2016-03-08 23:22:33 +00:00
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using Microsoft.DotNet.Cli.Build.Framework;
|
|
|
|
using Microsoft.Extensions.PlatformAbstractions;
|
|
|
|
|
|
|
|
using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers;
|
|
|
|
|
|
|
|
namespace Microsoft.DotNet.Cli.Build
|
|
|
|
{
|
|
|
|
public class SharedFrameworkTargets
|
|
|
|
{
|
2016-03-14 19:17:15 +00:00
|
|
|
public const string SharedFrameworkName = "Microsoft.NETCore.App";
|
2016-03-09 03:32:31 +00:00
|
|
|
|
2016-03-08 23:22:33 +00:00
|
|
|
private const string CoreHostBaseName = "corehost";
|
|
|
|
|
2016-03-14 19:17:15 +00:00
|
|
|
[Target(nameof(PackageSharedFramework), nameof(CrossGenAllManagedAssemblies))]
|
2016-03-09 03:32:31 +00:00
|
|
|
public static BuildTargetResult PublishSharedFramework(BuildTargetContext c)
|
2016-03-14 19:17:15 +00:00
|
|
|
{
|
|
|
|
return c.Success();
|
|
|
|
}
|
|
|
|
|
|
|
|
[Target]
|
|
|
|
public static BuildTargetResult PackageSharedFramework(BuildTargetContext c)
|
2016-03-09 03:32:31 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2016-03-14 19:17:15 +00:00
|
|
|
string publishFramework = "dnxcore50"; // Temporary, use "netcoreapp" when we update nuget.
|
|
|
|
string publishRuntime;
|
|
|
|
if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows)
|
|
|
|
{
|
|
|
|
publishRuntime = $"win7-{PlatformServices.Default.Runtime.RuntimeArchitecture}";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
publishRuntime = PlatformServices.Default.Runtime.GetRuntimeIdentifier();
|
|
|
|
}
|
|
|
|
|
|
|
|
DotNetCli.Stage2.Publish(
|
|
|
|
"--output", SharedFrameworkNameAndVersionRoot,
|
|
|
|
"-r", publishRuntime,
|
|
|
|
"-f", publishFramework,
|
|
|
|
SharedFrameworkSourceRoot).Execute().EnsureSuccessful();
|
2016-03-09 03:32:31 +00:00
|
|
|
|
|
|
|
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"));
|
2016-03-14 19:17:15 +00:00
|
|
|
File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps.json"), Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps.json"));
|
2016-03-09 03:32:31 +00:00
|
|
|
|
|
|
|
// 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}"));
|
|
|
|
|
2016-03-10 11:19:00 +00:00
|
|
|
if (File.Exists(Path.Combine(SharedFrameworkNameAndVersionRoot, "mscorlib.ni.dll")))
|
|
|
|
{
|
|
|
|
// Publish already places the crossgen'd version of mscorlib into the output, so we can
|
|
|
|
// remove the IL version
|
|
|
|
File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "mscorlib.dll"));
|
2016-03-14 19:17:15 +00:00
|
|
|
c.BuildContext["SharedFrameworkNameAndVersionRoot"] = SharedFrameworkNameAndVersionRoot;
|
2016-03-10 11:19:00 +00:00
|
|
|
}
|
2016-03-10 23:20:29 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
c.Warn("Shared framework will not be crossgen'd because mscorlib.ni.dll does not exist.");
|
|
|
|
}
|
2016-03-10 11:19:00 +00:00
|
|
|
|
2016-03-09 03:32:31 +00:00
|
|
|
return c.Success();
|
|
|
|
}
|
|
|
|
|
2016-03-08 23:22:33 +00:00
|
|
|
[Target]
|
|
|
|
public static BuildTargetResult PublishSharedHost(BuildTargetContext c)
|
|
|
|
{
|
|
|
|
string SharedHostPublishRoot = Path.Combine(Dirs.Output, "obj", "sharedhost");
|
2016-03-14 19:17:15 +00:00
|
|
|
Directory.CreateDirectory(SharedHostPublishRoot);
|
2016-03-08 23:22:33 +00:00
|
|
|
// corehost will be renamed to dotnet at some point and then this can be removed.
|
2016-03-14 19:17:15 +00:00
|
|
|
File.Copy(Path.Combine(Dirs.Corehost, $"{CoreHostBaseName}{Constants.ExeSuffix}"), Path.Combine(SharedHostPublishRoot, $"dotnet{Constants.ExeSuffix}"));
|
2016-03-08 23:22:33 +00:00
|
|
|
|
|
|
|
c.BuildContext["SharedHostPublishRoot"] = SharedHostPublishRoot;
|
|
|
|
|
|
|
|
return c.Success();
|
|
|
|
}
|
2016-03-09 03:32:31 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-14 19:17:15 +00:00
|
|
|
throw new InvalidOperationException("Unable to match the version name from " + pathToProjectJson);
|
2016-03-09 03:32:31 +00:00
|
|
|
}
|
2016-03-10 11:19:00 +00:00
|
|
|
|
2016-03-14 19:17:15 +00:00
|
|
|
[Target]
|
|
|
|
[Environment("CROSSGEN_SHAREDFRAMEWORK", "1", "true")]
|
|
|
|
public static BuildTargetResult CrossGenAllManagedAssemblies(BuildTargetContext c)
|
2016-03-10 11:19:00 +00:00
|
|
|
{
|
2016-03-14 19:17:15 +00:00
|
|
|
string pathToAssemblies = c.BuildContext.Get<string>("SharedFrameworkNameAndVersionRoot");
|
|
|
|
|
2016-03-10 11:19:00 +00:00
|
|
|
foreach (var file in Directory.GetFiles(pathToAssemblies))
|
|
|
|
{
|
|
|
|
string fileName = Path.GetFileName(file);
|
|
|
|
|
|
|
|
if (fileName == "mscorlib.dll" || fileName == "mscorlib.ni.dll" || !HasMetadata(file))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
string tempPathName = Path.ChangeExtension(file, "readytorun");
|
|
|
|
|
|
|
|
// This is not always correct. The version of crossgen we need to pick up is whatever one was restored as part
|
|
|
|
// of the Microsoft.NETCore.Runtime.CoreCLR package that is part of the shared library. For now, the version hardcoded
|
|
|
|
// in CompileTargets and the one in the shared library project.json match and are updated in lock step, but long term
|
|
|
|
// we need to be able to look at the project.lock.json file and figure out what version of Microsoft.NETCore.Runtime.CoreCLR
|
|
|
|
// was used, and then select that version.
|
|
|
|
ExecSilent(Crossgen.GetCrossgenPathForVersion(CompileTargets.CoreCLRVersion),
|
|
|
|
"-readytorun", "-in", file, "-out", tempPathName, "-platform_assemblies_paths", pathToAssemblies);
|
|
|
|
|
|
|
|
File.Delete(file);
|
|
|
|
File.Move(tempPathName, file);
|
|
|
|
}
|
2016-03-14 19:17:15 +00:00
|
|
|
|
|
|
|
return c.Success();
|
2016-03-10 11:19:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static bool HasMetadata(string pathToFile)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
using (var inStream = File.OpenRead(pathToFile))
|
|
|
|
{
|
|
|
|
using (var peReader = new PEReader(inStream))
|
|
|
|
{
|
|
|
|
return peReader.HasMetadata;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (BadImageFormatException) { }
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-08 23:22:33 +00:00
|
|
|
}
|
2016-03-10 11:19:00 +00:00
|
|
|
}
|