dotnet-installer/scripts/dotnet-cli-build/SharedFrameworkTargets.cs

219 lines
10 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
2016-03-08 19:32:31 -08:00
using System.Text.RegularExpressions;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli.Build.Framework;
using Microsoft.Extensions.PlatformAbstractions;
using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
namespace Microsoft.DotNet.Cli.Build
{
public class SharedFrameworkTargets
{
public const string SharedFrameworkName = "Microsoft.NETCore.App";
2016-03-08 19:32:31 -08:00
private const string CoreHostBaseName = "corehost";
private const string DotnetHostFxrBaseName = "hostfxr";
private const string HostPolicyBaseName = "hostpolicy";
[Target(nameof(PackageSharedFramework), nameof(CrossGenAllManagedAssemblies))]
2016-03-08 19:32:31 -08:00
public static BuildTargetResult PublishSharedFramework(BuildTargetContext c)
{
return c.Success();
}
[Target]
public static BuildTargetResult PackageSharedFramework(BuildTargetContext c)
2016-03-08 19:32:31 -08: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))
{
Utils.DeleteDirectory(SharedFrameworkPublishRoot);
2016-03-08 19:32:31 -08:00
}
// 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);
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-08 19:32:31 -08: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"));
File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.runtimeconfig.json"));
2016-03-08 19:32:31 -08:00
// Rename the .deps file
var destinationDeps = Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps.json");
2016-03-08 19:32:31 -08:00
File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps"), Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps"));
File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps.json"), destinationDeps);
// Generate RID fallback graph
string runtimeGraphGeneratorRuntime = null;
switch (PlatformServices.Default.Runtime.OperatingSystemPlatform)
{
case Platform.Windows:
runtimeGraphGeneratorRuntime = "win";
break;
case Platform.Linux:
runtimeGraphGeneratorRuntime = "linux";
break;
case Platform.Darwin:
runtimeGraphGeneratorRuntime = "osx";
break;
}
if (!string.IsNullOrEmpty(runtimeGraphGeneratorRuntime))
{
var runtimeGraphGeneratorName = "RuntimeGraphGenerator";
var runtimeGraphGeneratorProject = Path.Combine(c.BuildContext.BuildDirectory, "tools", runtimeGraphGeneratorName);
var runtimeGraphGeneratorOutput = Path.Combine(Dirs.Output, "tools", runtimeGraphGeneratorName);
DotNetCli.Stage2.Publish(
"--output", runtimeGraphGeneratorOutput,
runtimeGraphGeneratorProject).Execute().EnsureSuccessful();
var runtimeGraphGeneratorExe = Path.Combine(runtimeGraphGeneratorOutput, $"{runtimeGraphGeneratorName}{Constants.ExeSuffix}");
Cmd(runtimeGraphGeneratorExe, "--project", SharedFrameworkSourceRoot, "--deps", destinationDeps, runtimeGraphGeneratorRuntime)
.Execute();
}
else
{
c.Error($"Could not determine rid graph generation runtime for platform {PlatformServices.Default.Runtime.OperatingSystemPlatform}");
}
2016-03-08 19:32:31 -08:00
// corehost will be renamed to dotnet at some point and then we will not need to rename it here.
File.Copy(
Path.Combine(Dirs.Corehost, $"{CoreHostBaseName}{Constants.ExeSuffix}"),
Path.Combine(SharedFrameworkNameAndVersionRoot, $"dotnet{Constants.ExeSuffix}"));
File.Copy(
Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}{HostPolicyBaseName}{Constants.DynamicLibSuffix}"),
Path.Combine(SharedFrameworkNameAndVersionRoot, $"{Constants.DynamicLibPrefix}{HostPolicyBaseName}{Constants.DynamicLibSuffix}"), true);
2016-03-08 19:32:31 -08: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"));
c.BuildContext["SharedFrameworkNameAndVersionRoot"] = SharedFrameworkNameAndVersionRoot;
}
2016-03-08 19:32:31 -08:00
return c.Success();
}
[Target]
public static BuildTargetResult PublishSharedHost(BuildTargetContext c)
{
string SharedHostPublishRoot = Path.Combine(Dirs.Output, "obj", "sharedhost");
if (Directory.Exists(SharedHostPublishRoot))
{
Utils.DeleteDirectory(SharedHostPublishRoot);
}
Directory.CreateDirectory(SharedHostPublishRoot);
// corehost will be renamed to dotnet at some point and then this can be removed.
File.Copy(
Path.Combine(Dirs.Corehost, $"{CoreHostBaseName}{Constants.ExeSuffix}"),
Path.Combine(SharedHostPublishRoot, $"dotnet{Constants.ExeSuffix}"));
File.Copy(
Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}{DotnetHostFxrBaseName}{Constants.DynamicLibSuffix}"),
Path.Combine(SharedHostPublishRoot, $"{Constants.DynamicLibPrefix}{DotnetHostFxrBaseName}{Constants.DynamicLibSuffix}"));
c.BuildContext["SharedHostPublishRoot"] = SharedHostPublishRoot;
return c.Success();
}
2016-03-08 19:32:31 -08: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;
}
}
throw new InvalidOperationException("Unable to match the version name from " + pathToProjectJson);
2016-03-08 19:32:31 -08:00
}
[Target]
[Environment("CROSSGEN_SHAREDFRAMEWORK", "1", "true")]
public static BuildTargetResult CrossGenAllManagedAssemblies(BuildTargetContext c)
{
string pathToAssemblies = c.BuildContext.Get<string>("SharedFrameworkNameAndVersionRoot");
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);
}
return c.Success();
}
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;
}
}
}