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

View File

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

@ -1,67 +0,0 @@
param
(
[Parameter(Mandatory=$false)][string]$RepositoryRoot = $PSScriptRoot,
[Parameter(Mandatory=$false)][string]$ToolsLocalPath = (Join-Path $RepositoryRoot "Tools"),
[Parameter(Mandatory=$false)][string]$CliLocalPath = (Join-Path $ToolsLocalPath "dotnetcli"),
[Parameter(Mandatory=$false)][string]$SharedFrameworkSymlinkPath = (Join-Path $ToolsLocalPath "dotnetcli\shared\Microsoft.NETCore.App\version"),
[Parameter(Mandatory=$false)][string]$SharedFrameworkVersion = "<auto>",
[Parameter(Mandatory=$false)][string]$Architecture = "<auto>",
[Parameter(Mandatory=$false)][string]$DotNetInstallBranch = "release/2.0.0",
[switch]$Force = $false
)
$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
if ($Force -and (Test-Path $bootstrapComplete))
{
del $bootstrapComplete
}
# if the semaphore file exists and is identical to the specified version then exit
if ((Test-Path $bootstrapComplete) -and !(Compare-Object (Get-Content $rootCliVersion) (Get-Content $bootstrapComplete)))
{
exit 0
}
$initCliScript = "dotnet-install.ps1"
$dotnetInstallPath = Join-Path $ToolsLocalPath $initCliScript
# blow away the tools directory so we can start from a known state
if (Test-Path $ToolsLocalPath)
{
# if the bootstrap.ps1 script was downloaded to the tools directory don't delete it
rd -recurse -force $ToolsLocalPath -exclude "bootstrap.ps1"
}
else
{
mkdir $ToolsLocalPath | Out-Null
}
# download CLI boot-strapper script
Invoke-WebRequest "https://raw.githubusercontent.com/dotnet/cli/$DotNetInstallBranch/scripts/obtain/dotnet-install.ps1" -OutFile $dotnetInstallPath
# load the version of the CLI
$dotNetCliVersion = Get-Content $rootCliVersion
if (-Not (Test-Path $CliLocalPath))
{
mkdir $CliLocalPath | Out-Null
}
# now execute the script
Write-Host "$dotnetInstallPath -Version $dotNetCliVersion -InstallDir $CliLocalPath -Architecture ""$Architecture"""
Invoke-Expression "$dotnetInstallPath -Version $dotNetCliVersion -InstallDir $CliLocalPath -Architecture ""$Architecture"""
if ($LastExitCode -ne 0)
{
Write-Output "The .NET CLI installation failed with exit code $LastExitCode"
exit $LastExitCode
}
"{ `"sdk`": { `"version`": `"$dotNetCliVersion`" } }" | Out-File -Encoding utf8 -FilePath $globalJson
# write semaphore file
copy $rootCliVersion $bootstrapComplete
exit 0

View File

