Imported Upstream version 5.14.0.78

Former-commit-id: 3494343bcc9ddb42b36b82dd9ae7b69e85e0229f
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-05-10 08:37:03 +00:00
parent 74b74abd9f
commit 19234507ba
1776 changed files with 67755 additions and 31107 deletions

186
external/linker/corebuild/README.md vendored Normal file
View File

@@ -0,0 +1,186 @@
# ILLink.Tasks
ILLink.Tasks is a package containing MSBuild tasks and targets that
will run the linker to run during publish of a .NET Core app.
ILLink.Tasks provides an MSBuild task called ILLink that makes it easy
to run the linker from an MSBuild project file:
```xml
<ILLink AssemblyPaths="@(AssemblyFilesToLink)"
RootAssemblyNames="@(LinkerRootAssemblies)"
RootDescriptorFiles="@(LinkerRootDescriptors)"
OutputDirectory="output"
ExtraArgs="-t -c link -l none" />
```
For a description of the options that this task supports, see the
comments in [LinkTask.cs](integration/ILLink.Tasks/LinkTask.cs).
In addition, ILLink.Tasks contains MSBuild logic that makes the linker
run automatically during `dotnet publish` for .NET Core apps. This
will:
- Determine the assemblies and options to pass to illink.
- Remove unused native files from the publish output.
- Run crossgen on the linked assemblies to improve startup performance.
The full set of options is described below.
## Building
```
linker> ./corebuild/dotnet.{sh/ps1} restore ./corebuild/integration/linker.sln
linker> ./corebuild/dotnet.{sh/ps1} pack ./corebuild/integration/ILLink.Tasks/ILLink.Tasks.csproj
```
The output package will be placed in
`corebuild/integration/bin/nupkgs`. If you are building on unix, you
will need to adjust
[ILLink.Tasks.nuspec](integration/ILLink.Tasks/ILLink.Tasks.nuspec). Replace
the dll file includes with the following:
`<file src="netcoreapp2.0/**/*.dll" target="tools/netcoreapp2.0" />`
## Using ILLink.Tasks
Add a package reference to the linker. Ensure that either the
[dotnet-core](https://dotnet.myget.org/gallery/dotnet-core) myget feed
or the path to the locally-built linker package path exists in the
project's nuget.config. If using myget, you probably want to ensure
that you're using the latest version available at
https://dotnet.myget.org/feed/dotnet-core/package/nuget/ILLink.Tasks.
After adding the package, linking will be turned on during `dotnet
publish`. The publish output will contain the linked assemblies.
## Default behavior
By default, the linker will operate in a conservative mode that keeps
all managed assemblies that aren't part of the framework (they are
kept intact, and the linker simply copies them). It also analyzes all
non-framework assemblies to find and keep code used by them (they are
roots for the analysis). This means that unanalyzed reflection calls
within the app should continue to work after linking. Reflection calls
to code in the framework can potentially break when using the linker,
if the target of the call is removed.
For portable publish, framework assemblies usually do not get
published with the app. In this case they will not be analyzed or
linked.
For self-contained publish, framework assemblies are part of the
publish output, and are analyzed by the linker. Any framework
assemblies that aren't predicted to be used at runtime based on the
linker analysis will be removed from the publish output. Used
framework assemblies will be kept, and any used code within these
assemblies will be compiled to native code. Unused parts of used
framework assemblies are kept as IL, so that reflection calls will
continue to work, with runtime JIT compilation.
Native dependencies that aren't referenced by any of the kept managed
assemblies will be removed from the publish output as well.
## Caveats
You should make sure to test the publish output before deploying your
code, because the linker can potentially break apps that use
reflection.
The linker does not analyze reflection calls, so any reflection
targets outside of the kept assemblies will need to be rooted
explicitly using either `LinkerRootAssemblies` or
`LinkerRootDescriptors` (see below).
Sometimes an application may include multiple versions of the same
assembly. This may happen when portable apps include platform-specific
managed code, which gets placed in the `runtimes` directory of the
publish output. In such cases, the linker will pick one of the
duplicate assemblies to analyze. This means that dependencies of the
un-analyzed duplicates may not be included in the application, so you
may need to root such dependencies manually.
Native compilation only works when the target platform is the same as
the host. To use the linker when cross-targeting (building a unix app
from windows, for example), disable `CrossGenDuringPublish`.
## Options
The following MSBuild properties can be used to control the behavior
of the linker, from the command-line (via `dotnet publish
/p:PropertyName=PropertyValue`), or from the .csproj file (via
`<PropertyName>PropertyValue</PropertyName>`). They are defined and
used in
[ILLink.Tasks.targets](integration/ILLink.Tasks/ILLink.Tasks.targets)
and
[ILLink.CrossGen.targets](integration/ILLink.Tasks/ILLink.CrossGen.targets)
- `LinkDuringPublish` (default `true`) - Set to `false` to disable
linking.
- `ShowLinkerSizeComparison` (default `false`) - Set to `true` to
print out a table showing the size impact of the linker.
- `RootAllApplicationAssemblies` (default `true`) - If `true`, all
application assemblies are rooted by the linker. This means they are
kept in their entirety, and analyzed for dependencies. If `false`,
only the app dll's entry point is rooted.
- `LinkerRootAssemblies` - The set of assemblies to root. The default
depends on the value of `RootAllApplicationAssemblies`. Additional
assemblies can be rooted by adding them to this ItemGroup.
- `LinkerRootDescriptors` - The set of [xml descriptors](../linker#syntax-of-xml-descriptor)
specifying additional roots within assemblies. The default is to
include a generated descriptor that roots everything in the
application assembly if `RootAllApplicationAssemblies` is
`true`. Additional roots from descriptors can be included by adding
the descriptor files to this ItemGroup.
- `ExtraLinkerArgs` - Extra arguments to pass to the linker. The
default sets some flags that output symbols, tolerate resolution
errors, log warnings, skip mono-specific localization assemblies,
and keep type-forwarder assemblies. See
[ILLink.Tasks.targets](integration/ILLink.Tasks/ILLink.Tasks.targets).
Setting this will override the defaults.
- Assembly actions: illink has the ability to specify an [action](../linker#actions-on-the-assemblies) to
take per-assembly. ILLink.Tasks provides high-level switches that
control the action to take for a set of assemblies. The set of
managed files that make up the application are split into
"application" and "platform" assemblies. The "platform" represents
the .NET framework, while the "application" represents the rest of
the application and its other dependencies. The assembly action can
be set for each of these groups independently, for assemblies that
are analyzed as used and as unused, with the following switches:
- `UsedApplicationAssemblyAction` - The default is to `Copy` any used
application assemblies to the output, leaving them as-is.
- `UnusedApplicationAssemblyAction` - The default is to `Delete` (not
publish) unused application assemblies.
- `UsedPlatformAssemblyAction` - For self-contained publish, the
default is `AddBypassNGen`, which will add the BypassNGenAttribute
to unused code in used platform assemblies. This causes the native
compilation step to compile only parts of these assemblies that
are used. For portable publish, the default is to `Skip` these,
because the platform assemblies are generally not published with
the app.
- `UnusedPlatformAssemblyAction` - For self-contained publish, the
default is to `Delete` (not publish) unused platform
assemblies. For portable publish, the default is to `Skip`.
The full list of assembly actions is described in
[AssemblyAction.cs](../linker/Linker/AssemblyAction.cs) Some
combinations of actions may be disallowed if they do not make
sense. For more details, see
[SetAssemblyActions.cs](integration/ILLink.Tasks/SetAssemblyActions.cs).
- `LinkerTrimNativeDeps` (default `true`) - If `true`, enable
detection and removal of unused native dependencies. If `false`, all
native dependencies are kept.
- `CrossGenDuringPublish` (default `true`) - If `true`, run crossgen
on the set of assemblies modified by the linker that were crossgen'd
before linking. If `false`, just output IL for the linked
assemblies, even if they were crossgen'd before linking.

View File

@@ -4,7 +4,7 @@ using Microsoft.Build.Utilities;
namespace ILLink.Tasks
{
public class ComputeReadyToRunAssemblies : Task
public class ComputeCrossgenedAssemblies : Task
{
/// <summary>
/// Paths to assemblies.
@@ -13,17 +13,17 @@ namespace ILLink.Tasks
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.
/// This will contain the output list of crossgen-ed
/// assemblies. Metadata from the input parameter
/// Assemblies is preserved.
/// </summary>
[Output]
public ITaskItem[] ReadyToRunAssemblies { get; set; }
public ITaskItem[] CrossgenedAssemblies { get; set; }
public override bool Execute()
{
ReadyToRunAssemblies = Assemblies
.Where(f => Utils.IsReadyToRunAssembly(f.ItemSpec))
CrossgenedAssemblies = Assemblies
.Where(f => Utils.IsCrossgenedAssembly(f.ItemSpec))
.ToArray();
return true;
}

View File

@@ -33,6 +33,12 @@ namespace ILLink.Tasks
[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>
@@ -76,6 +82,12 @@ namespace ILLink.Tasks
return false;
}
var iLLinkTrimXmlFilePath = ILLinkTrimXmlFilePath.ItemSpec;
if (!File.Exists (iLLinkTrimXmlFilePath)) {
Log.LogError ("File " + iLLinkTrimXmlFilePath + " doesn't exist.");
return false;
}
ProcessNamespaces (namespaceFilePath);
ProcessMscorlib (mscorlibFilePath);
@@ -84,7 +96,7 @@ namespace ILLink.Tasks
ProcessExceptionTypes (rexcepFilePath);
OutputXml (RuntimeRootDescriptorFilePath.ItemSpec);
OutputXml (iLLinkTrimXmlFilePath, RuntimeRootDescriptorFilePath.ItemSpec);
return true;
}
@@ -206,22 +218,17 @@ namespace ILLink.Tasks
string classNamespace = defElements [1]; // g_InteropNS
string className = defElements [2]; // MarshalDirectiveException
AddClass (classNamespace, className, classId);
AddMethod (".ctor", classId, classNamespace, className);
}
}
}
void OutputXml (string outputFileName)
void OutputXml (string iLLinkTrimXmlFilePath, 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);
doc.Load (iLLinkTrimXmlFilePath);
XmlNode linkerNode = doc ["linker"];
XmlNode assemblyNode = linkerNode ["assembly"];
foreach (string typeName in classNamesToClassMembers.Keys) {
XmlNode typeNode = doc.CreateElement ("type");
@@ -273,20 +280,8 @@ namespace ILLink.Tasks
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;
string fullClassName = GetFullClassName (classNamespace, className);
if (fullClassName != null) {
if ((classId != null) && (classId != "NoClass")) {
classIdsToClassNames [classId] = fullClassName;
}
@@ -311,16 +306,44 @@ namespace ILLink.Tasks
members.fields.Add (fieldName);
}
void AddMethod (string methodName, string classId)
void AddMethod (string methodName, string classId, string classNamespace = null, string className = null)
{
string className = classIdsToClassNames [classId];
string fullClassName;
if (classId != null) {
fullClassName = classIdsToClassNames [classId];
}
else {
fullClassName = GetFullClassName (classNamespace, className);
}
ClassMembers members = classNamesToClassMembers [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

@@ -0,0 +1,47 @@
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,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CrossGenDuringPublish Condition=" '$(CrossGenDuringPublish)' == '' And '$(RuntimeIdentifier)' != '' ">true</CrossGenDuringPublish>
<CrossGenDuringPublish Condition=" '$(CrossGenDuringPublish)' == '' And '$(RuntimeIdentifier)' != '' And '$(LinkDuringPublish)' == 'true' ">true</CrossGenDuringPublish>
</PropertyGroup>
<PropertyGroup>
@@ -28,8 +28,7 @@
<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>
@@ -188,9 +187,9 @@
<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
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"
@@ -208,21 +207,20 @@
<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)" />
<UsingTask TaskName="ComputeCrossgenedAssemblies" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_ComputeFilesToCrossGen"
DependsOnTargets="_ComputeDefaultFilesToCrossGen">
<ComputeReadyToRunAssemblies Assemblies="@(FilesToCrossGen)">
<Output TaskParameter="ReadyToRunAssemblies" ItemName="_ReadyToRunFiles" />
</ComputeReadyToRunAssemblies>
<ComputeCrossgenedAssemblies Assemblies="@(FilesToCrossGen)">
<Output TaskParameter="CrossgenedAssemblies" ItemName="_CrossgenedFiles" />
</ComputeCrossgenedAssemblies>
<!-- Don't try to run crossgen on assemblies that are already R2R. -->
<!-- Don't try to run crossgen on assemblies that are already
crossgen'd. -->
<ItemGroup>
<FilesToCrossGen Remove="@(_ReadyToRunFiles)" />
<FilesToCrossGen Remove="@(_CrossgenedFiles)" />
</ItemGroup>
<Message Text="files to crossgen: @(FilesToCrossGen)" />

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>0.1.4-preview</VersionPrefix>
<VersionPrefix>0.1.5-preview</VersionPrefix>
<TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
@@ -101,11 +101,12 @@
<Compile Include="LinkTask.cs" />
<Compile Include="CompareSizes.cs" />
<Compile Include="ComputeManagedAssemblies.cs" />
<Compile Include="ComputeReadyToRunAssemblies.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" />

View File

@@ -95,7 +95,7 @@
<!-- Rewrite ResolvedAssembliesToPublish, which is an input to
ComputeFilesToPublish. -->
<ItemGroup>
<ResolvedAssembliesToPublish Remove="@(_ManagedResolvedAssembliesToPublish)" />
<ResolvedAssembliesToPublish Remove="@(_ManagedAssembliesToLink)" />
<ResolvedAssembliesToPublish Remove="@(_NativeResolvedDepsToPublish)" />
<ResolvedAssembliesToPublish Include="@(_NativeKeptDepsToPublish)" />
<ResolvedAssembliesToPublish Include="@(_LinkedResolvedAssemblies)" />
@@ -145,15 +145,21 @@
<!-- Print out a size comparison report for the linked
assemblies. This is disabled by default, but can be turned on
by setting $(ShowLinkerSizeComparison) to true. This runs after
the top-level link target, ComputeLinkedFilesToPublish, so it
is output even during incremental builds. -->
the ComputeFilesToPublish, so it is output even during
incremental builds and takes into account all transformations
on the files to be published, including link and crossgen. -->
<UsingTask TaskName="CompareAssemblySizes" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_CompareLinkedAssemblySizes"
AfterTargets="ComputeLinkedFilesToPublish"
AfterTargets="ComputeFilesToPublish"
DependsOnTargets="_ComputeManagedAssembliesToLink;_ComputeLinkedAssemblies"
Condition=" '$(LinkDuringPublish)' == 'true' And '$(ShowLinkerSizeComparison)' == 'true' ">
<FilterByMetadata Items="@(ResolvedAssembliesToPublish);@(IntermediateAssembly)"
MetadataName="Filename"
MetadataValues="@(_ManagedAssembliesToLink->'%(Filename)')">
<Output TaskParameter="FilteredItems" ItemName="_FinalAssembliesTouchedByLinker" />
</FilterByMetadata>
<CompareAssemblySizes UnlinkedAssemblies="@(_ManagedAssembliesToLink)"
LinkedAssemblies="@(_LinkedIntermediateAssembly);@(_LinkedResolvedAssemblies)" />
LinkedAssemblies="@(_FinalAssembliesTouchedByLinker)" />
</Target>
@@ -166,9 +172,10 @@
DependsOnTargets="_ComputeManagedResolvedAssembliesToPublish;ILLink">
<ItemGroup>
<__LinkedResolvedAssemblies Include="@(_ManagedResolvedAssembliesToPublish->'$(IntermediateLinkDir)/%(Filename)%(Extension)')" />
<__LinkedResolvedAssemblies Remove="@(_DuplicateManagedAssembliesToSkip->'$(IntermediateLinkDir)/%(Filename)%(Extension)')" />
<_LinkedResolvedAssemblies Include="@(__LinkedResolvedAssemblies)" Condition="Exists('%(Identity)')" />
</ItemGroup>
<ItemGroup>
<__LinkedIntermediateAssembly Include="@(IntermediateAssembly->'$(IntermediateLinkDir)/%(Filename)%(Extension)')" />
<_LinkedIntermediateAssembly Include="@(__LinkedIntermediateAssembly)" Condition="Exists('%(Identity)')" />
@@ -180,33 +187,62 @@
<_LinkedDebugSymbols Include="@(__LinkedDebugSymbols)"
Condition="Exists('%(Identity)') And '$(_DebugSymbolsProduced)' == 'true' " />
</ItemGroup>
</Target>
<!-- Compute the default set of assemblies to crossgen after
linking. This will include any assemblies modified by the
linker that were crossgen'd before linking. -->
<Target Name="_ComputeLinkedAssembliesToCrossgen"
AfterTargets="_ComputeLinkedAssemblies"
Condition=" '$(CrossGenDuringPublish)' == 'true' ">
<FilterByMetadata Items="@(_ManagedResolvedAssembliesToPublish);@(IntermediateAssembly)"
MetadataName="Filename"
MetadataValues="@(_LinkedResolvedAssemblies->'%(Filename)');@(_LinkedIntermediateAssembly->'%(Filename)')">
<Output TaskParameter="FilteredItems" ItemName="_OriginalLinkedAssemblies" />
</FilterByMetadata>
<ComputeCrossgenedAssemblies Assemblies="@(_OriginalLinkedAssemblies)">
<Output TaskParameter="CrossgenedAssemblies" ItemName="_OriginalLinkedAssembliesThatWereCrossgened" />
</ComputeCrossgenedAssemblies>
<!-- Ideally, we would remember which assemblies were R2R and
which were fragile crossgen-ed, and do the same after
linking. Currently this makes no difference because
System.Private.CoreLib is the only fragile image, and it
can't be ready-to-run crossgen-ed. -->
<ItemGroup>
<_LinkedAssembliesToCrossgen Include="@(_OriginalLinkedAssembliesThatWereCrossgened->'$(IntermediateLinkDir)/%(Filename)%(Extension)')" />
<FilesToCrossgen Include="@(_LinkedAssembliesToCrossgen)" />
</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>
<ItemGroup>
<_PlatformAssembliesToLink Include="@(PlatformLibraries->'%(Filename)')" />
<_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>
<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>
<ItemGroup>
<_ManagedAssembliesToLink Remove="@(_ManagedAssembliesToLink)" />
<_ManagedAssembliesToLink Include="@(_ManagedAssembliesToLinkWithActions)" />
</ItemGroup>
</Target>
<!-- This calls the linker. Inputs are the managed assemblies to
@@ -244,7 +280,8 @@
dependencies, and these are prevented from being published. -->
<UsingTask TaskName="FindNativeDeps" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_FindNativeDeps"
DependsOnTargets="_ComputeLinkedAssemblies">
DependsOnTargets="_ComputeLinkedAssemblies"
Condition=" '$(LinkerTrimNativeDeps)' == 'true' ">
<ItemGroup>
<_NativeResolvedDepsToPublish Include="@(ResolvedAssembliesToPublish)" />
<_NativeResolvedDepsToPublish Remove="@(_ManagedResolvedAssembliesToPublish)" />
@@ -263,21 +300,18 @@
<_NativeDepsToAlwaysKeep Include="hostpolicy.dll;libhostpolicy.dylib;libhostpolicy.so" />
</ItemGroup>
<FindNativeDeps Condition=" '$(LinkerTrimNativeDeps)' == 'true' "
ManagedAssemblyPaths="@(_ManagedLinkedAssemblies)"
<FindNativeDeps ManagedAssemblyPaths="@(_ManagedLinkedAssemblies);@(_DuplicateManagedAssembliesToSkip)"
NativeDepsPaths="@(_NativeResolvedDepsToPublish)"
NativeDepsToKeep="@(_NativeDepsToAlwaysKeep)">
<Output TaskParameter="KeptNativeDepsPaths" ItemName="_NativeKeptDepsToPublish" />
</FindNativeDeps>
<PropertyGroup>
<_NativeKeptDepsToPublish Condition=" '$(LinkerTrimNativeDeps)' != 'true' ">"@(_NativeResolvedDepsToPublish)"</_NativeKeptDepsToPublish>
</PropertyGroup>
</Target>
<!-- Computes the managed assemblies that are input to the
linker. Includes managed assemblies from
ResolvedAssembliesToPublish, and IntermediateAssembly. -->
<UsingTask TaskName="FindDuplicatesByMetadata" AssemblyFile="$(LinkTaskDllPath)" />
<Target Name="_ComputeManagedAssembliesToLink"
DependsOnTargets="_ComputeManagedResolvedAssembliesToPublish">
<ItemGroup>
@@ -285,6 +319,22 @@
<_ManagedAssembliesToLink Include="@(_ManagedResolvedAssembliesToPublish)" />
</ItemGroup>
<!-- Remove duplicate implementation dlls. This can happen if a
portable app has platform-specific managed assemblies. The
linker isn't currently able to analyze multiple assemblies
with the same identity, so we skip these, keeping only one
representative assembly from each set of duplicates. -->
<FindDuplicatesByMetadata Items="@(_ManagedAssembliesToLink)"
MetadataName="Filename">
<Output TaskParameter="DuplicateItems" ItemName="_DuplicateManagedAssemblies" />
<Output TaskParameter="DuplicateRepresentatives" ItemName="_DuplicateManagedAssembliesToLink" />
</FindDuplicatesByMetadata>
<ItemGroup>
<_DuplicateManagedAssembliesToSkip Include="@(_DuplicateManagedAssemblies)" />
<_DuplicateManagedAssembliesToSkip Remove="@(_DuplicateManagedAssembliesToLink)" />
<_ManagedAssembliesToLink Remove="@(_DuplicateManagedAssembliesToSkip)" />
</ItemGroup>
<!-- Portable publish: need to supply the linker with any needed
reference assemblies as well.
@@ -376,14 +426,23 @@
<ItemGroup Condition=" '$(RootAllApplicationAssemblies)' == 'true' ">
<_LinkerRootAssemblies Include="@(_ManagedResolvedAssembliesToPublish->'%(Filename)')" />
<_LinkerRootAssemblies Remove="@(PlatformLibraries->'%(Filename)')" />
<_LinkerRootAssemblies Remove="System.Private.CoreLib" Condition=" '$(_SPCHasEmbeddedRootDescriptor)' == 'true' "/>
<LinkerRootAssemblies Include="@(_LinkerRootAssemblies)" />
</ItemGroup>
<RemoveDuplicates Inputs="@(_LinkerRootAssemblies)"
Condition=" '$(RootAllApplicationAssemblies)' == 'true' ">
<Output TaskParameter="Filtered" ItemName="_UniqueLinkerRootAssemblies" />
</RemoveDuplicates>
<ItemGroup Condition=" '$(RootAllApplicationAssemblies)' == 'true' ">
<LinkerRootAssemblies Include="@(_UniqueLinkerRootAssemblies)" />
</ItemGroup>
<ItemGroup Condition=" '$(RootAllApplicationAssemblies)' == 'false' ">
<LinkerRootAssemblies Include="@(IntermediateAssembly)" />
<LinkerRootAssemblies Include="System.Private.CoreLib" Condition=" '$(_SPCHasEmbeddedRootDescriptor)' == 'false' "/>
</ItemGroup>
<ItemGroup Condition=" '$(_SPCHasEmbeddedRootDescriptor)' != 'true' ">
<LinkerRootAssemblies Include="@(_ManagedResolvedAssembliesToPublish->'%(Filename)')" Condition=" '%(Filename)' == 'System.Private.CoreLib' " />
</ItemGroup>
</Target>
<UsingTask TaskName="CheckEmbeddedRootDescriptor" AssemblyFile="$(LinkTaskDllPath)" />
@@ -406,6 +465,11 @@
PackageNames="$(MicrosoftNETPlatformLibrary)">
<Output TaskParameter="RuntimeLibraries" ItemName="PlatformLibraries" />
</GetRuntimeLibraries>
<ItemGroup>
<PlatformLibraries Include="@(_ManagedAssembliesToLink)" Condition=" '%(Filename)' == 'System.Private.CoreLib' " />
</ItemGroup>
<ItemGroup Condition=" '$(SelfContained)' != 'true' ">
<!-- Portable publish: computed referenced-not-published set in _ComputeManagedAssembliesToLink -->
<PlatformLibraries Include="@(_ReferencedLibraries)" />
@@ -447,7 +511,7 @@
DependsOnTargets="_ComputeManagedResolvedAssembliesToPublish;_ComputeLinkedAssemblies;_FindNativeDeps;_HandlePublishFileConflicts"
BeforeTargets="GeneratePublishDependencyFile"
Condition=" '$(LinkDuringPublish)' == 'true' ">
<ComputeRemovedAssemblies InputAssemblies="@(_ManagedResolvedAssembliesToPublish)"
<ComputeRemovedAssemblies InputAssemblies="@(_ManagedAssembliesToLink)"
KeptAssemblies="@(_LinkedResolvedAssemblies)">
<Output TaskParameter="RemovedAssemblies" ItemName="_RemovedManagedAssemblies" />
</ComputeRemovedAssemblies>

View File

@@ -16,6 +16,9 @@ namespace ILLink.Tasks
/// 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; }

View File

@@ -1,7 +1,8 @@
using System;
using Mono.Cecil;
using Mono.Linker;
public class Utils
public static class Utils
{
public static bool IsManagedAssembly (string fileName)
{
@@ -13,12 +14,11 @@ public class Utils
}
}
public static bool IsReadyToRunAssembly (string fileName)
public static bool IsCrossgenedAssembly (string fileName)
{
try {
ModuleDefinition module = ModuleDefinition.ReadModule (fileName);
return (module.Attributes & ModuleAttributes.ILOnly) == 0 &&
(module.Attributes & (ModuleAttributes) 0x04) != 0;
return module.IsCrossgened ();
} catch (BadImageFormatException) {
return false;
}