You've already forked linux-packaging-mono
Imported Upstream version 5.4.0.167
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
parent
e49d6f06c0
commit
536cd135cc
110
external/linker/corebuild/integration/ILLink.Tasks/CompareSizes.cs
vendored
Normal file
110
external/linker/corebuild/integration/ILLink.Tasks/CompareSizes.cs
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Microsoft.Build.Framework;
|
||||
|
||||
namespace ILLink.Tasks
|
||||
{
|
||||
struct AssemblySizes
|
||||
{
|
||||
public long unlinkedSize;
|
||||
public long linkedSize;
|
||||
}
|
||||
public class CompareAssemblySizes : Task
|
||||
{
|
||||
/// <summary>
|
||||
/// Paths to managed assemblies before linking.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] UnlinkedAssemblies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Paths to managed assemblies after linking. These
|
||||
/// assembly names should be a subset of the
|
||||
/// assembly names in UnlinkedAssemblies.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] LinkedAssemblies { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
string[] unlinkedFiles = UnlinkedAssemblies.Select (i => i.ItemSpec).ToArray();
|
||||
string[] linkedFiles = LinkedAssemblies.Select (i => i.ItemSpec).ToArray();
|
||||
|
||||
Dictionary<string, AssemblySizes> sizes = new Dictionary<string, AssemblySizes> ();
|
||||
|
||||
long totalUnlinked = 0;
|
||||
foreach (string unlinkedFile in unlinkedFiles) {
|
||||
try {
|
||||
AssemblyName.GetAssemblyName (unlinkedFile);
|
||||
}
|
||||
catch (BadImageFormatException) {
|
||||
continue;
|
||||
}
|
||||
string fileName = Path.GetFileName (unlinkedFile);
|
||||
AssemblySizes assemblySizes = new AssemblySizes ();
|
||||
assemblySizes.unlinkedSize = new System.IO.FileInfo (unlinkedFile).Length;
|
||||
totalUnlinked += assemblySizes.unlinkedSize;
|
||||
sizes[fileName] = assemblySizes;
|
||||
}
|
||||
|
||||
long totalLinked = 0;
|
||||
foreach (string linkedFile in linkedFiles) {
|
||||
try {
|
||||
AssemblyName.GetAssemblyName (linkedFile);
|
||||
}
|
||||
catch (BadImageFormatException) {
|
||||
continue;
|
||||
}
|
||||
string fileName = Path.GetFileName (linkedFile);
|
||||
if (!sizes.ContainsKey(fileName)) {
|
||||
Console.WriteLine ($"{linkedFile} was specified as an assembly kept by the linker, but {fileName} was not specified as a managed publish assembly.");
|
||||
continue;
|
||||
}
|
||||
AssemblySizes assemblySizes = sizes[fileName];
|
||||
assemblySizes.linkedSize = new System.IO.FileInfo (linkedFile).Length;
|
||||
totalLinked += assemblySizes.linkedSize;
|
||||
sizes[fileName] = assemblySizes;
|
||||
}
|
||||
|
||||
Console.WriteLine ("{0, -60} {1,-20:N0} {2, -20:N0} {3, -10:P}",
|
||||
"Total size of assemblies",
|
||||
totalUnlinked,
|
||||
totalLinked,
|
||||
((double)totalUnlinked - (double)totalLinked) / (double)totalUnlinked);
|
||||
|
||||
Console.WriteLine ("-----------");
|
||||
Console.WriteLine ("Details");
|
||||
Console.WriteLine ("-----------");
|
||||
|
||||
foreach (string assembly in sizes.Keys) {
|
||||
Console.WriteLine ("{0, -60} {1,-20:N0} {2, -20:N0} {3, -10:P}",
|
||||
assembly,
|
||||
sizes[assembly].unlinkedSize,
|
||||
sizes[assembly].linkedSize,
|
||||
(double)(sizes[assembly].unlinkedSize - sizes[assembly].linkedSize)/(double)sizes[assembly].unlinkedSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static long DirSize(DirectoryInfo d)
|
||||
{
|
||||
long size = 0;
|
||||
// Add file sizes.
|
||||
FileInfo[] fis = d.GetFiles ();
|
||||
foreach (FileInfo fi in fis) {
|
||||
size += fi.Length;
|
||||
}
|
||||
// Add subdirectory sizes.
|
||||
DirectoryInfo[] dis = d.GetDirectories ();
|
||||
foreach (DirectoryInfo di in dis) {
|
||||
size += DirSize (di);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
external/linker/corebuild/integration/ILLink.Tasks/ComputeManagedAssemblies.cs
vendored
Normal file
47
external/linker/corebuild/integration/ILLink.Tasks/ComputeManagedAssemblies.cs
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Build.Utilities; // Task
|
||||
using Microsoft.Build.Framework; // MessageImportance
|
||||
using Microsoft.NET.Build.Tasks; // LockFileCache
|
||||
using NuGet.ProjectModel; // LockFileTargetLibrary
|
||||
using NuGet.Frameworks; // NuGetFramework.Parse(targetframework)
|
||||
|
||||
namespace ILLink.Tasks
|
||||
{
|
||||
public class ComputeManagedAssemblies : Task
|
||||
{
|
||||
/// <summary>
|
||||
/// Paths to assemblies.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] Assemblies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This will contain the output list of managed
|
||||
/// assemblies. Metadata from the input parameter
|
||||
/// Assemblies is preserved.
|
||||
/// </summary>
|
||||
[Output]
|
||||
public ITaskItem[] ManagedAssemblies { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
var managedAssemblies = new List<ITaskItem>();
|
||||
foreach (var f in Assemblies) {
|
||||
try {
|
||||
AssemblyName.GetAssemblyName(f.ItemSpec);
|
||||
managedAssemblies.Add(f);
|
||||
} catch (BadImageFormatException) {
|
||||
}
|
||||
}
|
||||
ManagedAssemblies = managedAssemblies.ToArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
external/linker/corebuild/integration/ILLink.Tasks/CreateRootDescriptorFile.cs
vendored
Normal file
56
external/linker/corebuild/integration/ILLink.Tasks/CreateRootDescriptorFile.cs
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Build.Utilities; // Task
|
||||
using Microsoft.Build.Framework; // MessageImportance
|
||||
using Microsoft.NET.Build.Tasks; // LockFileCache
|
||||
using NuGet.ProjectModel; // LockFileTargetLibrary
|
||||
using NuGet.Frameworks; // NuGetFramework.Parse(targetframework)
|
||||
|
||||
namespace ILLink.Tasks
|
||||
{
|
||||
public class CreateRootDescriptorFile : Task
|
||||
{
|
||||
/// <summary>
|
||||
/// Assembly names (without path or extension) to
|
||||
/// include in the generated root file.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] AssemblyNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path to the file to generate.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem RootDescriptorFilePath { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
var roots = new XElement("linker");
|
||||
foreach (var assemblyItem in AssemblyNames) {
|
||||
var assemblyName = assemblyItem.ItemSpec;
|
||||
roots.Add(new XElement("assembly",
|
||||
new XAttribute("fullname", assemblyName),
|
||||
new XElement("type",
|
||||
new XAttribute("fullname", "*"),
|
||||
new XAttribute("required", "true"))));
|
||||
}
|
||||
|
||||
var xdoc = new XDocument(roots);
|
||||
|
||||
XmlWriterSettings xws = new XmlWriterSettings();
|
||||
xws.Indent = true;
|
||||
xws.OmitXmlDeclaration = true;
|
||||
|
||||
using (XmlWriter xw = XmlWriter.Create(RootDescriptorFilePath.ItemSpec, xws)) {
|
||||
xdoc.Save(xw);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
115
external/linker/corebuild/integration/ILLink.Tasks/DepsJsonLinker.cs
vendored
Normal file
115
external/linker/corebuild/integration/ILLink.Tasks/DepsJsonLinker.cs
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.IO;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Microsoft.Build.Framework;
|
||||
|
||||
namespace ILLink.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// This class exists as a workaround. It strips the publish
|
||||
/// dependency file of assemblies excluded from the publish
|
||||
/// output by the linker. Ideally we would pass appropriate
|
||||
/// parameters to the task that generates the deps file in
|
||||
/// the first place, instead of rewriting it. We may be
|
||||
/// ablee to do this once
|
||||
/// https://github.com/dotnet/sdk/pull/1052 is merged.
|
||||
/// </summary>
|
||||
public class DepsJsonLinker : Task
|
||||
{
|
||||
[Required]
|
||||
public ITaskItem InputDepsFilePath { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem OutputDepsFilePath { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] ManagedPublishAssemblies { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] KeptAssemblies { get; set; }
|
||||
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
string inputFile = InputDepsFilePath.ItemSpec;
|
||||
string outputFile = OutputDepsFilePath.ItemSpec;
|
||||
|
||||
string[] keptAssemblies = KeptAssemblies.Select(a => a.ItemSpec).ToArray();
|
||||
string[] allAssemblies = ManagedPublishAssemblies.Select(a => a.ItemSpec).ToArray();
|
||||
string[] removedAssemblies = allAssemblies.Except(keptAssemblies).ToArray();
|
||||
|
||||
var removedAssembliesSet = new HashSet<string> (removedAssemblies, StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
JObject o = JObject.Parse (File.ReadAllText (inputFile));
|
||||
|
||||
JObject targets = (JObject)o["targets"];
|
||||
|
||||
// Remove targets
|
||||
foreach (JProperty target in targets.Children()) {
|
||||
JEnumerable<JToken> children = target.Value.Children ();
|
||||
for (int i = 0; i < children.Count(); ++i) {
|
||||
//foreach (JProperty subtarget in target.Value.Children()) {
|
||||
var subtarget = (JProperty) children.ElementAt (i);
|
||||
string name = subtarget.Name.Substring (0, subtarget.Name.IndexOf ('/'));
|
||||
if (removedAssembliesSet.Contains (name + ".dll")) {
|
||||
subtarget.Remove ();
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove dependencies
|
||||
var dependencies = subtarget.Value["dependencies"];
|
||||
if (dependencies != null) {
|
||||
for (int j = 0; j < dependencies.Count (); ++j) {
|
||||
var dependency = ((JProperty)dependencies.ElementAt (j));
|
||||
|
||||
if (removedAssembliesSet.Contains (dependency.Name + ".dll")) {
|
||||
|
||||
dependency.Remove ();
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove runtimes
|
||||
var runtimes = subtarget.Value["runtime"];
|
||||
if (runtimes != null) {
|
||||
for (int j = 0; j < runtimes.Count (); ++j) {
|
||||
var runtime = ((JProperty)runtimes.ElementAt (j));
|
||||
string runtimeFileName = runtime.Name.Substring (runtime.Name.LastIndexOf ('/') + 1);
|
||||
|
||||
if (removedAssembliesSet.Contains (runtimeFileName)) {
|
||||
runtime.Remove ();
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove libraries
|
||||
JObject libraries = (JObject)o["libraries"];
|
||||
|
||||
JEnumerable<JToken> libraryChildren = libraries.Children ();
|
||||
for (int i = 0; i < libraryChildren.Count (); ++i) {
|
||||
var library = (JProperty)libraryChildren.ElementAt (i);
|
||||
string name = library.Name.Substring (0, library.Name.IndexOf ('/'));
|
||||
if (removedAssembliesSet.Contains (name + ".dll")) {
|
||||
library.Remove ();
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText (outputFile, o.ToString ());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
175
external/linker/corebuild/integration/ILLink.Tasks/GenerateRoots.cs
vendored
Normal file
175
external/linker/corebuild/integration/ILLink.Tasks/GenerateRoots.cs
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Build.Utilities; // Task
|
||||
using Microsoft.Build.Framework; // MessageImportance
|
||||
using Microsoft.NET.Build.Tasks; // LockFileCache
|
||||
using NuGet.ProjectModel; // LockFileTargetLibrary
|
||||
using NuGet.Frameworks; // NuGetFramework.Parse(targetframework)
|
||||
|
||||
namespace ILLink.Tasks
|
||||
{
|
||||
public class GenerateRoots : Task
|
||||
{
|
||||
|
||||
[Required]
|
||||
public string AssetsFilePath { get; set; }
|
||||
|
||||
[Required]
|
||||
public string TargetFramework { get; set; }
|
||||
|
||||
[Required]
|
||||
public string RuntimeIdentifier { get; set; }
|
||||
|
||||
[Required]
|
||||
public string PublishDir { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem SingleRootXmlFilePath { get; set; }
|
||||
|
||||
[Required]
|
||||
public string MainAssemblyName { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] RootAssemblies { get; private set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] FrameworkAssemblies { get; private set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] PublishAssemblies { get; private set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] UnmanagedFileAssets { get; private set; }
|
||||
|
||||
|
||||
private List<string> publishLibs;
|
||||
private List<string> unmanagedFileAssets;
|
||||
private List<string> rootLibs;
|
||||
private List<string> frameworkLibs;
|
||||
|
||||
private void WriteSingleRootXmlFile()
|
||||
{
|
||||
var xdoc = new XDocument(new XElement("linker",
|
||||
new XElement("assembly",
|
||||
new XAttribute("fullname", MainAssemblyName),
|
||||
new XElement("type",
|
||||
new XAttribute("fullname", "*"),
|
||||
new XAttribute("required", "true")))));
|
||||
|
||||
XmlWriterSettings xws = new XmlWriterSettings();
|
||||
xws.Indent = true;
|
||||
xws.OmitXmlDeclaration = true;
|
||||
|
||||
using (XmlWriter xw = XmlWriter.Create(SingleRootXmlFilePath.ItemSpec, xws))
|
||||
{
|
||||
xdoc.Save(xw);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void GetAssembliesAndFiles()
|
||||
{
|
||||
unmanagedFileAssets = new List<string>();
|
||||
publishLibs = new List<string>();
|
||||
foreach (var f in Directory.GetFiles(PublishDir))
|
||||
{
|
||||
try
|
||||
{
|
||||
AssemblyName.GetAssemblyName(f);
|
||||
publishLibs.Add(f);
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
unmanagedFileAssets.Add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void PopulateOutputItems()
|
||||
{
|
||||
FrameworkAssemblies = frameworkLibs.Select(l => new TaskItem(l)).ToArray();
|
||||
|
||||
RootAssemblies = rootLibs.Select(l => Path.GetFileNameWithoutExtension(l))
|
||||
.Select(l => new TaskItem(l)).ToArray();
|
||||
|
||||
UnmanagedFileAssets = unmanagedFileAssets.Select(f => Path.GetFileName(f))
|
||||
.Select(f => new TaskItem(f)).ToArray();
|
||||
|
||||
PublishAssemblies = publishLibs.Select(l => Path.GetFileName(l))
|
||||
.Select(l => new TaskItem(l)).ToArray();
|
||||
|
||||
}
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
if (!Directory.Exists(PublishDir))
|
||||
{
|
||||
Log.LogMessageFromText($"Publish directory {PublishDir} does not exist. Run dotnet publish before dotnet link.", MessageImportance.High); return false;
|
||||
}
|
||||
|
||||
// TODO: make this a separate msbuild task
|
||||
WriteSingleRootXmlFile();
|
||||
|
||||
// TODO: make this a separate msbuild task
|
||||
GetAssembliesAndFiles();
|
||||
|
||||
// TODO: make this a separate msbuild task
|
||||
GetFrameworkLibraries();
|
||||
|
||||
rootLibs = publishLibs.Select(l => Path.GetFileName(l)).Except(frameworkLibs).ToList();
|
||||
|
||||
PopulateOutputItems();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void GetFrameworkLibraries()
|
||||
{
|
||||
var lockFile = new LockFileCache(BuildEngine4).GetLockFile(AssetsFilePath);
|
||||
var lockFileTarget = lockFile.GetTarget(NuGetFramework.Parse(TargetFramework), RuntimeIdentifier);
|
||||
|
||||
if (lockFileTarget == null)
|
||||
{
|
||||
var targetString = string.IsNullOrEmpty(RuntimeIdentifier) ? TargetFramework : $"{TargetFramework}/{RuntimeIdentifier}";
|
||||
|
||||
throw new Exception($"Missing target section {targetString} from assets file {AssetsFilePath}. Ensure you have restored this project previously.");
|
||||
}
|
||||
|
||||
var netCoreAppPackage = lockFileTarget.Libraries.Single(l => l.Name == "Microsoft.NETCore.App");
|
||||
|
||||
Dictionary<string, LockFileTargetLibrary> packages = new Dictionary<string, LockFileTargetLibrary>(lockFileTarget.Libraries.Count, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var lib in lockFileTarget.Libraries)
|
||||
{
|
||||
packages.Add(lib.Name, lib);
|
||||
}
|
||||
|
||||
var packageQueue = new Queue<LockFileTargetLibrary>();
|
||||
packageQueue.Enqueue(netCoreAppPackage);
|
||||
|
||||
|
||||
var libraries = new List<string>();
|
||||
while (packageQueue.Count > 0)
|
||||
{
|
||||
var package = packageQueue.Dequeue();
|
||||
foreach (var lib in package.RuntimeAssemblies)
|
||||
{
|
||||
libraries.Add(lib.ToString());
|
||||
}
|
||||
|
||||
foreach (var dep in package.Dependencies.Select(d => d.Id))
|
||||
{
|
||||
packageQueue.Enqueue(packages[dep]);
|
||||
}
|
||||
}
|
||||
|
||||
frameworkLibs = libraries.Select(l => Path.GetFileName(l)).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
87
external/linker/corebuild/integration/ILLink.Tasks/GetRuntimeLibraries.cs
vendored
Normal file
87
external/linker/corebuild/integration/ILLink.Tasks/GetRuntimeLibraries.cs
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Build.Utilities; // Task
|
||||
using Microsoft.Build.Framework; // MessageImportance
|
||||
using Microsoft.NET.Build.Tasks; // LockFileCache
|
||||
using NuGet.ProjectModel; // LockFileTargetLibrary
|
||||
using NuGet.Frameworks; // NuGetFramework.Parse(targetframework)
|
||||
|
||||
namespace ILLink.Tasks
|
||||
{
|
||||
public class GetRuntimeLibraries : Task
|
||||
{
|
||||
/// <summary>
|
||||
/// Path to the assets file.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem AssetsFilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Target framework for which to get the platform
|
||||
/// libraries.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string TargetFramework { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Runtime identifier for which to get the platform
|
||||
/// libraries.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string RuntimeIdentifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the library to consider the "platform"
|
||||
/// library.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string[] PackageNames { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] RuntimeLibraries { get; private set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
var lockFile = new LockFileCache(BuildEngine4).GetLockFile(AssetsFilePath.ItemSpec);
|
||||
var lockFileTarget = lockFile.GetTarget(NuGetFramework.Parse(TargetFramework), RuntimeIdentifier);
|
||||
|
||||
if (lockFileTarget == null) {
|
||||
var targetString = string.IsNullOrEmpty(RuntimeIdentifier) ? TargetFramework : $"{TargetFramework}/{RuntimeIdentifier}";
|
||||
|
||||
throw new Exception($"Missing target section {targetString} from assets file {AssetsFilePath}. Ensure you have restored this project previously.");
|
||||
}
|
||||
|
||||
Dictionary<string, LockFileTargetLibrary> packages = new Dictionary<string, LockFileTargetLibrary>(lockFileTarget.Libraries.Count, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var lib in lockFileTarget.Libraries) {
|
||||
packages.Add(lib.Name, lib);
|
||||
}
|
||||
|
||||
HashSet<string> packageNames = new HashSet<string>(PackageNames);
|
||||
var rootPackages = lockFileTarget.Libraries.Where(l => packageNames.Contains(l.Name));
|
||||
|
||||
var packageQueue = new Queue<LockFileTargetLibrary>(rootPackages);
|
||||
|
||||
var libraries = new List<string>();
|
||||
while (packageQueue.Count > 0) {
|
||||
var package = packageQueue.Dequeue();
|
||||
foreach (var lib in package.RuntimeAssemblies) {
|
||||
libraries.Add(lib.ToString());
|
||||
}
|
||||
|
||||
foreach (var dep in package.Dependencies.Select(d => d.Id)) {
|
||||
packageQueue.Enqueue(packages[dep]);
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeLibraries = libraries.Select(l => new TaskItem(l)).ToArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
171
external/linker/corebuild/integration/ILLink.Tasks/ILLink.Tasks.csproj
vendored
Normal file
171
external/linker/corebuild/integration/ILLink.Tasks/ILLink.Tasks.csproj
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.1.4-preview</VersionPrefix>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.0.0-beta-001509-00</RuntimeFrameworkVersion>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
<PackageOutputPath>../nupkgs</PackageOutputPath>
|
||||
|
||||
<!-- IsTool true causes the build output to be placed in the
|
||||
package's tools folder. This allows projects to reference the
|
||||
tasks package without including the tasks dll in their
|
||||
output. -->
|
||||
<!-- TODO: This has no effect currently, because we are using a
|
||||
custom .nuspec with the tools path hardcoded. Uncomment this
|
||||
once we are able to remove the custom .nuspec workaround. -->
|
||||
<!-- <IsTool>true</IsTool> -->
|
||||
|
||||
<!-- We want to package the tasks package together with its
|
||||
package dependencies, the linker, and the linker's
|
||||
dependencies, in order to prevent projects that contsume the
|
||||
tasks package from pulling in the linker. To do this, we need
|
||||
to include project references and package references in the
|
||||
package, and prevent any of these references from being
|
||||
marked as dependencies in the tasks package.
|
||||
|
||||
To include the linker in the package, we want to package the
|
||||
tasks project together with its project references. This is
|
||||
not supported by the pack targets
|
||||
(https://github.com/dotnet/cli/issues/1290,
|
||||
https://github.com/dotnet/cli/issues/3959), so we work around
|
||||
this by explicitly setting the package path to include the
|
||||
build output. Using the publish directory will also cause
|
||||
dependencies from package references to be packaged.
|
||||
|
||||
To prevent the linker from being marked as a package
|
||||
dependency, we can't use PrivateAssets="All", because this
|
||||
removes it from the publish output as well, due to an issue
|
||||
in the SDK (https://github.com/dotnet/sdk/issues/952). To
|
||||
work around this, we use a custom .nuspec that doesn't
|
||||
declare any dependencies. This also prevents package
|
||||
references from being marked as dependencies. -->
|
||||
<!-- TODO: Remove the custom .nuspec once the P2P PrivateAssets
|
||||
issue is fixed. -->
|
||||
<NuspecFile>ILLink.Tasks.nuspec</NuspecFile>
|
||||
<NuspecProperties>id=$(AssemblyName);authors=$(AssemblyName);description=linker tasks;tfm=$(TargetFramework);</NuspecProperties>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- TODO: Remove this workaround once we're able to avoid using a
|
||||
custom .nuspec. We may still need a similar workaround to
|
||||
dynamically include the publish output in the package contents.
|
||||
|
||||
We can't specify the output path to package in the static
|
||||
nuspec properties, because the project's output path gets set
|
||||
at a later point. To work around this, we add the output path
|
||||
to the nuspec properties dynamically as part of the pack
|
||||
target. We use the same workaround to set the version in the
|
||||
.nuspec file.
|
||||
|
||||
We can't insert this into the pack target by modifying
|
||||
PackDependsOn, since GenerateNuspec is always prepended to
|
||||
PackDependsOn, which would cause the nuspec file to be
|
||||
generated before our extra properties are added.
|
||||
|
||||
Instead, we use GenerateNuspecDependsOn. We could probably also
|
||||
use BeforeTargets="GenerateNuspec". -->
|
||||
<PropertyGroup>
|
||||
<GenerateNuspecDependsOn>Publish;SetDynamicNuspecProperties;$(GenerateNuspecDependsOn)</GenerateNuspecDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="SetDynamicNuspecProperties">
|
||||
<PropertyGroup>
|
||||
<NuspecProperties>$(NuspecProperties)output=$(PublishDir);version=$(Version);</NuspecProperties>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="LinkTask.cs" />
|
||||
<Compile Include="DepsJsonLinker.cs" />
|
||||
<Compile Include="CompareSizes.cs" />
|
||||
<Compile Include="ComputeManagedAssemblies.cs" />
|
||||
<Compile Include="GetRuntimeLibraries.cs" />
|
||||
<Compile Include="CreateRootDescriptorFile.cs" />
|
||||
<Compile Include="Microsoft.NET.Build.Tasks/LockFileCache.cs" />
|
||||
<Compile Include="Microsoft.NET.Build.Tasks/BuildErrorException.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- TODO: Uncomment this once we can avoid hard-coding this in a
|
||||
custom .nuspec. -->
|
||||
<!-- Targets under the build directory of the package automatically
|
||||
get included in the consumer's build.
|
||||
-->
|
||||
<!--
|
||||
<ItemGroup>
|
||||
<Content Include="ILLink.Tasks.targets">
|
||||
<PackagePath>build</PackagePath>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
-->
|
||||
|
||||
<!-- TODO: Use this to set the package contents once we can avoid
|
||||
using a custom .nuspec. -->
|
||||
<!-- We can't glob everything in the output path for two reasons:
|
||||
|
||||
1. Content gets expanded before "Build" is called during
|
||||
"Pack". We could work around this by creating our own target to
|
||||
call build and then pack, but it would be nice to avoid
|
||||
changing the build/package pipeline.
|
||||
|
||||
2. We'll try to include the tasks dll twice. This only causes a
|
||||
warning during pack, but should be avoided.
|
||||
|
||||
<Content Include="$(OutputPath)*.dll;$(OutputPath)*.json">
|
||||
<PackagePath>tools</PackagePath>
|
||||
</Content>
|
||||
|
||||
There may also be a better ItemGroup to use than
|
||||
Content. Content semantics mean to output with the build, which
|
||||
isn't our goal. Instead, we want to include these dependencies
|
||||
in the package without necessarily including them in the build.
|
||||
-->
|
||||
<!--
|
||||
<ItemGroup>
|
||||
<Content Include="$(OutputPath)illink.dll;$(OutputPath)Mono.Cecil.dll">
|
||||
<PackagePath>tools</PackagePath>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
-->
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<!-- TODO: Once https://github.com/dotnet/sdk/issues/952 is fixed,
|
||||
use PrivateAssets="All" to prevent this project reference
|
||||
from being marked as a dependency of the tasks package (while
|
||||
still including it in the publish output). -->
|
||||
<ProjectReference Include="../../../linker/Mono.Linker.csproj" />
|
||||
<!-- SetConfiguration isn't required when the configuration is
|
||||
already set in the solution. However, it should be possible
|
||||
to set it here to allow packing the tasks csproj on its
|
||||
own. This would let us avoid some of the strange behavior
|
||||
that shows up when trying to build from a .sln file.
|
||||
|
||||
There is a nuget bug that prevents this from working
|
||||
properly during restore
|
||||
(https://github.com/NuGet/Home/issues/4873). For the
|
||||
moment, the linker has a workaround for this issue.
|
||||
|
||||
However, this still won't work properly because the build
|
||||
target doesn't propagate this information properly either -
|
||||
this is probably another bug. Building from the .csproj
|
||||
would cause cecil to be built twice, once through the
|
||||
linker with the netstandard configuration and once directly
|
||||
from the tasks project in the default configuration info
|
||||
(because some target gets its reference information from
|
||||
the lock file, which doesn't have configuration info).
|
||||
-->
|
||||
<!--
|
||||
<SetConfiguration>Configuration=netcore_$(Configuration)</SetConfiguration>
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<!-- TODO: Once we can avoid using a custom .nuspec, we should be
|
||||
able to set PrivateAssets="All" on these packages to prevent
|
||||
them from becoming package dependencies, and use an msbuild
|
||||
itemgroup to include their assets in the package instead of
|
||||
passing the publish path to the .nuspec. -->
|
||||
<PackageReference Include="Microsoft.Build.Framework" Version="0.1.0-preview-00028-160627" />
|
||||
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="0.1.0-preview-00028-160627" />
|
||||
<PackageReference Include="NuGet.ProjectModel" Version="4.3.0-preview1-2500" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
13
external/linker/corebuild/integration/ILLink.Tasks/ILLink.Tasks.nuspec
vendored
Normal file
13
external/linker/corebuild/integration/ILLink.Tasks/ILLink.Tasks.nuspec
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>$id$</id>
|
||||
<version>$version$</version>
|
||||
<authors>$authors$</authors>
|
||||
<description>$description$</description>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="ILLink.Tasks.targets" target="build" />
|
||||
<file src="$output$*.dll" target="tools/$tfm$" />
|
||||
</files>
|
||||
</package>
|
||||
294
external/linker/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets
vendored
Normal file
294
external/linker/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<PropertyGroup>
|
||||
<LinkTaskDllPath Condition=" '$(LinkTaskDllPath)' == '' ">$(MSBuildThisFileDirectory)../tools/$(TargetFramework)/ILLink.Tasks.dll</LinkTaskDllPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- LinkDuringPublish allows the linker to be disabled by passing
|
||||
a property on the command-line. (/p:LinkDuringPublish=false)
|
||||
-->
|
||||
<LinkDuringPublish Condition=" '$(LinkDuringPublish)' == '' ">true</LinkDuringPublish>
|
||||
<LinkDuringPublish Condition=" '$(LinkDuringPublish)' != 'true' ">false</LinkDuringPublish>
|
||||
<ShowLinkerSizeComparison Condition=" '$(ShowLinkerSizeComparison)' == '' ">false</ShowLinkerSizeComparison>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- LinkerRootDescriptors (the ItemGroup) is set to contain
|
||||
LinkerRootDescriptors (the Property), which allows adding
|
||||
linker roots on the command-line
|
||||
(/p:LinkerRootDescriptors=path/to/a.xml;path/to/b.xml;). These
|
||||
are relative paths from the project to the xml file.
|
||||
LinkerRootDescriptors (the ItemGroup) can also be set in the
|
||||
project file, and these will be included in addition to those
|
||||
specified on the command-line. -->
|
||||
<LinkerRootDescriptors Include="$(LinkerRootDescriptors)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- By default, the linker will generate roots for the intermediate
|
||||
assembly that root everything in the assembly. -->
|
||||
<PropertyGroup>
|
||||
<_IntermediateRootDescriptorName Condition=" '$(_IntermediateRootDescriptorName)' == '' ">IntermediateAssemblyRoots.xml</_IntermediateRootDescriptorName>
|
||||
<_IntermediateRootDescriptorPath Condition=" '$(_IntermediateRootDescriptorPath)' == '' ">$(IntermediateOutputPath)$(_IntermediateRootDescriptorName)</_IntermediateRootDescriptorPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- The linker will place linked assemblies into an intermediate
|
||||
directory, and hook into the rest of the publish pipeline to
|
||||
publish the linked assemblies instead of those given as input
|
||||
to the linker. -->
|
||||
<PropertyGroup>
|
||||
<IntermediateLinkDirName Condition=" '$(IntermediateLinkDirName)' == '' ">linked</IntermediateLinkDirName>
|
||||
<IntermediateLinkDir Condition=" '$(IntermediateLinkDir)' == '' ">$(IntermediateOutputPath)$(IntermediateLinkDirName)</IntermediateLinkDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Used to enable incremental build for the link target. -->
|
||||
<PropertyGroup>
|
||||
<_LinkSemaphore>$(IntermediateOutputPath)Link.semaphore</_LinkSemaphore>
|
||||
<_LinkDepsSemaphore>$(IntermediateOutputPath)LinkDeps.semaphore</_LinkDepsSemaphore>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<!--
|
||||
This target runs the linker during the publish pipeline. The
|
||||
publish pipeline has a target called ComputeFilesToPublish,
|
||||
which computes the ItemGroup ResolvedFileToPublish. To extend
|
||||
this target, we insert a target before
|
||||
ComputeFilesToPublish. Our target rewrites the relevant inputs
|
||||
(@(IntermediateAssembly) and
|
||||
@(ResolvedAssembliesToPublish)). This lets ComputeFilesToPublish
|
||||
be ignorant of the linker, but changes the meaning of
|
||||
IntermediateAssembly and ResolvedAssembliesToPublish.
|
||||
-->
|
||||
<!-- DependsOnTargets here doesn't include the targets that compute
|
||||
ResolvedAssembliesToPublish or IntermediateAssembly, because
|
||||
ComputeFilesToPublish already depends on
|
||||
these. BeforeTargets="ComputeFilesToPublish" ensures that
|
||||
ComputeLinkedFilesToPublish will run before
|
||||
ComputeFilesToPublish, but after all of its dependencies. -->
|
||||
<Target Name="ComputeLinkedFilesToPublish"
|
||||
BeforeTargets="ComputeFilesToPublish"
|
||||
DependsOnTargets="_ComputeLinkedAssemblies"
|
||||
Condition=" '$(LinkDuringPublish)' == 'true' ">
|
||||
<!-- Rewrite ResolvedAssembliesToPublish, which is an input to
|
||||
ComputeFilesToPublish. -->
|
||||
<ItemGroup>
|
||||
<ResolvedAssembliesToPublish Remove="@(_ManagedResolvedAssembliesToPublish)" />
|
||||
<ResolvedAssembliesToPublish Include="@(_LinkedResolvedAssemblies)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Rewrite IntermediateAssembly, which is an input to
|
||||
ComputeFilesToPublish. -->
|
||||
<ItemGroup>
|
||||
<IntermediateAssembly Remove="@(IntermediateAssembly)" />
|
||||
<IntermediateAssembly Include="@(_LinkedIntermediateAssembly)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- Print out a size comparison report for the linked
|
||||
assemblies. This is disabled by default, but can be turned on
|
||||
by setting $(ShowLinkerSizeComparison) to true. This runs after
|
||||
the top-level link target, ComputeLinkedFilesToPublish, so it
|
||||
is output even during incremental builds. -->
|
||||
<UsingTask TaskName="CompareAssemblySizes" AssemblyFile="$(LinkTaskDllPath)" />
|
||||
<Target Name="_CompareLinkedAssemblySizes"
|
||||
AfterTargets="ComputeLinkedFilesToPublish"
|
||||
DependsOnTargets="_ComputeManagedAssembliesToLink;_ComputeLinkedAssemblies"
|
||||
Condition=" '$(LinkDuringPublish)' == 'true' And '$(ShowLinkerSizeComparison)' == 'true' ">
|
||||
<CompareAssemblySizes UnlinkedAssemblies="@(_ManagedAssembliesToLink)"
|
||||
LinkedAssemblies="@(_LinkedIntermediateAssembly);@(_LinkedResolvedAssemblies)" />
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- Computes _LinkedResolvedAssemblies and
|
||||
_LinkedIntermediateAssembly. _LinkedResolvedAssemblies needs to
|
||||
keep metadata from _ManagedResolvedAssembliesToPublish, since
|
||||
this is used by ComputeFilesToPublish. -->
|
||||
<Target Name="_ComputeLinkedAssemblies"
|
||||
DependsOnTargets="_ComputeManagedResolvedAssembliesToPublish;ILLink">
|
||||
<ItemGroup>
|
||||
<__LinkedResolvedAssemblies Include="@(_ManagedResolvedAssembliesToPublish->'$(IntermediateLinkDir)/%(Filename)%(Extension)')" />
|
||||
<_LinkedResolvedAssemblies Include="@(__LinkedResolvedAssemblies)" Condition="Exists('%(Identity)')" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<__LinkedIntermediateAssembly Include="@(IntermediateAssembly->'$(IntermediateLinkDir)/%(Filename)%(Extension)')" />
|
||||
<_LinkedIntermediateAssembly Include="@(__LinkedIntermediateAssembly)" Condition="Exists('%(Identity)')" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- This calls the linker. Inputs are the managed assemblies to
|
||||
link, and root specifications. The semaphore enables msbuild to
|
||||
skip linking during an incremental build, when the semaphore is
|
||||
up to date with respect to _ManagedAssembliesToLink. -->
|
||||
<UsingTask TaskName="ILLink" AssemblyFile="$(LinkTaskDllPath)" />
|
||||
<Target Name="ILLink"
|
||||
DependsOnTargets="_ComputeManagedAssembliesToLink;_ComputeLinkerRootAssemblies;_ComputeLinkerRootDescriptors"
|
||||
Inputs="@(_ManagedAssembliesToLink);@(LinkerRootDescriptors);$(MSBuildAllProjects)"
|
||||
Outputs="$(_LinkSemaphore)">
|
||||
<!-- These extra arguments have been hard-coded for now, as this
|
||||
is what we want to use when linking a self-contained app. In
|
||||
the future we will want to generate these depending on the
|
||||
scenario in which the linker is invoked. -->
|
||||
<PropertyGroup>
|
||||
<ExtraLinkerArgs Condition=" '$(ExtraLinkerArgs)' == '' ">-t -c link -l none</ExtraLinkerArgs>
|
||||
</PropertyGroup>
|
||||
<ILLink AssemblyPaths="@(_ManagedAssembliesToLink)"
|
||||
RootAssemblyNames="@(LinkerRootAssemblies)"
|
||||
RootDescriptorFiles="@(LinkerRootDescriptors)"
|
||||
OutputDirectory="$(IntermediateLinkDir)"
|
||||
ExtraArgs="$(ExtraLinkerArgs)" />
|
||||
|
||||
<Touch Files="$(_LinkSemaphore)" AlwaysCreate="true">
|
||||
<Output TaskParameter="TouchedFiles" ItemName="FileWrites" />
|
||||
</Touch>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- Computes the managed assemblies that are input to the
|
||||
linker. Includes managed assemblies from
|
||||
ResolvedAssembliesToPublish, and IntermediateAssembly. -->
|
||||
<Target Name="_ComputeManagedAssembliesToLink"
|
||||
DependsOnTargets="_ComputeManagedResolvedAssembliesToPublish">
|
||||
<ItemGroup>
|
||||
<_ManagedAssembliesToLink Include="@(IntermediateAssembly)" />
|
||||
<_ManagedAssembliesToLink Include="@(_ManagedResolvedAssembliesToPublish)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- Computes the managed subset of
|
||||
ResolvedAssembliesToPublish. This needs to preserve metadata,
|
||||
because it is later used to compute the linked assemblies with
|
||||
metadata that gets used by the rest of the publish
|
||||
pipeline. This needs to run even during incremental build,
|
||||
because we use the list of managed assemblies to filter the
|
||||
publish output. -->
|
||||
<UsingTask TaskName="ComputeManagedAssemblies" AssemblyFile="$(LinkTaskDllPath)" />
|
||||
<Target Name="_ComputeManagedResolvedAssembliesToPublish">
|
||||
<!-- TODO: Is there a better way to get the managed assemblies
|
||||
from ResolvedAssembliesToPublish? We may be able to check for
|
||||
AssetType="runtime" on managed assemblies - would that give
|
||||
the same set of assemblies? -->
|
||||
<ComputeManagedAssemblies Assemblies="@(ResolvedAssembliesToPublish)">
|
||||
<Output TaskParameter="ManagedAssemblies" ItemName="_ManagedResolvedAssembliesToPublish" />
|
||||
</ComputeManagedAssemblies>
|
||||
<!-- For now, hard-code System.Private.CoreLib.ni, the only .ni
|
||||
file we've been encountering. This is a special case matching
|
||||
how we compute the linker roots by default - we always root
|
||||
System.Private.CoreLib, so we want to keep it in the publish
|
||||
output and the generated deps.json file. Excluding it from
|
||||
_ManagedResolvedAssembliesToPublish will prevent it from
|
||||
getting filtered out of the publish output later.
|
||||
|
||||
In the future we may want to detect ngen assemblies and
|
||||
filter them more robustly. -->
|
||||
<!-- TODO: Which .ni files do we expect to be in
|
||||
ResolvedAssembliesToPublish? -->
|
||||
<ItemGroup>
|
||||
<_ManagedResolvedAssembliesToPublish Remove="@(_ManagedResolvedAssembliesToPublish->WithMetadataValue('Filename', 'System.Private.CoreLib.ni'))" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- Compute the assemblies the linker should mark as roots. By
|
||||
default, these are passed as "-a", but this is an
|
||||
implementation detail of the link task and should not be relied
|
||||
upon in general. In the future we may add other inputs to the
|
||||
link task to control how these are rooted.
|
||||
-->
|
||||
<!-- We may want to add an additional mode in which we root only the
|
||||
assembly we have built, rooting all entry points visible from
|
||||
the outside of the assembly. We need to discuss whether this
|
||||
even makes sense during publish, since typically libraries get
|
||||
packaged via "dotnet pack", and the pack task takes input from
|
||||
build, not from publish. Thus linking the library itself should
|
||||
be part of the build step or pack step, OR pack could be made
|
||||
to work on the publish output. -->
|
||||
<Target Name="_ComputeLinkerRootAssemblies"
|
||||
DependsOnTargets="_ComputeManagedResolvedAssembliesToPublish;_ComputePlatformLibraries">
|
||||
<!-- By default, roots are everything minus the framework
|
||||
assemblies (except for System.Private.CoreLib, which we
|
||||
always root for now). This doesn't include the intermediate
|
||||
assembly, because we root it separately using an xml file,
|
||||
which lets us explicitly root everything. -->
|
||||
<ItemGroup>
|
||||
<LinkerRootAssemblies Include="@(_ManagedResolvedAssembliesToPublish->'%(Filename)')" />
|
||||
<LinkerRootAssemblies Remove="@(PlatformLibraries->'%(Filename)')" />
|
||||
<LinkerRootAssemblies Include="System.Private.CoreLib" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- Platform libraries are the managed runtime assets needed by the
|
||||
"platform", currently Microsoft.NETCore.App. -->
|
||||
<UsingTask TaskName="GetRuntimeLibraries" AssemblyFile="$(LinkTaskDllPath)" />
|
||||
<Target Name="_ComputePlatformLibraries">
|
||||
<GetRuntimeLibraries AssetsFilePath="$(ProjectAssetsFile)"
|
||||
TargetFramework="$(TargetFrameworkMoniker)"
|
||||
RuntimeIdentifier="$(RuntimeIdentifier)"
|
||||
PackageNames="$(MicrosoftNETPlatformLibrary)">
|
||||
<Output TaskParameter="RuntimeLibraries" ItemName="PlatformLibraries" />
|
||||
</GetRuntimeLibraries>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- This target prepares the LinkerRootDescriptors itemgroup for
|
||||
input to the link task. In addition to including user-specified
|
||||
LinkerRootDescriptors in the ItemGroup statically above, we
|
||||
dynamically include the generated descriptor files for the
|
||||
intermediate assembly. -->
|
||||
<Target Name="_ComputeLinkerRootDescriptors"
|
||||
DependsOnTargets="_GenerateIntermediateRootDescriptor">
|
||||
<ItemGroup>
|
||||
<LinkerRootDescriptors Include="$(_IntermediateRootDescriptorPath)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- Generates the xml root descriptor file that completely roots
|
||||
the intermediate assembly. -->
|
||||
<UsingTask TaskName="CreateRootDescriptorFile" AssemblyFile="$(LinkTaskDllPath)" />
|
||||
<Target Name="_GenerateIntermediateRootDescriptor"
|
||||
Inputs="@(IntermediateAssembly)"
|
||||
Outputs="$(_IntermediateRootDescriptorPath)">
|
||||
<CreateRootDescriptorFile AssemblyNames="@(IntermediateAssembly->'%(Filename)')"
|
||||
RootDescriptorFilePath="$(_IntermediateRootDescriptorPath)" />
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- This target needs to remove from the publish deps file those
|
||||
assemblies that were excluded from the publish output by the
|
||||
linker. Currently it does so by rewriting the publish
|
||||
dependency file (as opposed to generating one without the
|
||||
excluded assemblies in the first place).
|
||||
|
||||
TODO: update this to pass FilesToSkip to
|
||||
GeneratePublishDependencyFile once
|
||||
https://github.com/dotnet/sdk/pull/1052 is merged.
|
||||
-->
|
||||
<UsingTask TaskName="DepsJsonLinker" AssemblyFile="$(LinkTaskDllPath)" />
|
||||
<Target Name="_GenerateLinkedPublishDependencyFile"
|
||||
DependsOnTargets="_ComputeManagedAssembliesToLink;_ComputeLinkedAssemblies"
|
||||
AfterTargets="GeneratePublishDependencyFile"
|
||||
Condition=" '$(LinkDuringPublish)' == 'true' "
|
||||
Inputs="@(_ManagedResolvedAssembliesToPublish);@(_LinkedResolvedAssemblies);$(PublishDepsFilePath)"
|
||||
Outputs="$(_LinkDepsSemaphore)">
|
||||
<!-- DepsJsonLinker expects inputs in the form of filename.dll. -->
|
||||
<!-- We pass _ManagedResolvedAssembliesToPublish, which doesn't
|
||||
contain any .ni files. This correctly prevents stripping of
|
||||
the .ni files (which we want to continue publishing at the
|
||||
moment). -->
|
||||
<!-- This doesn't filter any assemblies from IntermediateAssembly,
|
||||
which should currently always be rooted by default. -->
|
||||
<DepsJsonLinker InputDepsFilePath="$(PublishDepsFilePath)"
|
||||
OutputDepsFilePath="$(PublishDepsFilePath)"
|
||||
ManagedPublishAssemblies="@(_ManagedResolvedAssembliesToPublish->'%(Filename)%(Extension)')"
|
||||
KeptAssemblies="@(_LinkedResolvedAssemblies->'%(Filename)%(Extension)')" />
|
||||
<Touch Files="$(_LinkDepsSemaphore)" AlwaysCreate="true">
|
||||
<Output TaskParameter="TouchedFiles" ItemName="FileWrites" />
|
||||
</Touch>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
102
external/linker/corebuild/integration/ILLink.Tasks/LinkTask.cs
vendored
Normal file
102
external/linker/corebuild/integration/ILLink.Tasks/LinkTask.cs
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace ILLink.Tasks
|
||||
{
|
||||
public class ILLink : Task
|
||||
{
|
||||
/// <summary>
|
||||
/// Paths to the assembly files that should be considered as
|
||||
/// input to the linker. Currently the linker will
|
||||
/// additionally be able to resolve any assemblies in the
|
||||
/// same directory as an assembly in AssemblyPaths, but this
|
||||
/// behavior should not be relied upon. Instead, work under
|
||||
/// the assumption that only the AssemblyPaths given will be
|
||||
/// resolved.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] AssemblyPaths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The names of the assemblies to root. This should contain
|
||||
/// assembly names without an extension, not file names or
|
||||
/// paths. Exactly which parts of the assemblies get rooted
|
||||
/// is subject to change. Currently these get passed to
|
||||
/// illink with "-a", which roots the entry point for
|
||||
/// executables, and everything for libraries. To control
|
||||
/// the linker more explicitly, either pass descriptor
|
||||
/// files, or pass extra arguments for illink.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] RootAssemblyNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The directory in which to place linked assemblies.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem OutputDirectory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of XML root descriptor files specifying linker
|
||||
/// roots at a granular level. See the mono/linker
|
||||
/// documentation for details about the format.
|
||||
/// </summary>
|
||||
public ITaskItem[] RootDescriptorFiles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Extra arguments to pass to illink, delimited by spaces.
|
||||
/// </summary>
|
||||
public string ExtraArgs { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
string[] args = GenerateCommandLineCommands();
|
||||
var argsString = String.Join(" ", args);
|
||||
Log.LogMessageFromText($"illink {argsString}", MessageImportance.Normal);
|
||||
int ret = Mono.Linker.Driver.Main(args);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
private string[] GenerateCommandLineCommands()
|
||||
{
|
||||
var args = new List<string>();
|
||||
|
||||
if (RootDescriptorFiles != null) {
|
||||
foreach (var rootFile in RootDescriptorFiles) {
|
||||
args.Add("-x");
|
||||
args.Add(rootFile.ItemSpec);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var assemblyItem in RootAssemblyNames) {
|
||||
args.Add("-a");
|
||||
args.Add(assemblyItem.ItemSpec);
|
||||
}
|
||||
|
||||
var assemblyDirs = AssemblyPaths.Select(p => Path.GetDirectoryName(p.ItemSpec))
|
||||
.GroupBy(d => d).Select(ds => ds.First());
|
||||
foreach (var dir in assemblyDirs) {
|
||||
args.Add("-d");
|
||||
args.Add(dir);
|
||||
}
|
||||
|
||||
if (OutputDirectory != null) {
|
||||
args.Add("-out");
|
||||
args.Add(OutputDirectory.ItemSpec);
|
||||
}
|
||||
|
||||
if (ExtraArgs != null) {
|
||||
args.AddRange(ExtraArgs.Split(' '));
|
||||
}
|
||||
|
||||
return args.ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Microsoft.NET.Build.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an error that is neither avoidable in all cases nor indicative of a bug in this library.
|
||||
/// It will be logged as a plain build error without the exception type or stack.
|
||||
/// </summary>
|
||||
internal class BuildErrorException : Exception
|
||||
{
|
||||
public BuildErrorException()
|
||||
{
|
||||
}
|
||||
|
||||
public BuildErrorException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public BuildErrorException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public BuildErrorException(string format, params string[] args)
|
||||
: this(string.Format(CultureInfo.CurrentCulture, format, args))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
62
external/linker/corebuild/integration/ILLink.Tasks/Microsoft.NET.Build.Tasks/LockFileCache.cs
vendored
Normal file
62
external/linker/corebuild/integration/ILLink.Tasks/Microsoft.NET.Build.Tasks/LockFileCache.cs
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Build.Framework;
|
||||
using NuGet.Common;
|
||||
using NuGet.ProjectModel;
|
||||
|
||||
namespace Microsoft.NET.Build.Tasks
|
||||
{
|
||||
internal class LockFileCache
|
||||
{
|
||||
private IBuildEngine4 _buildEngine;
|
||||
|
||||
public LockFileCache(IBuildEngine4 buildEngine)
|
||||
{
|
||||
_buildEngine = buildEngine;
|
||||
}
|
||||
|
||||
public LockFile GetLockFile(string path)
|
||||
{
|
||||
if (!Path.IsPathRooted(path))
|
||||
{
|
||||
throw new BuildErrorException("Assets file path '{0}' is not rooted. Only full paths are supported.", path);
|
||||
}
|
||||
|
||||
string lockFileKey = GetTaskObjectKey(path);
|
||||
|
||||
LockFile result;
|
||||
object existingLockFileTaskObject = _buildEngine.GetRegisteredTaskObject(lockFileKey, RegisteredTaskObjectLifetime.Build);
|
||||
if (existingLockFileTaskObject == null)
|
||||
{
|
||||
result = LoadLockFile(path);
|
||||
|
||||
_buildEngine.RegisterTaskObject(lockFileKey, result, RegisteredTaskObjectLifetime.Build, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (LockFile)existingLockFileTaskObject;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetTaskObjectKey(string lockFilePath)
|
||||
{
|
||||
return $"{nameof(LockFileCache)}:{lockFilePath}";
|
||||
}
|
||||
|
||||
private LockFile LoadLockFile(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new BuildErrorException("Assets file '{0}' not found. Run a NuGet package restore to generate this file.", path);
|
||||
}
|
||||
|
||||
// TODO - https://github.com/dotnet/sdk/issues/18 adapt task logger to Nuget Logger
|
||||
return LockFileUtilities.GetLockFile(path, NullLogger.Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
external/linker/corebuild/integration/build.ps1
vendored
Normal file
9
external/linker/corebuild/integration/build.ps1
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
$tasksFolder="~\.nuget\packages\illink.tasks"
|
||||
If (Test-Path $tasksFolder) {
|
||||
Remove-Item -r $tasksFolder
|
||||
}
|
||||
|
||||
$dotNetTool = Join-Path $PSScriptRoot "..\corebuild\dotnet.ps1"
|
||||
# create integration packages
|
||||
& $dotNetTool restore (Join-Path $PSScriptRoot "linker.sln")
|
||||
& $dotNetTool pack (Join-Path $PSScriptRoot "linker.sln")
|
||||
14
external/linker/corebuild/integration/build.sh
vendored
Executable file
14
external/linker/corebuild/integration/build.sh
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
__scriptpath=$(cd "$(dirname "$0")"; pwd -P)
|
||||
|
||||
tasksFolder=~/.nuget/packages/illink.tasks
|
||||
if [ -d $tasksFolder ]
|
||||
then
|
||||
rm -r $tasksFolder
|
||||
fi
|
||||
|
||||
dotNetTool=$__scriptpath/../corebuild/dotnet.sh
|
||||
# create integration packages
|
||||
$dotNetTool restore $__scriptpath/linker.sln
|
||||
$dotNetTool pack $__scriptpath/linker.sln
|
||||
76
external/linker/corebuild/integration/linker.sln
vendored
Normal file
76
external/linker/corebuild/integration/linker.sln
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26124.0
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILLink.Tasks", "ILLink.Tasks\ILLink.Tasks.csproj", "{42050FFF-50CB-41D5-B617-68D1624FE716}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Linker", "..\..\linker\Mono.Linker.csproj", "{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "..\..\cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "..\..\cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Debug|x64.Build.0 = Debug|x64
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Debug|x86.Build.0 = Debug|x86
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Release|x64.ActiveCfg = Release|x64
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Release|x64.Build.0 = Release|x64
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Release|x86.ActiveCfg = Release|x86
|
||||
{42050FFF-50CB-41D5-B617-68D1624FE716}.Release|x86.Build.0 = Release|x86
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|Any CPU.ActiveCfg = netcore_Debug|Any CPU
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|Any CPU.Build.0 = netcore_Debug|Any CPU
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|x64.ActiveCfg = netcore_Debug|x64
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|x64.Build.0 = netcore_Debug|x64
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|x86.ActiveCfg = netcore_Debug|x86
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|x86.Build.0 = netcore_Debug|x86
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|Any CPU.ActiveCfg = netcore_Release|Any CPU
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|Any CPU.Build.0 = netcore_Release|Any CPU
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|x64.ActiveCfg = netcore_Release|x64
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|x64.Build.0 = netcore_Release|x64
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|x86.ActiveCfg = netcore_Release|x86
|
||||
{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|x86.Build.0 = netcore_Release|x86
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = netstandard_Debug|Any CPU
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = netstandard_Debug|Any CPU
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x64.ActiveCfg = netstandard_Debug|x64
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x64.Build.0 = netstandard_Debug|x64
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = netstandard_Debug|x86
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = netstandard_Debug|x86
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = netstandard_Release|Any CPU
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = netstandard_Release|Any CPU
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x64.ActiveCfg = netstandard_Release|x64
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x64.Build.0 = netstandard_Release|x64
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = netstandard_Release|x86
|
||||
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = netstandard_Release|x86
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.ActiveCfg = netstandard_Debug|Any CPU
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = netstandard_Debug|Any CPU
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|x64.ActiveCfg = netstandard_Debug|x64
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|x64.Build.0 = netstandard_Debug|x64
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|x86.ActiveCfg = netstandard_Debug|x86
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|x86.Build.0 = netstandard_Debug|x86
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = netstandard_Release|Any CPU
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.Build.0 = netstandard_Release|Any CPU
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x64.ActiveCfg = netstandard_Release|x64
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x64.Build.0 = netstandard_Release|x64
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x86.ActiveCfg = netstandard_Release|x86
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x86.Build.0 = netstandard_Release|x86
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
41
external/linker/corebuild/integration/test/HelloWorldTest.cs
vendored
Normal file
41
external/linker/corebuild/integration/test/HelloWorldTest.cs
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace ILLink.Tests
|
||||
{
|
||||
public class HelloWorldTest : IntegrationTestBase
|
||||
{
|
||||
public HelloWorldTest(ITestOutputHelper output) : base(output) {}
|
||||
|
||||
public string SetupProject()
|
||||
{
|
||||
string projectRoot = "helloworld";
|
||||
|
||||
if (Directory.Exists(projectRoot)) {
|
||||
Directory.Delete(projectRoot, true);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(projectRoot);
|
||||
int ret = Dotnet("new console", projectRoot);
|
||||
if (ret != 0) {
|
||||
output.WriteLine("dotnet new failed");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj");
|
||||
return csproj;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunHelloWorld()
|
||||
{
|
||||
string csproj = SetupProject();
|
||||
|
||||
AddLinkerReference(csproj);
|
||||
|
||||
BuildAndLink(csproj, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
147
external/linker/corebuild/integration/test/IntegrationTestBase.cs
vendored
Normal file
147
external/linker/corebuild/integration/test/IntegrationTestBase.cs
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace ILLink.Tests
|
||||
{
|
||||
public class IntegrationTestBase
|
||||
{
|
||||
protected readonly ITestOutputHelper output;
|
||||
|
||||
protected readonly TestContext context;
|
||||
|
||||
public IntegrationTestBase(ITestOutputHelper output)
|
||||
{
|
||||
this.output = output;
|
||||
|
||||
// This sets up the context with some values specific to
|
||||
// the setup of the linker repository. A different context
|
||||
// should be used in order to run tests in a different
|
||||
// environment.
|
||||
this.context = TestContext.CreateDefaultContext();
|
||||
}
|
||||
|
||||
protected int Dotnet(string args, string workingDir, string additionalPath = null)
|
||||
{
|
||||
return RunCommand(context.DotnetToolPath, args, workingDir, additionalPath);
|
||||
}
|
||||
|
||||
protected int RunCommand(string command, string args, string workingDir, string additionalPath = null)
|
||||
{
|
||||
output.WriteLine($"{command} {args}");
|
||||
if (workingDir != null)
|
||||
output.WriteLine($"working directory: {workingDir}");
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = command,
|
||||
Arguments = args,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
WorkingDirectory = workingDir,
|
||||
};
|
||||
|
||||
if (additionalPath != null) {
|
||||
string path = psi.Environment["PATH"];
|
||||
psi.Environment["PATH"] = path + ";" + additionalPath;
|
||||
}
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = psi,
|
||||
};
|
||||
|
||||
process.Start();
|
||||
string capturedOutput = process.StandardOutput.ReadToEnd();
|
||||
output.WriteLine(capturedOutput);
|
||||
string capturedError = process.StandardError.ReadToEnd();
|
||||
output.WriteLine(capturedError);
|
||||
process.WaitForExit();
|
||||
return process.ExitCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the linker on the specified project. This assumes
|
||||
/// that the project already contains a reference to the
|
||||
/// linker task package.
|
||||
/// Optionally takes a list of root descriptor files.
|
||||
/// </summary>
|
||||
public void BuildAndLink(string csproj, List<string> rootFiles = null)
|
||||
{
|
||||
string rid = context.RuntimeIdentifier;
|
||||
string config = context.Configuration;
|
||||
string demoRoot = Path.GetDirectoryName(csproj);
|
||||
|
||||
int ret = Dotnet($"restore -r {rid}", demoRoot);
|
||||
if (ret != 0) {
|
||||
output.WriteLine("restore failed");
|
||||
Assert.True(false);
|
||||
return;
|
||||
}
|
||||
|
||||
string publishArgs = $"publish -r {rid} -c {config} /v:n /p:ShowLinkerSizeComparison=true";
|
||||
string rootFilesStr;
|
||||
if (rootFiles != null && rootFiles.Any()) {
|
||||
rootFilesStr = String.Join(";", rootFiles);
|
||||
publishArgs += $" /p:LinkerRootDescriptors={rootFilesStr}";
|
||||
}
|
||||
ret = Dotnet(publishArgs, demoRoot);
|
||||
if (ret != 0) {
|
||||
output.WriteLine("publish failed");
|
||||
Assert.True(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected void AddLinkerReference(string csproj)
|
||||
{
|
||||
var xdoc = XDocument.Load(csproj);
|
||||
var ns = xdoc.Root.GetDefaultNamespace();
|
||||
bool added = false;
|
||||
foreach (var el in xdoc.Root.Elements(ns + "ItemGroup")) {
|
||||
if (el.Elements(ns + "PackageReference").Any()) {
|
||||
el.Add(new XElement(ns+"PackageReference",
|
||||
new XAttribute("Include", context.TasksPackageName),
|
||||
new XAttribute("Version", context.TasksPackageVersion)));
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
xdoc.Root.Add(new XElement(ns + "ItemGroup",
|
||||
new XElement(ns + "PackageReference",
|
||||
new XAttribute("Include", context.TasksPackageName),
|
||||
new XAttribute("Version", context.TasksPackageVersion))));
|
||||
added= true;
|
||||
}
|
||||
|
||||
using (var fs = new FileStream(csproj, FileMode.Create)) {
|
||||
xdoc.Save(fs);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddLinkerRoots(string csproj, List<string> rootFiles)
|
||||
{
|
||||
var xdoc = XDocument.Load(csproj);
|
||||
var ns = xdoc.Root.GetDefaultNamespace();
|
||||
|
||||
var rootsItemGroup = new XElement(ns+"ItemGroup");
|
||||
foreach (var rootFile in rootFiles) {
|
||||
rootsItemGroup.Add(new XElement(ns+"LinkerRootFiles",
|
||||
new XAttribute("Include", rootFile)));
|
||||
}
|
||||
|
||||
var propertyGroup = xdoc.Root.Elements(ns + "PropertyGroup").First();
|
||||
propertyGroup.AddAfterSelf(rootsItemGroup);
|
||||
|
||||
using (var fs = new FileStream(csproj, FileMode.Create)) {
|
||||
xdoc.Save(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
external/linker/corebuild/integration/test/MusicStoreReflection.xml
vendored
Executable file
20
external/linker/corebuild/integration/test/MusicStoreReflection.xml
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
<linker>
|
||||
<!--- Called by Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions:.cctor -->
|
||||
<assembly fullname="System.Linq.Queryable">
|
||||
<type fullname="System.Linq.Queryable" required="true" />
|
||||
</assembly>
|
||||
|
||||
<!--- Called by System.Linq.Expressions.Expression:CreateLambda -->
|
||||
<assembly fullname="System.Linq.Expressions">
|
||||
<type fullname="System.Linq.Expressions.Expression`1" required="true" />
|
||||
</assembly>
|
||||
|
||||
<assembly fullname="System.Dynamic.Runtime">
|
||||
<!--- Called by [System.Dynamic.Runtime]System.Runtime.CompilerServices.CallSite<>.CreateCustomNoMatchDelegate and [System.Dynamic.Runtime]System.Runtime.CompilerServices.CallSite<>.CreateCustomUpdateDelegate-->
|
||||
<type fullname="System.Runtime.CompilerServices.CallSiteOps" required="true" />
|
||||
<!--- Called by [System.Dynamic.Runtime]System.Runtime.CompilerServices.CallSiteBinder.Stitch -->
|
||||
<type fullname="System.Runtime.CompilerServices.CallSite" required="true" />
|
||||
<!--- Called by [System.Dynamic.Runtime]System.Runtime.CompilerServices.CallSiteBinder.Stitch -->
|
||||
<type fullname="System.Runtime.CompilerServices.CallSite`1" required="true" />
|
||||
</assembly>
|
||||
</linker>
|
||||
94
external/linker/corebuild/integration/test/MusicStoreTest.cs
vendored
Normal file
94
external/linker/corebuild/integration/test/MusicStoreTest.cs
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions; // ITestOutputHelper
|
||||
|
||||
namespace ILLink.Tests
|
||||
{
|
||||
public class MusicStoreTest : IntegrationTestBase
|
||||
{
|
||||
public MusicStoreTest(ITestOutputHelper output) : base(output) {}
|
||||
|
||||
private static List<string> rootFiles = new List<string> { "MusicStoreReflection.xml" };
|
||||
|
||||
[Fact]
|
||||
public void RunMusicStore()
|
||||
{
|
||||
string csproj = SetupProject();
|
||||
|
||||
// Copy root files into the project directory
|
||||
string demoRoot= Path.GetDirectoryName(csproj);
|
||||
CopyRootFiles(demoRoot);
|
||||
|
||||
// This is necessary because JitBench comes with a
|
||||
// NuGet.Config that has a <clear /> line, preventing
|
||||
// NuGet.Config sources defined in outer directories from
|
||||
// applying.
|
||||
string nugetConfig = Path.Combine("JitBench", "NuGet.config");
|
||||
AddLocalNugetFeedAfterClear(nugetConfig);
|
||||
|
||||
AddLinkerReference(csproj);
|
||||
|
||||
BuildAndLink(csproj, rootFiles);
|
||||
}
|
||||
|
||||
// returns path to .csproj project file
|
||||
string SetupProject()
|
||||
{
|
||||
string gitRepo = "http://github.com/aspnet/JitBench";
|
||||
string repoName = "JitBench";
|
||||
string gitBranch = "dev";
|
||||
string demoRoot = Path.Combine("JitBench", Path.Combine("src", "MusicStore"));
|
||||
|
||||
int ret;
|
||||
if (Directory.Exists(repoName)) {
|
||||
Directory.Delete(repoName, true);
|
||||
}
|
||||
|
||||
ret = RunCommand("git", $"clone {gitRepo}", null, null);
|
||||
if (ret != 0) {
|
||||
output.WriteLine("git failed");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(demoRoot)) {
|
||||
output.WriteLine($"{demoRoot} does not exist");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
ret = RunCommand("git", $"checkout {gitBranch}", demoRoot, null);
|
||||
if (ret != 0) {
|
||||
output.WriteLine($"problem checking out branch {gitBranch}");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
string csproj = Path.Combine(demoRoot, "MusicStore.csproj");
|
||||
return csproj;
|
||||
}
|
||||
|
||||
static void CopyRootFiles(string demoRoot)
|
||||
{
|
||||
foreach (var rf in rootFiles) {
|
||||
File.Copy(rf, Path.Combine(demoRoot, rf));
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLocalNugetFeedAfterClear(string nugetConfig)
|
||||
{
|
||||
string localPackagePath = Path.GetFullPath(context.PackageSource);
|
||||
var xdoc = XDocument.Load(nugetConfig);
|
||||
var ns = xdoc.Root.GetDefaultNamespace();
|
||||
var clear = xdoc.Root.Element(ns+"packageSources").Element(ns+"clear");
|
||||
clear.Parent.Add(new XElement(ns+"add",
|
||||
new XAttribute("key", "local linker feed"),
|
||||
new XAttribute("value", localPackagePath)));
|
||||
|
||||
using (var fs = new FileStream(nugetConfig, FileMode.Create)) {
|
||||
xdoc.Save(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
external/linker/corebuild/integration/test/NuGet.config
vendored
Normal file
10
external/linker/corebuild/integration/test/NuGet.config
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
|
||||
<!-- When the tests are run from the repo's test bin directory,
|
||||
this NuGet.config should be read to find the local package
|
||||
directory. -->
|
||||
<add key="local linker packages" value="../nupkgs" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user