Imported Upstream version 6.0.0.172

Former-commit-id: f3cc9b82f3e5bd8f0fd3ebc098f789556b44e9cd
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-04-12 14:10:50 +00:00
parent 8016999e4d
commit 64ac736ec5
32155 changed files with 3981439 additions and 75368 deletions

View File

@ -1,49 +0,0 @@
using System;
using System.Collections.Generic;
using Mono.Linker;
using Mono.Linker.Steps;
using Mono.Cecil;
namespace ILLink.CustomSteps
{
public class ClearInitLocalsStep : BaseStep
{
HashSet<string> _assemblies;
protected override void Process ()
{
string parameterName = "ClearInitLocalsAssemblies";
if (Context.HasParameter (parameterName)) {
string parameter = Context.GetParameter (parameterName);
_assemblies = new HashSet<string> (parameter.Split(','), StringComparer.OrdinalIgnoreCase);
}
}
protected override void ProcessAssembly (AssemblyDefinition assembly)
{
if ((_assemblies != null) && (!_assemblies.Contains (assembly.Name.Name))) {
return;
}
bool changed = false;
foreach (ModuleDefinition module in assembly.Modules) {
foreach (TypeDefinition type in module.Types) {
foreach (MethodDefinition method in type.Methods) {
if (method.Body != null) {
if (method.Body.InitLocals) {
method.Body.InitLocals = false;
changed = true;
}
}
}
}
}
if (changed && (Annotations.GetAction (assembly) == AssemblyAction.Copy))
Annotations.SetAction (assembly, AssemblyAction.Save);
}
}
}

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
<DefineConstants>$(DefineConstants);FEATURE_ILLINK</DefineConstants>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AssemblyName>ILLink.CustomSteps</AssemblyName>
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup>
<ProjectGuid>{275C1D10-168A-4AC4-8F3E-AD969F580B9C}</ProjectGuid>
</PropertyGroup>
<ItemGroup>
<Compile Include="ClearInitLocals.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\linker\Mono.Linker.csproj">
<SetConfiguration Condition=" '$(Configuration)' == 'illink_Debug' ">Configuration=illink_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(Configuration)' == 'illink_Release' ">Configuration=illink_Release</SetConfiguration>
<Project>{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\cecil\Mono.Cecil.csproj">
<SetConfiguration Condition=" '$(Configuration)' == 'illink_Debug' ">Configuration=netstandard_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(Configuration)' == 'illink_Debug' And '$(TargetFramework)' == 'net46' ">Configuration=net_4_0_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(Configuration)' == 'illink_Release' ">Configuration=netstandard_Release</SetConfiguration>
<SetConfiguration Condition=" '$(Configuration)' == 'illink_Release' And '$(TargetFramework)' == 'net46' ">Configuration=net_4_0_Release</SetConfiguration>
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
</ProjectReference>
</ItemGroup>
<!-- The reference to the linker will cause Mono.Cecil.Pdb to be
built in the wrong configuration unless we apply this
workaround. -->
<Target Name="SetCecilConfiguration"
AfterTargets="AssignProjectConfiguration">
<ItemGroup>
<ProjectReferenceWithConfiguration Condition=" '%(Filename)%(Extension)' == 'Mono.Cecil.Pdb.csproj' ">
<SetConfiguration Condition=" '$(TargetFramework)' == 'net46' And '$(Configuration)' == 'illink_Debug' ">Configuration=net_4_0_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'netcoreapp2.0' And '$(Configuration)' == 'illink_Debug' ">Configuration=netstandard_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'net46' And '$(Configuration)' == 'illink_Release' ">Configuration=net_4_0_Release</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'netcoreapp2.0' And '$(Configuration)' == 'illink_Release' ">Configuration=netstandard_Release</SetConfiguration>
</ProjectReferenceWithConfiguration>
<ProjectReferenceWithConfiguration Condition=" '%(Filename)%(Extension)' == 'Mono.Cecil.Mdb.csproj' ">
<SetConfiguration Condition=" '$(TargetFramework)' == 'net46' And '$(Configuration)' == 'illink_Debug' ">Configuration=net_4_0_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'netcoreapp2.0' And '$(Configuration)' == 'illink_Debug' ">Configuration=netstandard_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'net46' And '$(Configuration)' == 'illink_Release' ">Configuration=net_4_0_Release</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'netcoreapp2.0' And '$(Configuration)' == 'illink_Release' ">Configuration=netstandard_Release</SetConfiguration>
</ProjectReferenceWithConfiguration>
</ItemGroup>
</Target>
</Project>

View File

@ -1,37 +0,0 @@
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{
class AdapterLogger : Mono.Linker.ILogger
{
private TaskLoggingHelper log;
public AdapterLogger (TaskLoggingHelper log)
{
this.log = log;
}
public void LogMessage (Mono.Linker.MessageImportance importance, string message, params object[] values)
{
Microsoft.Build.Framework.MessageImportance msBuildImportance;
switch (importance)
{
case Mono.Linker.MessageImportance.High:
msBuildImportance = MessageImportance.High;
break;
case Mono.Linker.MessageImportance.Normal:
msBuildImportance = MessageImportance.Normal;
break;
case Mono.Linker.MessageImportance.Low:
msBuildImportance = MessageImportance.Low;
break;
default:
throw new ArgumentException ($"Unrecognized importance level {importance}", nameof(importance));
}
log.LogMessageFromText (String.Format (message, values), msBuildImportance);
}
}
}

View File

@ -1,37 +0,0 @@
using Microsoft.Build.Utilities; // Task
using Microsoft.Build.Framework; // ITaskItem
using Mono.Cecil;
namespace ILLink.Tasks
{
public class CheckEmbeddedRootDescriptor : Task
{
/// <summary>
/// Path to the assembly.
/// </summary>
[Required]
public ITaskItem AssemblyPath { get; set; }
/// <summary>
/// This will be set to true if the assembly has an embedded root descriptor.
/// </summary>
[Output]
public bool HasEmbeddedRootDescriptor { get; set; }
public override bool Execute()
{
ModuleDefinition module = ModuleDefinition.ReadModule (AssemblyPath.ItemSpec);
string assemblyName = module.Assembly.Name.Name;
string expectedResourceName = assemblyName + ".xml";
HasEmbeddedRootDescriptor = false;
foreach (var resource in module.Resources) {
if (resource.Name == expectedResourceName) {
HasEmbeddedRootDescriptor = true;
break;
}
}
return true;
}
}
}

View File

@ -1,117 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
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) {
if (!Utils.IsManagedAssembly (unlinkedFile)) {
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) {
if (!Utils.IsManagedAssembly (linkedFile)) {
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}",
"",
"Before linking (B)",
"After linking (B)",
"Size decrease");
Console.WriteLine ("{0, -60} {1,-20:N0} {2, -20:N0} {3, -10:P}",
"-----------",
"-----------",
"-----------",
"-----------"
);
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 ("{0, -60} {1,-20:N0} {2, -20:N0} {3, -10:P}",
"-----------",
"-----------",
"-----------",
"-----------"
);
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

@ -1,31 +0,0 @@
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{
public class ComputeCrossgenedAssemblies : Task
{
/// <summary>
/// Paths to assemblies.
/// </summary>
[Required]
public ITaskItem[] Assemblies { get; set; }
/// <summary>
/// This will contain the output list of crossgen-ed
/// assemblies. Metadata from the input parameter
/// Assemblies is preserved.
/// </summary>
[Output]
public ITaskItem[] CrossgenedAssemblies { get; set; }
public override bool Execute()
{
CrossgenedAssemblies = Assemblies
.Where(f => Utils.IsCrossgenedAssembly(f.ItemSpec))
.ToArray();
return true;
}
}
}

View File

@ -1,31 +0,0 @@
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
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()
{
ManagedAssemblies = Assemblies
.Where(f => Utils.IsManagedAssembly(f.ItemSpec))
.ToArray();
return true;
}
}
}

