Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@@ -11,6 +11,7 @@ param
)
$rootCliVersion = Join-Path $RepositoryRoot ".cliversion"
$globalJson = Join-Path $RepositoryRoot "global.json"
$bootstrapComplete = Join-Path $ToolsLocalPath "bootstrap.complete"
# if the force switch is specified delete the semaphore file if it exists
@@ -59,6 +60,8 @@ if ($LastExitCode -ne 0)
exit $LastExitCode
}
"{ `"sdk`": { `"version`": `"$dotNetCliVersion`" } }" | Out-File -Encoding utf8 -FilePath $globalJson
# write semaphore file
copy $rootCliVersion $bootstrapComplete
exit 0

View File

@@ -150,6 +150,7 @@ fi
rootCliVersion="$repoRoot/.cliversion"
globalJson="$repoRoot/global.json"
bootstrapComplete="$toolsLocalPath/bootstrap.complete"
# if the force switch is specified delete the semaphore file if it exists
@@ -195,6 +196,8 @@ if [ $forcedCliLocalPath = "<none>" ]; then
say_err "The .NET CLI installation failed with exit code $?"
exit $?
fi
echo "{ \"sdk\": { \"version\": \"$dotNetCliVersion\" } }" > $globalJson
fi
cp $rootCliVersion $bootstrapComplete

View File

@@ -1,5 +0,0 @@
{
"sdk": {
"version": "2.0.0"
}
}

View File

@@ -0,0 +1,37 @@
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,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using Microsoft.Build.Utilities;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{

View File

@@ -1,16 +1,6 @@
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)
using Mono.Cecil;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{
@@ -32,14 +22,9 @@ namespace ILLink.Tasks
public override bool Execute()
{
var managedAssemblies = new List<ITaskItem>();
foreach (var f in Assemblies) {
if (Utils.IsManagedAssembly(f.ItemSpec)) {
managedAssemblies.Add(f);
}
}
ManagedAssemblies = managedAssemblies.ToArray();
ManagedAssemblies = Assemblies
.Where(f => Utils.IsManagedAssembly(f.ItemSpec))
.ToArray();
return true;
}
}

View File

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

View File

@@ -1,9 +1,8 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{

View File

@@ -1,15 +1,7 @@
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)
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{

View File

@@ -0,0 +1,326 @@
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 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;
}
ProcessNamespaces (namespaceFilePath);
ProcessMscorlib (mscorlibFilePath);
ProcessCoreTypes (cortypeFilePath);
ProcessExceptionTypes (rexcepFilePath);
OutputXml (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);
}
}
}
void OutputXml (string outputFileName)
{
XmlDocument doc = new XmlDocument ();
XmlNode linkerNode = doc.CreateElement ("linker");
doc.AppendChild (linkerNode);
XmlNode assemblyNode = doc.CreateElement ("assembly");
XmlAttribute assemblyFullName = doc.CreateAttribute ("fullname");
assemblyFullName.Value = "System.Private.CoreLib";
assemblyNode.Attributes.Append (assemblyFullName);
linkerNode.AppendChild (assemblyNode);
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 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);
}
string fullClassName = null;
if ((classNamespace != "NULL") && (className != "NULL")) {
if (!namespaceDictionary.ContainsKey (classNamespace)) {
Log.LogError ("Unknown namespace: " + classNamespace);
}
fullClassName = namespaceDictionary [classNamespace] + "." + className;
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 className = classIdsToClassNames [classId];
ClassMembers members = classNamesToClassMembers [className];
if (members.methods == null) {
members.methods = new HashSet<string> ();
}
members.methods.Add (methodName);
}
}
}

View File