@ -1,206 +0,0 @@
#!/usr/bin/env bash
# Stop script on NZEC
# set -e
# Stop script if unbound variable found (use ${var:-} if intentional)
set -u
# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success
# This is causing it to fail
set -o pipefail
# Use in the the functions: eval $invocation
invocation='say_verbose "Calling: ${FUNCNAME[0]}"'
# standard output may be used as a return value in the functions
# we need a way to write text on the screen in the functions so that
# it won't interfere with the return value.
# Exposing stream 3 as a pipe to standard output of the script itself
exec 3>&1
say_err() {
printf "%b\n" "bootstrap: Error: $1" >&2
}
say() {
# using stream 3 (defined in the beginning) to not interfere with stdout of functions
# which may be used as return value
printf "%b\n" "bootstrap: $1" >&3
}
say_verbose() {
if [ "$verbose" = true ]; then
say "$1"
fi
}
machine_has() {
eval $invocation
hash "$1" > /dev/null 2>&1
return $?
}
check_min_reqs() {
if ! machine_has "curl"; then
say_err "curl is required to download dotnet. Install curl to proceed."
return 1
fi
return 0
}
# args:
# remote_path - $1
# [out_path] - $2 - stdout if not provided
download() {
eval $invocation
local remote_path=$1
local out_path=${2:-}
local failed=false
if [ -z "$out_path" ]; then
curl --retry 10 -sSL --create-dirs $remote_path || failed=true
else
curl --retry 10 -sSL --create-dirs -o $out_path $remote_path || failed=true
fi
if [ "$failed" = true ]; then
say_err "Download failed"
return 1
fi
}
verbose=false
repoRoot=`pwd`
toolsLocalPath="<auto>"
cliLocalPath="<auto>"
symlinkPath="<auto>"
sharedFxVersion="<auto>"
force=
forcedCliLocalPath="<none>"
architecture="<auto>"
dotNetInstallBranch="release/2.0.0"
while [ $# -ne 0 ]
do
name=$1
case $name in
-r|--repositoryRoot|-[Rr]epositoryRoot)
shift
repoRoot="$1"
;;
-t|--toolsLocalPath|-[Tt]oolsLocalPath)
shift
toolsLocalPath="$1"
;;
-c|--cliInstallPath|--cliLocalPath|-[Cc]liLocalPath)
shift
cliLocalPath="$1"
;;
-u|--useLocalCli|-[Uu]seLocalCli)
shift
forcedCliLocalPath="$1"
;;
-a|--architecture|-[Aa]rchitecture)
shift
architecture="$1"
;;
--dotNetInstallBranch|-[Dd]ot[Nn]et[Ii]nstall[Bb]ranch)
shift
dotNetInstallBranch="$1"
;;
--sharedFrameworkSymlinkPath|--symlink|-[Ss]haredFrameworkSymlinkPath)
shift
symlinkPath="$1"
;;
--sharedFrameworkVersion|-[Ss]haredFrameworkVersion)
sharedFxVersion="$1"
;;
--force|-[Ff]orce)
force=true
;;
-v|--verbose|-[Vv]erbose)
verbose=true
;;
*)
say_err "Unknown argument \`$name\`"
exit 1
;;
esac
shift
done
if [ $toolsLocalPath = "<auto>" ]; then
toolsLocalPath="$repoRoot/Tools"
fi
if [ $cliLocalPath = "<auto>" ]; then
if [ $forcedCliLocalPath = "<none>" ]; then
cliLocalPath="$toolsLocalPath/dotnetcli"
else
cliLocalPath=$forcedCliLocalPath
fi
fi
if [ $symlinkPath = "<auto>" ]; then
symlinkPath="$toolsLocalPath/dotnetcli/shared/Microsoft.NETCore.App/version"
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
if [[ $force && -f $bootstrapComplete ]]; then
rm -f $bootstrapComplete
fi
# if the semaphore file exists and is identical to the specified version then exit
if [[ -f $bootstrapComplete && ! `cmp $bootstrapComplete $rootCliVersion` ]]; then
say "$bootstrapComplete appears to show that bootstrapping is complete. Use --force if you want to re-bootstrap."
exit 0
fi
initCliScript="dotnet-install.sh"
dotnetInstallPath="$toolsLocalPath/$initCliScript"
# blow away the tools directory so we can start from a known state
if [ -d $toolsLocalPath ]; then
# if the bootstrap.sh script was downloaded to the tools directory don't delete it
find $toolsLocalPath -type f -not -name bootstrap.sh -exec rm -f {} \;
else
mkdir $toolsLocalPath
fi
if [ $forcedCliLocalPath = "<none>" ]; then
check_min_reqs
# download CLI boot-strapper script
download "https://raw.githubusercontent.com/dotnet/cli/$dotNetInstallBranch/scripts/obtain/dotnet-install.sh" "$dotnetInstallPath"
chmod u+x "$dotnetInstallPath"
# load the version of the CLI
dotNetCliVersion=`cat $rootCliVersion`
if [ ! -e $cliLocalPath ]; then
mkdir -p "$cliLocalPath"
fi
# now execute the script
say_verbose "installing CLI: $dotnetInstallPath --version \"$dotNetCliVersion\" --install-dir $cliLocalPath --architecture \"$architecture\""
$dotnetInstallPath --version "$dotNetCliVersion" --install-dir $cliLocalPath --architecture "$architecture"
if [ $? != 0 ]; then
say_err "The .NET CLI installation failed with exit code $?"
exit $?
fi
echo "{ \"sdk\": { \"version\": \"$dotNetCliVersion\" } }" > $globalJson
fi
cp $rootCliVersion $bootstrapComplete
say "Bootstrap finished successfully."