View File

@ -1,44 +0,0 @@
using System.IO;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{
public class ComputeRemovedAssemblies : Task
{
/// <summary>
/// The paths to the inputs to the linker.
/// </summary>
[Required]
public ITaskItem[] InputAssemblies { get; set; }
/// <summary>
/// The paths to the linked assemblies.
/// </summary>
[Required]
public ITaskItem[] KeptAssemblies { get; set; }
/// <summary>
/// The set of assemblies in the inputs that weren't kept by
/// the linker. These items include the full metadata from
/// the input assemblies, and only the filenames of the
/// inputs are used to determine which assemblies were
/// removed.
/// </summary>
[Output]
public ITaskItem[] RemovedAssemblies { get; set; }
public override bool Execute()
{
var keptAssemblyNames = new HashSet<string> (
KeptAssemblies.Select(i => Path.GetFileName(i.ItemSpec))
);
RemovedAssemblies = InputAssemblies.Where(i =>
!keptAssemblyNames.Contains(Path.GetFileName(i.ItemSpec))
).ToArray();
return true;
}
}
}

View File

@ -1,48 +0,0 @@
using System.Xml;
using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
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

@ -1,349 +0,0 @@
using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using Microsoft.Build.Utilities; // Task
using Microsoft.Build.Framework; // ITaskItem
namespace ILLink.Tasks
{
public class CreateRuntimeRootILLinkDescriptorFile : Task
{
/// <summary>
/// The path to namespace.h.
/// </summary>
[Required]
public ITaskItem NamespaceFilePath { get; set; }
/// <summary>
/// The path to mscorlib.h.
/// </summary>
[Required]
public ITaskItem MscorlibFilePath { get; set; }
/// <summary>
/// The path to cortypeinfo.h.
/// </summary>
[Required]
public ITaskItem CortypeFilePath { get; set; }
/// <summary>
/// The path to rexcep.h.
/// </summary>
[Required]
public ITaskItem RexcepFilePath { get; set; }
/// <summary>
/// The path to ILLinkTrim.xml.
/// </summary>
[Required]
public ITaskItem ILLinkTrimXmlFilePath { get; set; }
/// <summary>
/// The path to the file to generate.
/// </summary>
[Required]
public ITaskItem RuntimeRootDescriptorFilePath { get; set; }
class ClassMembers
{
public bool keepAllFields;
public HashSet<string> methods;
public HashSet<string> fields;
}
Dictionary<string, string> namespaceDictionary = new Dictionary<string, string> ();
Dictionary<string, string> classIdsToClassNames = new Dictionary<string, string> ();
Dictionary<string, ClassMembers> classNamesToClassMembers = new Dictionary<string, ClassMembers> ();
public override bool Execute ()
{
var namespaceFilePath = NamespaceFilePath.ItemSpec;
if (!File.Exists (namespaceFilePath)) {
Log.LogError ("File " + namespaceFilePath + " doesn't exist.");
return false;
}
var mscorlibFilePath = MscorlibFilePath.ItemSpec;
if (!File.Exists (mscorlibFilePath)) {
Log.LogError ("File " + mscorlibFilePath + " doesn't exist.");
return false;
}
var cortypeFilePath = CortypeFilePath.ItemSpec;
if (!File.Exists (cortypeFilePath)) {
Log.LogError ("File " + cortypeFilePath + " doesn't exist.");
return false;
}
var rexcepFilePath = RexcepFilePath.ItemSpec;
if (!File.Exists (rexcepFilePath)) {
Log.LogError ("File " + rexcepFilePath + " doesn't exist.");
return false;
}
var iLLinkTrimXmlFilePath = ILLinkTrimXmlFilePath.ItemSpec;
if (!File.Exists (iLLinkTrimXmlFilePath)) {
Log.LogError ("File " + iLLinkTrimXmlFilePath + " doesn't exist.");
return false;
}
ProcessNamespaces (namespaceFilePath);
ProcessMscorlib (mscorlibFilePath);
ProcessCoreTypes (cortypeFilePath);
ProcessExceptionTypes (rexcepFilePath);
OutputXml (iLLinkTrimXmlFilePath, RuntimeRootDescriptorFilePath.ItemSpec);
return true;
}
void ProcessNamespaces (string namespaceFile)
{
string [] namespaces = File.ReadAllLines (namespaceFile);
// Process definitions of the form
// #define g_SystemNS "System"
// from namespace.h
foreach (string namespaceDef in namespaces) {
if (namespaceDef.StartsWith ("#define")) {
char [] separators = { '"', ' ' };
string [] namespaceDefElements = namespaceDef.Split (separators, StringSplitOptions.RemoveEmptyEntries);
int startIndex = "g_".Length;
// E.g., if namespaceDefElements [1] is "g_RuntimeNS", lhs is "Runtime".
string lhs = namespaceDefElements [1].Substring (startIndex, namespaceDefElements [1].LastIndexOf ('N') - startIndex);
if (namespaceDefElements.Length == 3) {
// E.G., #define g_SystemNS "System"
// "System" --> "System"
namespaceDictionary [lhs] = namespaceDefElements [2];
}
else {
// E.g., #define g_RuntimeNS g_SystemNS ".Runtime"
// "Runtime" --> "System.Runtime"
string prefix = namespaceDefElements [2].Substring (startIndex, namespaceDefElements [2].LastIndexOf ('N') - startIndex);
namespaceDictionary [lhs] = namespaceDictionary [prefix] + namespaceDefElements [3];
}
}
}
}
void ProcessMscorlib (string typeFile)
{
string [] types = File.ReadAllLines (typeFile);
string classId = null;
foreach (string def in types) {
string [] defElements = null;
if (def.StartsWith ("DEFINE_") || def.StartsWith ("// DEFINE_")) {
char [] separators = { ',', '(', ')', ' ', '/' };
defElements = def.Split (separators, StringSplitOptions.RemoveEmptyEntries);
}
if (def.StartsWith ("DEFINE_CLASS(") || def.StartsWith ("// DEFINE_CLASS(")) {
// E.g., DEFINE_CLASS(APP_DOMAIN, System, AppDomain)
classId = defElements [1]; // APP_DOMAIN
string classNamespace = defElements [2]; // System
string className = defElements [3]; // AppDomain
AddClass (classNamespace, className, classId);
}
else if (def.StartsWith ("DEFINE_CLASS_U(")) {
// E.g., DEFINE_CLASS_U(System, AppDomain, AppDomainBaseObject)
string classNamespace = defElements [1]; // System
string className = defElements [2]; // AppDomain
classId = defElements [3]; // AppDomainBaseObject
// For these classes the sizes of managed and unmanaged classes and field offsets
// are compared so we need to preserve all fields.
const bool keepAllFields = true;
AddClass (classNamespace, className, classId, keepAllFields);
}
else if (def.StartsWith ("DEFINE_FIELD(")) {
// E.g., DEFINE_FIELD(ACCESS_VIOLATION_EXCEPTION, IP, _ip)
classId = defElements [1]; // ACCESS_VIOLATION_EXCEPTION
string fieldName = defElements [3]; // _ip
AddField (fieldName, classId);
}
else if (def.StartsWith ("DEFINE_METHOD(")) {
// E.g., DEFINE_METHOD(APP_DOMAIN, ON_ASSEMBLY_LOAD, OnAssemblyLoadEvent, IM_Assembly_RetVoid)
string methodName = defElements [3]; // OnAssemblyLoadEvent
classId = defElements [1]; // APP_DOMAIN
AddMethod (methodName, classId);
}
else if (def.StartsWith ("DEFINE_PROPERTY(") || def.StartsWith ("DEFINE_STATIC_PROPERTY(")) {
// E.g., DEFINE_PROPERTY(ARRAY, LENGTH, Length, Int)
// or DEFINE_STATIC_PROPERTY(THREAD, CURRENT_THREAD, CurrentThread, Thread)
string propertyName = defElements [3]; // Length or CurrentThread
classId = defElements [1]; // ARRAY or THREAD
AddMethod ("get_" + propertyName, classId);
}
else if (def.StartsWith ("DEFINE_SET_PROPERTY(")) {
// E.g., DEFINE_SET_PROPERTY(THREAD, UI_CULTURE, CurrentUICulture, CultureInfo)
string propertyName = defElements [3]; // CurrentUICulture
classId = defElements [1]; // THREAD
AddMethod ("get_" + propertyName, classId);
AddMethod ("set_" + propertyName, classId);
}
}
}
public void ProcessCoreTypes (string corTypeFile)
{
string [] corTypes = File.ReadAllLines (corTypeFile);
foreach (string def in corTypes) {
// E.g., TYPEINFO(ELEMENT_TYPE_VOID, "System", "Void", 0, TYPE_GC_NONE, false, true, false, false, false) // 0x01
if (def.StartsWith ("TYPEINFO(")) {
char [] separators = { ',', '(', ')', '"', ' ' };
string [] defElements = def.Split (separators, StringSplitOptions.RemoveEmptyEntries);
string classId = null;
string classNamespace = defElements [2]; // System
string className = defElements [3]; // Void
AddClass (classNamespace, className, classId);
}
}
}
public void ProcessExceptionTypes (string excTypeFile)
{
string [] excTypes = File.ReadAllLines (excTypeFile);
foreach (string def in excTypes) {
// E.g., DEFINE_EXCEPTION(g_InteropNS, MarshalDirectiveException, false, COR_E_MARSHALDIRECTIVE)
if (def.StartsWith ("DEFINE_EXCEPTION(")) {
char [] separators = { ',', '(', ')', ' ' };
string [] defElements = def.Split (separators, StringSplitOptions.RemoveEmptyEntries);
string classId = null;
string classNamespace = defElements [1]; // g_InteropNS
string className = defElements [2]; // MarshalDirectiveException
AddClass (classNamespace, className, classId);
AddMethod (".ctor", classId, classNamespace, className);
}
}
}
void OutputXml (string iLLinkTrimXmlFilePath, string outputFileName)
{
XmlDocument doc = new XmlDocument ();
doc.Load (iLLinkTrimXmlFilePath);
XmlNode linkerNode = doc ["linker"];
XmlNode assemblyNode = linkerNode ["assembly"];
foreach (string typeName in classNamesToClassMembers.Keys) {
XmlNode typeNode = doc.CreateElement ("type");
XmlAttribute typeFullName = doc.CreateAttribute ("fullname");
typeFullName.Value = typeName;
typeNode.Attributes.Append (typeFullName);
ClassMembers members = classNamesToClassMembers [typeName];
// We need to keep everyting in System.Runtime.InteropServices.WindowsRuntime and
// System.Threading.Volatile.
if (!typeName.StartsWith ("System.Runtime.InteropServices.WindowsRuntime") &&
!typeName.StartsWith ("System.Threading.Volatile")) {
if (members.keepAllFields) {
XmlAttribute preserve = doc.CreateAttribute ("preserve");
preserve.Value = "fields";
typeNode.Attributes.Append (preserve);
}
else if ((members.fields == null) && (members.methods == null)) {
XmlAttribute preserve = doc.CreateAttribute ("preserve");
preserve.Value = "nothing";
typeNode.Attributes.Append (preserve);
}
if (!members.keepAllFields && (members.fields != null)) {
foreach (string field in members.fields) {
XmlNode fieldNode = doc.CreateElement ("field");
XmlAttribute fieldName = doc.CreateAttribute ("name");
fieldName.Value = field;
fieldNode.Attributes.Append (fieldName);
typeNode.AppendChild (fieldNode);
}
}
if (members.methods != null) {
foreach (string method in members.methods) {
XmlNode methodNode = doc.CreateElement ("method");
XmlAttribute methodName = doc.CreateAttribute ("name");
methodName.Value = method;
methodNode.Attributes.Append (methodName);
typeNode.AppendChild (methodNode);
}
}
}
assemblyNode.AppendChild (typeNode);
}
doc.Save (outputFileName);
}
void AddClass (string classNamespace, string className, string classId, bool keepAllFields = false)
{
string fullClassName = GetFullClassName (classNamespace, className);
if (fullClassName != null) {
if ((classId != null) && (classId != "NoClass")) {
classIdsToClassNames [classId] = fullClassName;
}
ClassMembers members;
if (!classNamesToClassMembers.TryGetValue (fullClassName, out members)) {
members = new ClassMembers ();
classNamesToClassMembers [fullClassName] = members;
}
members.keepAllFields |= keepAllFields;
}
}
void AddField (string fieldName, string classId)
{
string className = classIdsToClassNames [classId];
ClassMembers members = classNamesToClassMembers [className];
if (members.fields == null) {
members.fields = new HashSet<string> ();
}
members.fields.Add (fieldName);
}
void AddMethod (string methodName, string classId, string classNamespace = null, string className = null)
{
string fullClassName;
if (classId != null) {
fullClassName = classIdsToClassNames [classId];
}
else {
fullClassName = GetFullClassName (classNamespace, className);
}
ClassMembers members = classNamesToClassMembers [fullClassName];
if (members.methods == null) {
members.methods = new HashSet<string> ();
}
members.methods.Add (methodName);
}
string GetFullClassName (string classNamespace, string className)
{
string prefixToRemove = "g_";
if (classNamespace.StartsWith (prefixToRemove)) {
classNamespace = classNamespace.Substring (prefixToRemove.Length);
}
string suffixToRemove = "NS";
if (classNamespace.EndsWith (suffixToRemove)) {
classNamespace = classNamespace.Substring (0, classNamespace.Length - suffixToRemove.Length);
}
if ((classNamespace == "NULL") && (className == "NULL")) {
return null;
}
if (!namespaceDictionary.ContainsKey (classNamespace)) {
Log.LogError ("Unknown namespace: " + classNamespace);
}
return namespaceDictionary [classNamespace] + "." + className;
}
}
}