@@ -0,0 +1,46 @@
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,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using System.Reflection.PortableExecutable;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{

View File

@@ -1,175 +0,0 @@
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

@@ -1,15 +1,12 @@
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.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.NET.Build.Tasks; // LockFileCache
using NuGet.ProjectModel; // LockFileTargetLibrary
using NuGet.Frameworks; // NuGetFramework.Parse(targetframework)
using NuGet.ProjectModel; // LockFileTargetLibrary
namespace ILLink.Tasks
{

View File

@@ -0,0 +1,231 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CrossGenDuringPublish Condition=" '$(CrossGenDuringPublish)' == '' And '$(RuntimeIdentifier)' != '' ">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)')" />
<!-- FilesToCrossGen doesn't contain System.Private.CoreLib, so
it will still be published. -->
<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 R2R 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>
<Error Text="System.Private.CoreLib should already be crossgen compiled."
Condition=" '%(FilesToCrossGen.Filename)' == 'System.Private.CoreLib' " />
</Target>
<UsingTask TaskName="ComputeReadyToRunAssemblies" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_ComputeFilesToCrossGen"
DependsOnTargets="_ComputeDefaultFilesToCrossGen">
<ComputeReadyToRunAssemblies Assemblies="@(FilesToCrossGen)">
<Output TaskParameter="ReadyToRunAssemblies" ItemName="_ReadyToRunFiles" />
</ComputeReadyToRunAssemblies>
<!-- Don't try to run crossgen on assemblies that are already R2R. -->
<ItemGroup>
<FilesToCrossGen Remove="@(_ReadyToRunFiles)" />
</ItemGroup>
<Message Text="files to crossgen: @(FilesToCrossGen)" />
</Target>
</Project>

View File

@@ -83,6 +83,7 @@
<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">
@@ -99,13 +100,18 @@
<Compile Include="LinkTask.cs" />
<Compile Include="CompareSizes.cs" />
<Compile Include="ComputeManagedAssemblies.cs" />
<Compile Include="ComputeReadyToRunAssemblies.cs" />
<Compile Include="GetRuntimeLibraries.cs" />
<Compile Include="CreateRootDescriptorFile.cs" />
<Compile Include="CreateRuntimeRootDescriptorFile.cs" />
<Compile Include="FilterByMetadata.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
@@ -190,8 +196,8 @@
AfterTargets="AssignProjectConfiguration">
<ItemGroup>
<ProjectReferenceWithConfiguration Condition=" '%(Filename)%(Extension)' == 'Mono.Cecil.csproj' Or '%(Filename)%(Extension)' == 'Mono.Cecil.Pdb.csproj' ">
<SetConfiguration Condition=" '$(TargetFramework)' == 'net46' ">Configuration=net_4_0_$(Configuration)</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">Configuration=netstandard_$(Configuration)</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'net46' ">Configuration=net_4_0_$(Configuration)</SetConfiguration>
<SetConfiguration Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">Configuration=netstandard_$(Configuration)</SetConfiguration>
</ProjectReferenceWithConfiguration>
</ItemGroup>
</Target>

View File

@@ -8,6 +8,7 @@
</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>

View File

@@ -15,8 +15,19 @@
<LinkDuringPublish Condition=" '$(LinkDuringPublish)' == '' ">true</LinkDuringPublish>
<LinkDuringPublish Condition=" '$(LinkDuringPublish)' != 'true' ">false</LinkDuringPublish>
<ShowLinkerSizeComparison Condition=" '$(ShowLinkerSizeComparison)' == '' ">false</ShowLinkerSizeComparison>
<LinkerDumpDependencies Condition=" '$(LinkerDumpDependencies)' == '' ">false</LinkerDumpDependencies>
<UsedApplicationAssemblyAction Condition=" '$(UsedApplicationAssemblyAction)' == '' ">Copy</UsedApplicationAssemblyAction>
<UnusedApplicationAssemblyAction Condition=" '$(UnusedApplicationAssemblyAction)' == '' ">Delete</UnusedApplicationAssemblyAction>
<UsedPlatformAssemblyAction Condition=" '$(UsedPlatformAssemblyAction)' == '' ">Link</UsedPlatformAssemblyAction>
<UnusedPlatformAssemblyAction Condition=" '$(UnusedPlatformAssemblyAction)' == '' ">Delete</UnusedPlatformAssemblyAction>
<RootAllApplicationAssemblies Condition=" '$(RootAllApplicationAssemblies)' == '' ">true</RootAllApplicationAssemblies>
<RootAllApplicationAssemblies Condition=" '$(RootAllApplicationAssemblies)' != 'true' ">false</RootAllApplicationAssemblies>
</PropertyGroup>
<!-- This depends on LinkDuringPublish, so it needs to be imported
after the property is set. -->
<Import Project="$(MSBuildThisFileDirectory)ILLink.CrossGen.targets" />
<ItemGroup>
<!-- LinkerRootDescriptors (the ItemGroup) is set to contain
LinkerRootDescriptors (the Property), which allows adding
@@ -100,6 +111,31 @@
</ItemGroup>
</Target>
<!-- The SDK has a target called ComputeRefAssembliesToPublish that
runs after ComputeFilesToPublish and rewrites
ResolvedFileToPublish to include any reference assemblies that
aren't in ResolvedAssembliesToPublish. Because
ComputeLinkedFilesToPublish changes ResolvedAssembliesToPublish
(replacing the original assemblies with linked assemblies),
this would change the behavior of
ComputeRefAssembliesToPublish, resulting in extra assemblies
being placed in the refs directory of the output. To prevent
this, we save ResolvedAssembliesToPublish before linking, and
restore it to its pre-link state before
ComputeRefAssembliesToPublish. -->
<Target Name="SaveResolvedAssembliesToPublish"
BeforeTargets="ComputeLinkedFilesToPublish">
<ItemGroup>
<PreLinkResolvedAssembliesToPublish Include="@(ResolvedAssembliesToPublish)" />
</ItemGroup>
</Target>
<Target Name="RestoreResolvedAssembliesToPublish"
BeforeTargets="ComputeRefAssembliesToPublish">
<ItemGroup>
<ResolvedAssembliesToPublish Remove="@(ResolvedAssembliesToPublish)" />
<ResolvedAssembliesToPublish Include="@(PreLinkResolvedAssembliesToPublish)" />
</ItemGroup>
</Target>
<!-- Print out a size comparison report for the linked
assemblies. This is disabled by default, but can be turned on
@@ -140,14 +176,41 @@
Condition="Exists('%(Identity)') And '$(_DebugSymbolsProduced)' == 'true' " />
</ItemGroup>
</Target>
<UsingTask TaskName="SetAssemblyActions" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_SetAssemblyActions"
DependsOnTargets="_ComputeManagedAssembliesToLink;_ComputePlatformLibraries">
<ItemGroup>
<_PlatformAssembliesToLink Include="@(PlatformLibraries->'%(Filename)')" />
<_PlatformAssembliesToLink Include="System.Private.CoreLib" />
<_ApplicationAssembliesToLink Include="@(_ManagedAssembliesToLink->'%(Filename)')" />
<_ApplicationAssembliesToLink Remove="@(_PlatformAssembliesToLink)" />
</ItemGroup>
<SetAssemblyActions AssemblyPaths="@(_ManagedAssembliesToLink)"
ApplicationAssemblyNames="@(_ApplicationAssembliesToLink)"
PlatformAssemblyNames="@(_PlatformAssembliesToLink)"
UsedApplicationAssemblyAction="$(UsedApplicationAssemblyAction)"
UnusedApplicationAssemblyAction="$(UnusedApplicationAssemblyAction)"
UsedPlatformAssemblyAction="$(UsedPlatformAssemblyAction)"
UnusedPlatformAssemblyAction="$(UnusedPlatformAssemblyAction)">
<Output TaskParameter="AssemblyPathsWithActions" ItemName="_ManagedAssembliesToLinkWithActions" />
</SetAssemblyActions>
<ItemGroup>
<_ManagedAssembliesToLink Remove="@(_ManagedAssembliesToLink)" />
<_ManagedAssembliesToLink Include="@(_ManagedAssembliesToLinkWithActions)" />
</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"
DependsOnTargets="_ComputeManagedAssembliesToLink;_ComputeLinkerRootAssemblies;_ComputeLinkerRootDescriptors;_SetAssemblyActions"
Inputs="@(_ManagedAssembliesToLink);@(LinkerRootDescriptors);$(MSBuildAllProjects)"
Outputs="$(_LinkSemaphore)">
<!-- These extra arguments have been hard-coded for now, as this
@@ -155,12 +218,13 @@
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 -b true</ExtraLinkerArgs>
<ExtraLinkerArgs Condition=" '$(ExtraLinkerArgs)' == '' ">-t -l none -b true</ExtraLinkerArgs>
</PropertyGroup>
<ILLink AssemblyPaths="@(_ManagedAssembliesToLink)"
RootAssemblyNames="@(LinkerRootAssemblies)"
RootDescriptorFiles="@(LinkerRootDescriptors)"
OutputDirectory="$(IntermediateLinkDir)"
DumpDependencies="$(LinkerDumpDependencies)"
ExtraArgs="$(ExtraLinkerArgs)" />
<Touch Files="$(_LinkSemaphore)" AlwaysCreate="true">
@@ -199,7 +263,6 @@
</Target>
<!-- Computes the managed assemblies that are input to the
linker. Includes managed assemblies from
ResolvedAssembliesToPublish, and IntermediateAssembly. -->
@@ -266,20 +329,37 @@
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>
DependsOnTargets="_ComputeManagedResolvedAssembliesToPublish;_ComputePlatformLibraries;_CheckSystemPrivateCorelibEmbeddedRoots">
<!-- If RootAllApplicationAssemblies is true, roots are everything minus the framework
assemblies. This doesn't include the intermediate assembly,
because we root it separately using an xml file,
which lets us explicitly root everything.
If RootAllApplicationAssemblies is false, only intermediate assembly's Main method is rooted.
System.Private.CoreLib is rooted unless it has an embedded
xml descriptor file. -->
<ItemGroup Condition=" '$(RootAllApplicationAssemblies)' == 'true' ">
<_LinkerRootAssemblies Include="@(_ManagedResolvedAssembliesToPublish->'%(Filename)')" />
<_LinkerRootAssemblies Remove="@(PlatformLibraries->'%(Filename)')" />
<_LinkerRootAssemblies Include="System.Private.CoreLib" />
<_LinkerRootAssemblies Remove="System.Private.CoreLib" Condition=" '$(_SPCHasEmbeddedRootDescriptor)' == 'true' "/>
<LinkerRootAssemblies Include="@(_LinkerRootAssemblies)" />
</ItemGroup>
<ItemGroup Condition=" '$(RootAllApplicationAssemblies)' == 'false' ">
<LinkerRootAssemblies Include="@(IntermediateAssembly)" />
<LinkerRootAssemblies Include="System.Private.CoreLib" Condition=" '$(_SPCHasEmbeddedRootDescriptor)' == 'false' "/>
</ItemGroup>
</Target>
<UsingTask TaskName="CheckEmbeddedRootDescriptor" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_CheckSystemPrivateCorelibEmbeddedRoots"
DependsOnTargets="_ComputeManagedAssembliesToLink">
<CheckEmbeddedRootDescriptor AssemblyPath="@(_ManagedAssembliesToLink->WithMetadataValue('Filename', 'System.Private.CoreLib'))">
<Output TaskParameter="HasEmbeddedRootDescriptor" PropertyName="_SPCHasEmbeddedRootDescriptor" />
</CheckEmbeddedRootDescriptor>
</Target>
<!-- Platform libraries are the managed runtime assets needed by the
"platform", currently Microsoft.NETCore.App. -->
@@ -300,7 +380,8 @@
dynamically include the generated descriptor files for the
intermediate assembly. -->
<Target Name="_ComputeLinkerRootDescriptors"
DependsOnTargets="_GenerateIntermediateRootDescriptor">
DependsOnTargets="_GenerateIntermediateRootDescriptor"
Condition=" '$(RootAllApplicationAssemblies)' == 'true' ">
<ItemGroup>
<LinkerRootDescriptors Include="$(_IntermediateRootDescriptorPath)" />
</ItemGroup>
@@ -312,7 +393,8 @@
<UsingTask TaskName="CreateRootDescriptorFile" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_GenerateIntermediateRootDescriptor"
Inputs="@(IntermediateAssembly)"
Outputs="$(_IntermediateRootDescriptorPath)">
Outputs="$(_IntermediateRootDescriptorPath)"
Condition=" '$(RootAllApplicationAssemblies)' == 'true' ">
<CreateRootDescriptorFile AssemblyNames="@(IntermediateAssembly->'%(Filename)')"
RootDescriptorFilePath="$(_IntermediateRootDescriptorPath)" />
</Target>

View File

@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Text;
using System.IO;
using System.Linq;
namespace ILLink.Tasks
{
@@ -21,7 +18,7 @@ namespace ILLink.Tasks
/// resolved.
/// </summary>
[Required]
public ITaskItem[] AssemblyPaths { get; set; }
public ITaskItem [] AssemblyPaths { get; set; }
/// <summary>
/// The names of the assemblies to root. This should contain
@@ -34,7 +31,7 @@ namespace ILLink.Tasks
/// files, or pass extra arguments for illink.
/// </summary>
[Required]
public ITaskItem[] RootAssemblyNames { get; set; }
public ITaskItem [] RootAssemblyNames { get; set; }
/// <summary>
/// The directory in which to place linked assemblies.
@@ -47,55 +44,74 @@ namespace ILLink.Tasks
/// roots at a granular level. See the mono/linker
/// documentation for details about the format.
/// </summary>
public ITaskItem[] RootDescriptorFiles { get; set; }
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()
/// <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);
int ret = Mono.Linker.Driver.Main(args);
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()
string [] GenerateCommandLineCommands ()
{
var args = new List<string>();
var args = new List<string> ();
if (RootDescriptorFiles != null) {
foreach (var rootFile in RootDescriptorFiles) {
args.Add("-x");
args.Add(rootFile.ItemSpec);
args.Add ("-x");
args.Add (rootFile.ItemSpec);
}
}
foreach (var assemblyItem in RootAssemblyNames) {
args.Add("-a");
args.Add(assemblyItem.ItemSpec);
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);
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);
args.Add ("-out");
args.Add (OutputDirectory.ItemSpec);
}
if (ExtraArgs != null) {
args.AddRange(ExtraArgs.Split(' '));
args.AddRange (ExtraArgs.Split (' '));
}
return args.ToArray();
if (DumpDependencies)
args.Add ("--dump-dependencies");
return args.ToArray ();
}
}