View File

@ -2,5 +2,5 @@
REM build.cmd will bootstrap the cli and ultimately call "dotnet pack"
@call %~dp0dotnet.cmd pack %~dp0integration\ILLink.Tasks\ILLink.Tasks.csproj %*
@call %~dp0dotnet.cmd pack %~dp0..\src\ILLink.Tasks\ILLink.Tasks.csproj %*
@exit /b %ERRORLEVEL%

View File

@ -3,5 +3,5 @@
# build.sh will bootstrap the cli and ultimately call "dotnet build"
working_tree_root="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
$working_tree_root/dotnet.sh build $working_tree_root/linker.sln $@
$working_tree_root/../eng/dotnet.sh build $working_tree_root/../illink.sln $@
exit $?

View File

@ -2,14 +2,18 @@
setlocal
if not defined VisualStudioVersion (
if defined VS150COMNTOOLS (
call "%VS150COMNTOOLS%\VsDevCmd.bat"
goto :Run
)
if defined VS140COMNTOOLS (
call "%VS140COMNTOOLS%\VsDevCmd.bat"
goto :Run
)
echo Error: Visual Studio 2015 required.
echo Error: Visual Studio 2015 or 2017 required.
exit /b 1
)
:Run
powershell -NoProfile -ExecutionPolicy unrestricted -Command "%~dp0dotnet.ps1 -- %*"
powershell -NoProfile -ExecutionPolicy unrestricted -Command "%~dp0..\eng\dotnet.ps1 -- %*"
exit /b %ERRORLEVEL%

View File

@ -1,27 +0,0 @@
# set the base tools directory
$toolsLocalPath = Join-Path $PSScriptRoot "Tools"
$bootStrapperPath = Join-Path $toolsLocalPath "bootstrap.ps1"
# if the boot-strapper script doesn't exist copy it to the tools path
if ((Test-Path $bootStrapperPath) -eq 0)
{
if ((Test-Path $toolsLocalPath) -eq 0)
{
mkdir $toolsLocalPath | Out-Null
}
cp (Join-Path $PSScriptRoot "bootstrap.ps1") $bootStrapperPath
}
# now execute it
& $bootStrapperPath $PSScriptRoot $toolsLocalPath | Out-File (Join-Path $PSScriptRoot "bootstrap.log")
if ($LastExitCode -ne 0)
{
Write-Output "Boot-strapping failed with exit code $LastExitCode, see bootstrap.log for more information."
exit $LastExitCode
}
# execute the tool using the dotnet.exe host
$dotNetExe = Join-Path $toolsLocalPath "dotnetcli\dotnet.exe"
& $dotNetExe $args
exit $LastExitCode

View File

@ -1,25 +0,0 @@
#!/usr/bin/env bash
__scriptpath=$(cd "$(dirname "$0")"; pwd -P)
toolsLocalPath=$__scriptpath/Tools
bootStrapperPath=$toolsLocalPath/bootstrap.sh
if [ ! -e $bootStrapperPath ]; then
if [ ! -e $toolsLocalPath ]; then
mkdir $toolsLocalPath
fi
cp $__scriptpath/bootstrap.sh $__scriptpath/Tools
fi
$bootStrapperPath --verbose --repositoryRoot $__scriptpath --toolsLocalPath $toolsLocalPath > bootstrap.log
lastExitCode=$?
if [ $lastExitCode -ne 0 ]; then
echo "Boot-strapping failed with exit code $lastExitCode, see bootstrap.log for more information."
exit $lastExitCode
fi
dotNetExe=$toolsLocalPath/dotnetcli/dotnet
echo $dotNetExe $@
$dotNetExe $@
exit $?

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

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