View File

@ -1,46 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{
public class FilterByMetadata : Task
{
/// <summary>
/// Items to filter.
/// </summary>
[Required]
public ITaskItem[] Items { get; set; }
/// <summary>
/// Name of metadata to filter on.
/// </summary>
[Required]
public String MetadataName { get; set; }
/// <summary>
/// The set of metadata values to include.
/// </summary>
[Required]
public ITaskItem[] MetadataValues { get; set; }
/// <summary>
/// Filtered items: the input items for which the
/// specified metadata was one of the allowed
/// values.
/// </summary>
[Output]
public ITaskItem[] FilteredItems { get; set; }
public override bool Execute()
{
var metadataValues = new HashSet<string>(MetadataValues.Select(v => v.ItemSpec));
FilteredItems = Items
.Where(i => metadataValues.Contains(i.GetMetadata(MetadataName)))
.ToArray();
return true;
}
}
}

View File

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{
public class FindDuplicatesByMetadata : Task
{
/// <summary>
/// Items to scan.
/// </summary>
[Required]
public ITaskItem [] Items { get; set; }
/// <summary>
/// Name of metadata to scan for.
/// </summary>
[Required]
public String MetadataName { get; set; }
/// <summary>
/// Duplicate items: the input items for which the
/// specified metadata was shared by multiple input
/// items.
/// </summary>
[Output]
public ITaskItem [] DuplicateItems { get; set; }
/// <summary>
/// Duplicate representatives: includes one input
/// item from each set of duplicates.
/// </summary>
[Output]
public ITaskItem [] DuplicateRepresentatives { get; set; }
public override bool Execute ()
{
var duplicateGroups = Items.GroupBy (i => i.GetMetadata (MetadataName))
.Where (g => g.Count () > 1);
DuplicateItems = duplicateGroups.SelectMany (g => g).ToArray ();
DuplicateRepresentatives = duplicateGroups.Select (g => g.First ()).ToArray ();
return true;
}
}
}

