You've already forked linux-packaging-mono
Imported Upstream version 6.0.0.172
Former-commit-id: f3cc9b82f3e5bd8f0fd3ebc098f789556b44e9cd
This commit is contained in:
parent
8016999e4d
commit
64ac736ec5
1
external/linker/corebuild/.cliversion
vendored
1
external/linker/corebuild/.cliversion
vendored
@ -1 +0,0 @@
|
||||
2.0.0
|
186
external/linker/corebuild/README.md
vendored
186
external/linker/corebuild/README.md
vendored
@ -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.
|
67
external/linker/corebuild/bootstrap.ps1
vendored
67
external/linker/corebuild/bootstrap.ps1
vendored
@ -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
|
206
external/linker/corebuild/bootstrap.sh
vendored
206
external/linker/corebuild/bootstrap.sh
vendored
@ -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."
|
||||
|
2
external/linker/corebuild/build.cmd
vendored
2
external/linker/corebuild/build.cmd
vendored
@ -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%
|
||||
|
2
external/linker/corebuild/build.sh
vendored
2
external/linker/corebuild/build.sh
vendored
@ -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 $?
|
||||
|
8
external/linker/corebuild/dotnet.cmd
vendored
8
external/linker/corebuild/dotnet.cmd
vendored
@ -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%
|
||||
|
27
external/linker/corebuild/dotnet.ps1
vendored
27
external/linker/corebuild/dotnet.ps1
vendored
@ -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
|
25
external/linker/corebuild/dotnet.sh
vendored
25
external/linker/corebuild/dotnet.sh
vendored
@ -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 $?
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
Reference in New Issue
Block a user