View File

@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.IO;
namespace ILLink.Tasks
{
public class SetAssemblyActions : Task
{
/// <summary>
/// Paths to the assembly files that should be considered as
/// input to the linker.
/// </summary>
[Required]
public ITaskItem [] AssemblyPaths { get; set; }
/// <summary>
/// Application assembly names.
/// </summary>
[Required]
public ITaskItem [] ApplicationAssemblyNames { get; set; }
/// <summary>
/// Platform assembly names.
/// </summary>
[Required]
public ITaskItem [] PlatformAssemblyNames { get; set; }
/// <summary>
/// Action to perform on used application assemblies.
/// </summary>
[Required]
public ITaskItem UsedApplicationAssemblyAction { get; set; }
/// <summary>
/// Action to perform on unused application assemblies.
/// </summary>
[Required]
public ITaskItem UnusedApplicationAssemblyAction { get; set; }
/// <summary>
/// Action to perform on used platform assemblies.
/// </summary>
[Required]
public ITaskItem UsedPlatformAssemblyAction { get; set; }
/// <summary>
/// Action to perform on unused platform assemblies.
/// </summary>
[Required]
public ITaskItem UnusedPlatformAssemblyAction { get; set; }
[Output]
public ITaskItem [] AssemblyPathsWithActions { get; set; }
public override bool Execute ()
{
string applicationAssemblyAction;
string usedApplicationAssemblyAction = UsedApplicationAssemblyAction.ItemSpec;
string unusedApplicationAssemblyAction = UnusedApplicationAssemblyAction.ItemSpec;
if (!GetAssemblyAction (usedApplicationAssemblyAction.ToLower (), unusedApplicationAssemblyAction.ToLower (), out applicationAssemblyAction)) {
Log.LogError ("Unsupported combination of application assembly actions: {0}, {1}.",
usedApplicationAssemblyAction, unusedApplicationAssemblyAction);
return false;
}
string platformAssemblyAction;
string usedPlatformAssemblyAction = UsedPlatformAssemblyAction.ItemSpec;
string unusedPlatformAssemblyAction = UnusedPlatformAssemblyAction.ItemSpec;
if (!GetAssemblyAction (usedPlatformAssemblyAction.ToLower (), unusedPlatformAssemblyAction.ToLower (), out platformAssemblyAction)) {
Log.LogError ("Unsupported combination of platform assembly actions: {0}, {1}.",
usedPlatformAssemblyAction, unusedPlatformAssemblyAction);
return false;
}
List<ITaskItem> resultAssemblies = new List<ITaskItem> ();
AddAssemblyActionMetadata (ApplicationAssemblyNames, applicationAssemblyAction, resultAssemblies);
AddAssemblyActionMetadata (PlatformAssemblyNames, platformAssemblyAction, resultAssemblies);
AssemblyPathsWithActions = resultAssemblies.ToArray ();
return true;
}
bool GetAssemblyAction (string usedAssemblyAction, string unusedAssemblyAction, out string assemblyAction)
{
assemblyAction = "illegal";
if ((unusedAssemblyAction != usedAssemblyAction) && (unusedAssemblyAction != "delete")) {
return false;
}
switch (usedAssemblyAction) {
case "link":
assemblyAction = "link";
break;
case "copy":
assemblyAction = (unusedAssemblyAction == "delete") ? "copyused" : "copy";
break;
case "addbypassngen":
assemblyAction = (unusedAssemblyAction == "delete") ? "addbypassngenused" : "addbypassngen";
break;
case "skip":
if (unusedAssemblyAction != usedAssemblyAction) {
return false;
}
assemblyAction = "skip";
break;
default:
return false;
}
return true;
}
void AddAssemblyActionMetadata (ITaskItem [] assemblies, string action, List<ITaskItem> resultList)
{
HashSet<string> assemblyHashSet = new HashSet<string> ();
foreach (var assembly in assemblies) {
assemblyHashSet.Add (assembly.ItemSpec);
}
foreach (var assembly in AssemblyPaths) {
if (assemblyHashSet.Contains (Path.GetFileNameWithoutExtension (assembly.ItemSpec))) {
assembly.SetMetadata ("action", action);
resultList.Add (assembly);
}
}
}
}
}

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