View File

@ -1,91 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{
public class FindNativeDeps : Task
{
/// <summary>
/// The managed assemblies to scan for references to native
/// dependencies.
/// </summary>
[Required]
public ITaskItem [] ManagedAssemblyPaths { get; set; }
/// <summary>
/// The set of native dependencies to keep even if they
/// aren't found to be referenced by a managed assembly.
/// </summary>
public ITaskItem [] NativeDepsToKeep { get; set; }
/// <summary>
/// The paths to the available native dependencies. We
/// expect that all references found point to existing
/// native files.
/// </summary>
[Required]
public ITaskItem [] NativeDepsPaths { get; set; }
/// <summary>
/// The set of native dependencies to keep, including those
/// found in the analysis, and those explicitly marked keep
/// by NativeDepsToKeep. This includes metadata from the
/// input NativeDepsToKeep.
/// </summary>
[Output]
public ITaskItem [] KeptNativeDepsPaths { get; set; }
public override bool Execute ()
{
var allNativeNames = new HashSet<string> ();
foreach (var nativeDep in NativeDepsPaths)
allNativeNames.Add (Path.GetFileName (nativeDep.ItemSpec));
var keptNativeNames = new HashSet<string> ();
foreach (var nativeDep in NativeDepsToKeep)
keptNativeNames.Add (Path.GetFileName (nativeDep.ItemSpec));
var managedAssemblies = ManagedAssemblyPaths.Select (i => i.ItemSpec).ToArray ();
foreach (string managedAssembly in managedAssemblies) {
using (var peReader = new PEReader(new FileStream (managedAssembly, FileMode.Open, FileAccess.Read, FileShare.Read))) {
if (peReader.HasMetadata) {
var reader = peReader.GetMetadataReader ();
for (int i = 1, count = reader.GetTableRowCount (TableIndex.ModuleRef); i <= count; i++) {
var moduleRef = reader.GetModuleReference (MetadataTokens.ModuleReferenceHandle (i));
var moduleName = reader.GetString (moduleRef.Name);
var moduleRefCandidates = new [] { moduleName, moduleName + ".dll", moduleName + ".so", moduleName + ".dylib" };
bool foundModuleRef = false;
foreach (string moduleRefCandidate in moduleRefCandidates) {
if (allNativeNames.Contains (moduleRefCandidate)) {
keptNativeNames.Add (moduleRefCandidate);
foundModuleRef = true;
}
}
if (!foundModuleRef)
Log.LogMessage("unsatisfied DLLImport: " + managedAssembly + " -> " + moduleName);
}
}
}
}
var keptNativeDeps = new List<ITaskItem> ();
foreach (var nativeDep in NativeDepsPaths) {
var fileName = Path.GetFileName (nativeDep.ItemSpec);
if (keptNativeNames.Contains (fileName))
keptNativeDeps.Add (nativeDep);
}
KeptNativeDepsPaths = keptNativeDeps.ToArray ();
return true;
}
}
}

