Imported Upstream version 5.4.0.167

Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-08-21 15:34:15 +00:00
parent e49d6f06c0
commit 536cd135cc
12856 changed files with 563812 additions and 223249 deletions

View File

@@ -8,12 +8,15 @@
# User-specific files
*.suo
*.user
*.userprefs
.vs/
.idea/
packages/
# Build results
linker/obj
linker/bin
obj/
bin/
.DS_Store

View File

@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!-- nuget-build is necessary for the integration package to
depend on the same NuGet package that the sdk uses -->
<add key="nuget-build" value="https://dotnet.myget.org/F/nuget-build/api/v3/index.json" />
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View File

@@ -1,8 +1,11 @@
The Mono linker is a tool one can use to only ship the minimal possible set of functions that a set of
# IL linker
The linker is a tool one can use to only ship the minimal possible IL code and metadata that a set of
programs might require to run as opposed to the full libraries.
It is used by the various Xamarin products to extract only the bits of code that are needed to run
an application on Android, iOS and other platforms.
This file was extracted from Mono (github.com/mono/mono) on November 1st, 2016 to allow easier
sharing of the linker code with other .NET projects.
### Build & Test Status
[![Build Status](https://jenkins.mono-project.com/buildStatus/icon?job=test-linker-mainline)](https://jenkins.mono-project.com/job/test-linker-mainline/)

View File

@@ -34,7 +34,7 @@ namespace Mono.Cecil.Cil {
Mixin.CheckModule (module);
Mixin.CheckStream (symbolStream);
return GetSymbolReader (module, Disposable.NotOwned (symbolStream), "");
return GetSymbolReader (module, Disposable.NotOwned (symbolStream), symbolStream.GetFileName ());
}
ISymbolReader GetSymbolReader (ModuleDefinition module, Disposable<Stream> symbolStream, string fileName)
@@ -301,7 +301,11 @@ namespace Mono.Cecil.Cil {
// PDB Age
buffer.WriteUInt32 (1);
// PDB Path
buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (writer.BaseStream.GetFileName ()));
var filename = writer.BaseStream.GetFileName ();
if (!string.IsNullOrEmpty (filename))
filename = Path.GetFileName (filename);
buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (filename));
buffer.WriteByte (0);
var data = new byte [buffer.length];

View File

@@ -2986,13 +2986,13 @@ namespace Mono.Cecil {
value = Encoding.Unicode.GetString (bytes, 0, bytes.Length);
} else
value = null;
} else if (type.etype == ElementType.Object) {
value = null;
} else if (type.IsTypeOf ("System", "Decimal")) {
var b = signature.ReadByte ();
value = new decimal (signature.ReadInt32 (), signature.ReadInt32 (), signature.ReadInt32 (), (b & 0x80) != 0, (byte) (b & 0x7f));
} else if (type.IsTypeOf ("System", "DateTime")) {
value = new DateTime (signature.ReadInt64());
} else if (type.etype == ElementType.Object || type.etype == ElementType.None || type.etype == ElementType.Class) {
value = null;
} else
value = signature.ReadConstantSignature (type.etype);

View File

@@ -122,9 +122,8 @@ namespace Mono.Cecil {
#if !NET_CORE
if (parameters.StrongNameKeyPair != null)
CryptoService.StrongName (stream.value, writer, parameters.StrongNameKeyPair);
stream.Dispose ();
#endif
stream.Dispose ();
}
static void BuildMetadata (ModuleDefinition module, MetadataBuilder metadata)
@@ -2152,6 +2151,7 @@ namespace Mono.Cecil {
case ElementType.SzArray:
case ElementType.Class:
case ElementType.Object:
case ElementType.None:
case ElementType.Var:
case ElementType.MVar:
signature.WriteInt32 (0);

View File

@@ -995,19 +995,7 @@ namespace Mono.Cecil {
public ImageDebugHeader GetDebugHeader ()
{
if (!HasDebugHeader)
throw new InvalidOperationException ();
return Image.DebugHeader;
}
void ProcessDebugHeader ()
{
if (!HasDebugHeader)
return;
if (!symbol_reader.ProcessDebugHeader (GetDebugHeader ()))
throw new InvalidOperationException ();
return Image.DebugHeader ?? new ImageDebugHeader ();
}
#if !READ_ONLY
@@ -1084,7 +1072,10 @@ namespace Mono.Cecil {
symbol_reader = reader;
ProcessDebugHeader ();
if (!symbol_reader.ProcessDebugHeader (GetDebugHeader ())) {
symbol_reader = null;
throw new InvalidOperationException ();
}
if (HasImage && ReadingMode == ReadingMode.Immediate) {
var immediate_reader = new ImmediateModuleReader (Image);
@@ -1135,7 +1126,7 @@ namespace Mono.Cecil {
Mixin.CheckStream (stream);
Mixin.CheckReadSeek (stream);
return ReadModule (Disposable.NotOwned (stream), "", parameters);
return ReadModule (Disposable.NotOwned (stream), stream.GetFileName (), parameters);
}
static ModuleDefinition ReadModule (Disposable<Stream> stream, string fileName, ReaderParameters parameters)

View File

@@ -263,6 +263,20 @@ namespace Mono.Cecil.Tests {
}
}
[Test]
public void OwnedStreamModuleFileName ()
{
var path = GetAssemblyResourcePath ("hello.exe", GetType ().Assembly);
using (var file = File.Open (path, FileMode.Open))
{
using (var module = ModuleDefinition.ReadModule (file))
{
Assert.IsNotNullOrEmpty (module.FileName);
Assert.AreEqual (path, module.FileName);
}
}
}
[Test]
public void ReadAndWriteFile ()
{

View File

@@ -387,6 +387,22 @@ namespace Mono.Cecil.Tests {
}, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider));
}
[Test]
public void NullClassConstant ()
{
TestModule ("xattr.dll", module => {
var type = module.GetType ("Library");
var method = type.GetMethod ("NullXAttributeConstant");
var symbol = method.DebugInformation;
Assert.IsNotNull (symbol);
Assert.AreEqual(1, symbol.Scope.Constants.Count);
var a = symbol.Scope.Constants [0];
Assert.AreEqual ("a", a.Name);
}, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider));
}
[Test]
public void PortablePdbLineInfo ()
{

Binary file not shown.

View File

@@ -1 +1 @@
2.0.0-preview1-005685
2.0.0-preview2-005905

View File

@@ -59,24 +59,6 @@ if ($LastExitCode -ne 0)
exit $LastExitCode
}
# create a junction to the shared FX version directory. this is
# so we have a stable path to dotnet.exe regardless of version.
$runtimesPath = Join-Path $CliLocalPath "shared\Microsoft.NETCore.App"
if ($SharedFrameworkVersion -eq "<auto>")
{
$SharedFrameworkVersion = Get-ChildItem $runtimesPath -Directory | Sort-Object | Select-Object -First 1 | % { New-Object System.Version($_) }
}
$junctionTarget = Join-Path $runtimesPath $SharedFrameworkVersion
$junctionParent = Split-Path $SharedFrameworkSymlinkPath -Parent
if (-Not (Test-Path $junctionParent))
{
mkdir $junctionParent | Out-Null
}
if (-Not (Test-Path $SharedFrameworkSymlinkPath))
{
cmd.exe /c mklink /j $SharedFrameworkSymlinkPath $junctionTarget | Out-Null
}
# write semaphore file
copy $rootCliVersion $bootstrapComplete
exit 0

View File

@@ -197,26 +197,6 @@ if [ $forcedCliLocalPath = "<none>" ]; then
fi
fi
runtimesPath="$cliLocalPath/shared/Microsoft.NETCore.App"
if [ $sharedFxVersion = "<auto>" ]; then
# OSX doesn't support --version-sort, https://stackoverflow.com/questions/21394536/how-to-simulate-sort-v-on-mac-osx
sharedFxVersion=`ls $runtimesPath | sed 's/^[0-9]\./0&/; s/\.\([0-9]\)$/.0\1/; s/\.\([0-9]\)\./.0\1./g; s/\.\([0-9]\)\./.0\1./g' | sort -r | sed 's/^0// ; s/\.0/./g' | head -n 1`
fi
# create a junction to the shared FX version directory. this is
# so we have a stable path to dotnet.exe regardless of version.
junctionTarget="$runtimesPath/$sharedFxVersion"
junctionParent="$(dirname "$symlinkPath")"
if [ ! -d $junctionParent ]; then
mkdir -p $junctionParent
fi
if [ ! -e $symlinkPath ]; then
ln -s $junctionTarget $symlinkPath
fi
cp $rootCliVersion $bootstrapComplete
say "Bootstrap finished successfully."

View File

@@ -12,7 +12,7 @@ if [ ! -e $bootStrapperPath ]; then
cp $__scriptpath/bootstrap.sh $__scriptpath/Tools
fi
$bootStrapperPath --repositoryRoot $__scriptpath --toolsLocalPath $toolsLocalPath > bootstrap.log
$bootStrapperPath --verbose --repositoryRoot $__scriptpath --toolsLocalPath $toolsLocalPath > bootstrap.log
lastExitCode=$?
if [ $lastExitCode -ne 0 ]; then
echo "Boot-strapping failed with exit code $lastExitCode, see bootstrap.log for more information."

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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();
}
}
}

View 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;
}
}
}

Some files were not shown because too many files have changed in this diff Show More