View File

@ -1,84 +0,0 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.NET.Build.Tasks; // LockFileCache
using NuGet.Frameworks; // NuGetFramework.Parse(targetframework)
using NuGet.ProjectModel; // LockFileTargetLibrary
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;
}
}
}

View File

@ -1,229 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CrossGenDuringPublish Condition=" '$(CrossGenDuringPublish)' == '' And '$(RuntimeIdentifier)' != '' And '$(LinkDuringPublish)' == 'true' ">true</CrossGenDuringPublish>
</PropertyGroup>
<PropertyGroup>
<IntermediateOptimizedDirName Condition=" '$(IntermediateOptimizedDirName)' == '' ">optimized</IntermediateOptimizedDirName>
<IntermediateOptimizedDir Condition=" '$(IntermediateOptimizedDir)' == '' ">$(IntermediateOutputPath)$(IntermediateOptimizedDirName)</IntermediateOptimizedDir>
<IntermediateCrossGenDirName Condition=" '$(IntermediateCrossGenDirName)' == '' ">crossgen</IntermediateCrossGenDirName>
<IntermediateCrossGenDir Condition=" '$(IntermediateCrossGenDir)' == '' ">$(IntermediateOutputPath)$(IntermediateCrossGenDirName)</IntermediateCrossGenDir>
</PropertyGroup>
<PropertyGroup>
<ComputeCrossGenFilesToPublishAfter Condition=" '$(LinkDuringPublish)' == 'true' ">ComputeLinkedFilesToPublish</ComputeCrossGenFilesToPublishAfter>
<ComputeCrossGenFilesToPublishBefore Condition=" '$(LinkDuringPublish)' != 'true' ">ComputeFilesToPublish</ComputeCrossGenFilesToPublishBefore>
</PropertyGroup>
<!-- Rewrite inputs to ComputeFilesToPublish, so that crossgen'd
files get published instead of the pre-crossgen assemblies. -->
<Target Name="ComputeCrossGenFilesToPublish"
BeforeTargets="$(ComputeCrossGenFilesToPublishBefore)"
AfterTargets="$(ComputeCrossGenFilesToPublishAfter)"
Condition=" '$(CrossGenDuringPublish)' == 'true' "
DependsOnTargets="_CrossGenForPublish">
<!-- Rewrite ResolvedAssembliesToPublish, preserving metadata. -->
<ItemGroup>
<_CrossGenResolvedAssembliesToPublishCandidates Include="@(ResolvedAssembliesToPublish->'$(IntermediateOptimizedDir)/%(Filename)%(Extension)')" />
<_CrossGenResolvedAssembliesToPublish Include="@(_CrossGenResolvedAssembliesToPublishCandidates)" Condition="Exists('%(Identity)')" />
<ResolvedAssembliesToPublish Remove="@(FilesToCrossGen)" />
<ResolvedAssembliesToPublish Include="@(_CrossGenResolvedAssembliesToPublish)" />
</ItemGroup>
<!-- Rewrite IntermediateAssembly, preserving metadata. -->
<ItemGroup>
<_CrossGenIntermediateAssemblyCandidates Include="@(IntermediateAssembly->'$(IntermediateOptimizedDir)/%(Filename)%(Extension)')" />
<_CrossGenIntermediateAssembly Include="@(_CrossGenIntermediateAssemblyCandidates)" Condition="Exists('%(Identity)')" />
<IntermediateAssembly Remove="@(FilesToCrossGen)" />
<IntermediateAssembly Include="@(_CrossGenIntermediateAssembly)" />
</ItemGroup>
</Target>
<!-- The target that runs crossgen on all input assemblies. We could
probably also reuse _RunCrossgen, but this gets its inputs from
ResolvedFileToPublish, so we would need to run crossgen after
ComputeFilesToPublish. -->
<Target Name="_CrossGenForPublish"
DependsOnTargets="PrepOptimizer;_ComputeCrossGenInputs">
<MakeDir Directories="$(IntermediateOptimizedDir)" />
<PropertyGroup>
<_CrossGenPlatformAssemblies>@(_CrossGenPlatformAssemblies)</_CrossGenPlatformAssemblies>
</PropertyGroup>
<ItemGroup>
<CrossGenInvocations Include="$(MSBuildProjectFullPath)">
<Properties>
CrossGenExe=$(Crossgen);
CrossGenInput=%(FilesToCrossGen.FullPath);
CrossGenOutput=$(IntermediateOptimizedDir)/%(Filename)%(Extension);
CrossGenPlatformAssemblies=$(_CrossGenPlatformAssemblies)
</Properties>
</CrossGenInvocations>
</ItemGroup>
<MSBuild Projects="@(CrossGenInvocations)"
Targets="RunCrossGenForPublish" />
</Target>
<!-- Workarounds for SDK issues around the interdependency between
ComposeStore targets and CrossGen targets. These let us reuse
PrepOptimizer from the SDK to obtain a crossgen executable for
the target RID. -->
<!-- _RestoreCrossgen (a dependency of PrepOptimizer) requires _TFM
to be set, but it is only set in an unrelated target called
during ComposeStore (PrepareForComposeStore). -->
<Target Name="_SetTFMForCrossGenRestore"
BeforeTargets="_RestoreCrossgen"
Condition=" '$(CrossGenDuringPublish)' == 'true' ">
<PropertyGroup>
<_TFM Condition=" '$(_TFM)' == '' ">$(TargetFramework)</_TFM>
</PropertyGroup>
</Target>
<!-- _RestoreCrossgen also requires _CrossProjAssetsFile to be
set. This path is computed from ComposeWorkingDir in the target
_GetCrossgenProps, but ComposeWorkingDir is set only in
store-related targets. We hook into _GetCrossgenProps to
specify where to restore crossgen. -->
<Target Name="_SetComposeWorkingDirForCrossGenRestore"
AfterTargets="_GetCrossgenProps"
Condition=" '$(CrossGenDuringPublish)' == 'true' ">
<PropertyGroup>
<_CrossProjFileDir>$([System.IO.Path]::GetFullPath($(IntermediateCrossGenDir)))</_CrossProjFileDir>
<_NetCoreRefDir>$([System.IO.Path]::Combine($(_CrossProjFileDir), "netcoreapp"))</_NetCoreRefDir>
<_CrossProjAssetsFile>$([System.IO.Path]::Combine($(_CrossProjFileDir), project.assets.json))</_CrossProjAssetsFile>
</PropertyGroup>
<MakeDir Directories="$(_CrossProjFileDir)" />
</Target>
<!-- PrepforRestoreForComposeStore (a dependency of
_RestoreCrossgen) sets BaseIntermediateOutputPath and
ProjectAssetsFile to the compose working directory. We don't
want this because we are not composing a package store, so we
save and restore these properties. -->
<Target Name="_SavePropsModifiedByPrepforRestoreForComposeStore"
BeforeTargets="PrepforRestoreForComposeStore"
Condition=" '$(CrossGenDuringPublish)' == 'true' ">
<PropertyGroup>
<_SavedBaseIntermediateOutputPath>$(BaseIntermediateOutputPath)</_SavedBaseIntermediateOutputPath>
<_SavedProjectAssetsFile>$(ProjectAssetsFile)</_SavedProjectAssetsFile>
</PropertyGroup>
</Target>
<Target Name="_RestorePropsModifiedByPrepforRestoreForComposeStore"
AfterTargets="PrepforRestoreForComposeStore">
<PropertyGroup>
<BaseIntermediateOutputPath>$(_SavedBaseIntermediateOutputPath)</BaseIntermediateOutputPath>
<ProjectAssetsFile>$(_SavedProjectAssetsFile)</ProjectAssetsFile>
</PropertyGroup>
</Target>
<!-- Run crossgen on a single input assembly. -->
<Target Name="RunCrossGenForPublish"
Inputs="$(CrossGenInput);$(CrossGenPlatformAssemblies)"
Outputs="$(CrossGenOutput)">
<!-- The property CrossGenPlatformAssemblies must be
semicolon-delimited for incremental build to work correctly,
but the directory paths have to be passed with
platform-specific path separators in the crossgen command.
-->
<ItemGroup>
<_CrossGenPlatformAssemblies Include="$(CrossGenPlatformAssemblies)" />
<__CrossGenPlatformAssembliesPaths Include="@(_CrossGenPlatformAssemblies->'%(RootDir)%(Directory)')" />
<_CrossGenPlatformAssembliesPaths Include="@(__CrossGenPlatformAssembliesPaths->Distinct())" />
</ItemGroup>
<PropertyGroup>
<_PathSeparator>$([System.IO.Path]::PathSeparator)</_PathSeparator>
<_CrossGenPlatformAssembliesPaths>@(_CrossGenPlatformAssembliesPaths, '$(_PathSeparator)')</_CrossGenPlatformAssembliesPaths>
</PropertyGroup>
<PropertyGroup>
<CrossGenCommand>$(CrossGenExe) -readytorun -in $(CrossGenInput) -out $(CrossGenOutput) -platform_assemblies_paths $(_CrossGenPlatformAssembliesPaths)</CrossGenCommand>
</PropertyGroup>
<Message Text="$(CrossGenCommand)" />
<Exec Command="$(CrossGenCommand)" />
</Target>
<Target Name="_ComputeCrossGenInputs"
DependsOnTargets="_ComputeCrossGenPlatformAssemblies;_ComputeFilesToCrossGen" />
<!-- Compute the platform assembly paths, a parameter to crossgen
that lets it find dependencies of the input file. This needs to
include the path to the input file and its dependency closure,
including System.Private.CoreLib. -->
<Target Name="_ComputeCrossGenPlatformAssemblies"
DependsOnTargets="_ComputeManagedResolvedAssembliesForCrossGen">
<ItemGroup>
<_CrossGenPlatformAssemblies Include="@(_ManagedResolvedAssembliesForCrossGen)" />
<_CrossGenPlatformAssemblies Include="@(IntermediateAssembly)" />
</ItemGroup>
</Target>
<!-- _ManagedResolvedAssembliesForCrossGen includes the app's
managed dependency closure, including System.Private.CoreLib,
but not the app itself or resource assemblies. -->
<Target Name="_ComputeManagedResolvedAssembliesForCrossGen">
<ComputeManagedAssemblies Assemblies="@(ResolvedAssembliesToPublish)">
<Output TaskParameter="ManagedAssemblies" ItemName="_ManagedResolvedAssembliesForCrossGen" />
</ComputeManagedAssemblies>
<ItemGroup>
<_ManagedResolvedAssembliesForCrossGen Remove="@(_ManagedResolvedAssembliesForCrossGen->WithMetadataValue('AssetType', 'resources'))" />
</ItemGroup>
</Target>
<UsingTask TaskName="FilterByMetadata" AssemblyFile="$(LinkTaskDllPath)" />
<!-- This computes the default set of files that we want to be
crossgen'd. Some of these may already be crossgen images, and
these will not be crossgen'd again. The default is to crossgen
the app and platform libraries. Defaults will be used only if
FilesToCrossGen hasn't been set elsewhere, allowing users and
other props/targets to select what will be crossgen'd. -->
<Target Name="_ComputeDefaultFilesToCrossGen"
DependsOnTargets="_ComputeManagedResolvedAssembliesForCrossGen;_ComputePlatformLibraries"
Condition=" '@(FilesToCrossGen->Count())' == '0' ">
<FilterByMetadata Items="@(_ManagedResolvedAssembliesForCrossGen)"
MetadataName="Filename"
MetadataValues="@(PlatformLibraries->'%(Filename)')">
<Output TaskParameter="FilteredItems" ItemName="_PlatformLibrariesForCrossGen" />
</FilterByMetadata>
<ItemGroup>
<FilesToCrossGen Include="@(IntermediateAssembly)" />
<FilesToCrossGen Include="@(_PlatformLibrariesForCrossGen)" />
</ItemGroup>
</Target>
<UsingTask TaskName="ComputeCrossgenedAssemblies" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_ComputeFilesToCrossGen"
DependsOnTargets="_ComputeDefaultFilesToCrossGen">
<ComputeCrossgenedAssemblies Assemblies="@(FilesToCrossGen)">
<Output TaskParameter="CrossgenedAssemblies" ItemName="_CrossgenedFiles" />
</ComputeCrossgenedAssemblies>
<!-- Don't try to run crossgen on assemblies that are already
crossgen'd. -->
<ItemGroup>
<FilesToCrossGen Remove="@(_CrossgenedFiles)" />
</ItemGroup>
<Message Text="files to crossgen: @(FilesToCrossGen)" />
</Target>
</Project>

View File

@ -1,225 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>0.1.5-preview</VersionPrefix>
<TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<BaseOutputPath>../bin/</BaseOutputPath>
<PackageOutputPath>$(BaseOutputPath)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 consume 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. -->
<NuspecFileName>ILLink.Tasks.nuspec</NuspecFileName>
<NuspecFile>$(BaseOutputPath)$(NuspecFileName)</NuspecFile>
<NuspecProperties>id=$(AssemblyName);authors=$(AssemblyName);description=linker tasks;</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>SetDynamicNuspecProperties;BinPlacePackageDeps;$(GenerateNuspecDependsOn)</GenerateNuspecDependsOn>
</PropertyGroup>
<Target Name="SetDynamicNuspecProperties"
DependsOnTargets="LayoutPackage">
<PropertyGroup>
<NuspecProperties>$(NuspecProperties)version=$(Version);</NuspecProperties>
</PropertyGroup>
</Target>
<!-- This target is necessary because the .nuspec includes the full
path of the selected dlls in the package layout. We want the
assets to be included in the package without the bin prefix, so
we place the .nuspec and the included targets alongside the
publish directories in the bin directory. -->
<Target Name="BinPlacePackageDeps">
<Copy SourceFiles="$(NuspecFileName)" DestinationFolder="$(BaseOutputPath)" />
<Copy SourceFiles="ILLink.Tasks.targets" DestinationFolder="$(BaseOutputPath)" />
<Copy SourceFiles="ILLink.CrossGen.targets" DestinationFolder="$(BaseOutputPath)" />
</Target>
<Target Name="LayoutPackage">
<ItemGroup>
<TFMsToPublish Include="$(TargetFrameworks)" />
<ProjectsToPublish Include="$(MSBuildProjectFile)">
<AdditionalProperties>TargetFramework=%(TFMsToPublish.Identity);PublishDir=$(BaseOutputPath)%(TFMsToPublish.Identity)</AdditionalProperties>
</ProjectsToPublish>
</ItemGroup>
<MSBuild Projects="@(ProjectsToPublish)" Targets="Publish" />
</Target>
<ItemGroup>
<Compile Include="AdapterLogger.cs" />
<Compile Include="LinkTask.cs" />
<Compile Include="CompareSizes.cs" />
<Compile Include="ComputeManagedAssemblies.cs" />
<Compile Include="ComputeCrossgenedAssemblies.cs" />
<Compile Include="GetRuntimeLibraries.cs" />
<Compile Include="CreateRootDescriptorFile.cs" />
<Compile Include="CreateRuntimeRootDescriptorFile.cs" />
<Compile Include="FilterByMetadata.cs" />
<Compile Include="FindDuplicatesByMetadata.cs" />
<Compile Include="Utils.cs" />
<Compile Include="Microsoft.NET.Build.Tasks/LockFileCache.cs" />
<Compile Include="Microsoft.NET.Build.Tasks/BuildErrorException.cs" />
<Compile Include="FindNativeDeps.cs" />
<Compile Include="ComputeRemovedAssemblies.cs" />
<Compile Include="CheckEmbeddedRootDescriptor.cs" />
<Compile Include="SetAssemblyActions.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. Setting it here allows packing
the tasks csproj on its own. This lets 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=illink_$(Configuration)</SetConfiguration>
</ProjectReference>
<ProjectReference Include="../../../cecil/Mono.Cecil.csproj" />
<ProjectReference Include="../ILLink.CustomSteps/ILLink.CustomSteps.csproj">
<SetConfiguration>Configuration=illink_$(Configuration)</SetConfiguration>
</ProjectReference>
</ItemGroup>
<!-- Workaround for the SetConfiguration issue described above. -->
<Target Name="SetCecilConfiguration"
AfterTargets="AssignProjectConfiguration">
<ItemGroup>
<ProjectReferenceWithConfiguration Condition=" '%(Filename)%(Extension)' == 'Mono.Cecil.csproj' Or '%(Filename)%(Extension)' == 'Mono.Cecil.Pdb.csproj' Or '%(Filename)%(Extension)' == 'Mono.Cecil.Mdb.csproj' ">
<SetConfiguration Condition=" '$(TargetFramework)' == 'net46' ">Configuration=net_4_0_$(Configuration)</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">Configuration=netstandard_$(Configuration)</SetConfiguration>
</ProjectReferenceWithConfiguration>
</ItemGroup>
</Target>
<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. -->
<!-- We use private assets for the Microsoft.Build packages to
prevent them from being published with the tasks dll, because
these are already a part of the SDK. -->
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.1012"
PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.1.1012"
PrivateAssets="All" />
<PackageReference Include="NuGet.ProjectModel" Version="4.3.0-preview1-2500" />
<PackageReference Include="System.Reflection.Metadata" Version="1.3.0"
PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@ -1,15 +0,0 @@
<?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="ILLink.CrossGen.targets" target="build" />
<file src="netcoreapp2.0/**/*.dll" target="tools" />
<file src="net46/**/*.dll" target="tools" />
</files>
</package>

File diff suppressed because it is too large Load Diff

View File

@ -1,144 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
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.
/// Each path can also have an "action" metadata,
/// which will set the illink action to take for
/// that assembly.
/// </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>
/// Boolean specifying whether to clear initlocals flag on methods.
/// </summary>
public bool ClearInitLocals { get; set; }
/// <summary>
/// A comma-separated list of assemblies whose methods
/// should have initlocals flag cleared if ClearInitLocals is true.
/// </summary>
public string ClearInitLocalsAssemblies { get; set; }
/// <summary>
/// Extra arguments to pass to illink, delimited by spaces.
/// </summary>
public string ExtraArgs { get; set; }
/// <summary>
/// Make illink dump dependencies file for linker analyzer tool.
/// </summary>
public bool DumpDependencies { get; set; }
public override bool Execute ()
{
string [] args = GenerateCommandLineCommands ();
var argsString = String.Join (" ", args);
Log.LogMessageFromText ($"illink {argsString}", MessageImportance.Normal);
var logger = new AdapterLogger (Log);
int ret = Mono.Linker.Driver.Execute (args, logger);
return ret == 0;
}
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);
}
HashSet<string> directories = new HashSet<string> ();
foreach (var assembly in AssemblyPaths) {
var assemblyPath = assembly.ItemSpec;
var dir = Path.GetDirectoryName (assemblyPath);
if (!directories.Contains (dir)) {
directories.Add (dir);
args.Add ("-d");
args.Add (dir);
}
string action = assembly.GetMetadata ("action");
if ((action != null) && (action.Length > 0)) {
args.Add ("-p");
args.Add (action);
args.Add (Path.GetFileNameWithoutExtension (assemblyPath));
}
}
if (OutputDirectory != null) {
args.Add ("-out");
args.Add (OutputDirectory.ItemSpec);
}
if (ClearInitLocals) {
args.Add ("-s");
// Version of ILLink.CustomSteps is passed as a workaround for msbuild issue #3016
args.Add ("ILLink.CustomSteps.ClearInitLocalsStep,ILLink.CustomSteps,Version=0.0.0.0:OutputStep");
if ((ClearInitLocalsAssemblies != null) && (ClearInitLocalsAssemblies.Length > 0)) {
args.Add ("-m");
args.Add ("ClearInitLocalsAssemblies");
args.Add (ClearInitLocalsAssemblies);
}
}
if (ExtraArgs != null) {
args.AddRange (ExtraArgs.Split (' '));
}
if (DumpDependencies)
args.Add ("--dump-dependencies");
return args.ToArray ();
}
}
}

View File

@ -1,33 +0,0 @@
// 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))
{
}
}
}

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