You've already forked linux-packaging-mono
Imported Upstream version 5.12.0.220
Former-commit-id: c477e03582759447177c6d4bf412cd2355aad476
This commit is contained in:
parent
8bd104cef2
commit
8fc30896db
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Mono.Linker;
|
||||
using Mono.Linker.Steps;
|
||||
@@ -8,17 +9,41 @@ namespace ILLink.CustomSteps
|
||||
{
|
||||
public class ClearInitLocalsStep : BaseStep
|
||||
{
|
||||
protected override void ProcessAssembly(AssemblyDefinition assembly)
|
||||
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) {
|
||||
method.Body.InitLocals = false;
|
||||
if (method.Body.InitLocals) {
|
||||
method.Body.InitLocals = false;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed && (Annotations.GetAction (assembly) == AssemblyAction.Copy))
|
||||
Annotations.SetAction (assembly, AssemblyAction.Save);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,12 @@
|
||||
<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>
|
||||
|
||||
37
external/linker/corebuild/integration/ILLink.Tasks/AdapterLogger.cs
vendored
Normal file
37
external/linker/corebuild/integration/ILLink.Tasks/AdapterLogger.cs
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,13 @@ namespace ILLink.Tasks
|
||||
/// dependencies.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] ManagedAssemblyPaths { get; set; }
|
||||
public ITaskItem [] ManagedAssemblyPaths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of native dependencies to keep even if they
|
||||
/// aren't found to be referenced by a managed assembly..
|
||||
/// aren't found to be referenced by a managed assembly.
|
||||
/// </summary>
|
||||
public ITaskItem[] NativeDepsToKeep { get; set; }
|
||||
public ITaskItem [] NativeDepsToKeep { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The paths to the available native dependencies. We
|
||||
@@ -31,7 +31,7 @@ namespace ILLink.Tasks
|
||||
/// native files.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] NativeDepsPaths { get; set; }
|
||||
public ITaskItem [] NativeDepsPaths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of native dependencies to keep, including those
|
||||
@@ -40,67 +40,51 @@ namespace ILLink.Tasks
|
||||
/// input NativeDepsToKeep.
|
||||
/// </summary>
|
||||
[Output]
|
||||
public ITaskItem[] KeptNativeDepsPaths { get; set; }
|
||||
public ITaskItem [] KeptNativeDepsPaths { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
public override bool Execute ()
|
||||
{
|
||||
var allNative = new Dictionary<string, ITaskItem> ();
|
||||
foreach (var n in NativeDepsPaths)
|
||||
{
|
||||
var fileName = Path.GetFileName(n.ItemSpec);
|
||||
if (!allNative.ContainsKey(fileName))
|
||||
{
|
||||
allNative.Add(fileName, n);
|
||||
}
|
||||
}
|
||||
var keptNative = new List<ITaskItem> ();
|
||||
var managedAssemblies = ManagedAssemblyPaths.Select (i => i.ItemSpec).ToArray();
|
||||
foreach (string managedAssembly in managedAssemblies)
|
||||
{
|
||||
using (var peReader = new PEReader(new FileStream(managedAssembly, FileMode.Open, FileAccess.Read, FileShare.Read)))
|
||||
{
|
||||
if (peReader.HasMetadata)
|
||||
{
|
||||
var reader = peReader.GetMetadataReader();
|
||||
for (int i = 1, count = reader.GetTableRowCount(TableIndex.ModuleRef); i <= count; i++)
|
||||
{
|
||||
var moduleRef = reader.GetModuleReference(MetadataTokens.ModuleReferenceHandle(i));
|
||||
var moduleName = reader.GetString(moduleRef.Name);
|
||||
var allNativeNames = new HashSet<string> ();
|
||||
foreach (var nativeDep in NativeDepsPaths)
|
||||
allNativeNames.Add (Path.GetFileName (nativeDep.ItemSpec));
|
||||
var keptNativeNames = new HashSet<string> ();
|
||||
foreach (var nativeDep in NativeDepsToKeep)
|
||||
keptNativeNames.Add (Path.GetFileName (nativeDep.ItemSpec));
|
||||
|
||||
var moduleRefCandidates = new[] { moduleName, moduleName + ".dll", moduleName + ".so", moduleName + ".dylib" };
|
||||
var managedAssemblies = ManagedAssemblyPaths.Select (i => i.ItemSpec).ToArray ();
|
||||
foreach (string managedAssembly in managedAssemblies) {
|
||||
using (var peReader = new PEReader(new FileStream (managedAssembly, FileMode.Open, FileAccess.Read, FileShare.Read))) {
|
||||
if (peReader.HasMetadata) {
|
||||
var reader = peReader.GetMetadataReader ();
|
||||
for (int i = 1, count = reader.GetTableRowCount (TableIndex.ModuleRef); i <= count; i++) {
|
||||
var moduleRef = reader.GetModuleReference (MetadataTokens.ModuleReferenceHandle (i));
|
||||
var moduleName = reader.GetString (moduleRef.Name);
|
||||
|
||||
ITaskItem referencedNativeFile = null;
|
||||
foreach (string moduleRefCandidate in moduleRefCandidates)
|
||||
{
|
||||
if (allNative.TryGetValue (moduleRefCandidate, out referencedNativeFile))
|
||||
{
|
||||
break;
|
||||
var moduleRefCandidates = new [] { moduleName, moduleName + ".dll", moduleName + ".so", moduleName + ".dylib" };
|
||||
|
||||
bool foundModuleRef = false;
|
||||
foreach (string moduleRefCandidate in moduleRefCandidates) {
|
||||
if (allNativeNames.Contains (moduleRefCandidate)) {
|
||||
keptNativeNames.Add (moduleRefCandidate);
|
||||
foundModuleRef = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (referencedNativeFile != null)
|
||||
{
|
||||
keptNative.Add(referencedNativeFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// DLLImport that wasn't satisfied
|
||||
Log.LogMessage(MessageImportance.High, "unsatisfied DLLImport: " + managedAssembly + " -> " + moduleName);
|
||||
}
|
||||
if (!foundModuleRef)
|
||||
Log.LogMessage("unsatisfied DLLImport: " + managedAssembly + " -> " + moduleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var n in NativeDepsToKeep)
|
||||
{
|
||||
ITaskItem nativeFile = null;
|
||||
if (allNative.TryGetValue (n.ItemSpec, out nativeFile))
|
||||
{
|
||||
keptNative.Add(nativeFile);
|
||||
}
|
||||
var keptNativeDeps = new List<ITaskItem> ();
|
||||
foreach (var nativeDep in NativeDepsPaths) {
|
||||
var fileName = Path.GetFileName (nativeDep.ItemSpec);
|
||||
if (keptNativeNames.Contains (fileName))
|
||||
keptNativeDeps.Add (nativeDep);
|
||||
}
|
||||
KeptNativeDepsPaths = keptNative.ToArray();
|
||||
|
||||
KeptNativeDepsPaths = keptNativeDeps.ToArray ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="AdapterLogger.cs" />
|
||||
<Compile Include="LinkTask.cs" />
|
||||
<Compile Include="CompareSizes.cs" />
|
||||
<Compile Include="ComputeManagedAssemblies.cs" />
|
||||
@@ -195,7 +196,7 @@
|
||||
<Target Name="SetCecilConfiguration"
|
||||
AfterTargets="AssignProjectConfiguration">
|
||||
<ItemGroup>
|
||||
<ProjectReferenceWithConfiguration Condition=" '%(Filename)%(Extension)' == 'Mono.Cecil.csproj' Or '%(Filename)%(Extension)' == 'Mono.Cecil.Pdb.csproj' ">
|
||||
<ProjectReferenceWithConfiguration Condition=" '%(Filename)%(Extension)' == 'Mono.Cecil.csproj' Or '%(Filename)%(Extension)' == 'Mono.Cecil.Pdb.csproj' Or '%(Filename)%(Extension)' == 'Mono.Cecil.Mdb.csproj' ">
|
||||
<SetConfiguration Condition=" '$(TargetFramework)' == 'net46' ">Configuration=net_4_0_$(Configuration)</SetConfiguration>
|
||||
<SetConfiguration Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">Configuration=netstandard_$(Configuration)</SetConfiguration>
|
||||
</ProjectReferenceWithConfiguration>
|
||||
|
||||
@@ -18,10 +18,15 @@
|
||||
<LinkerDumpDependencies Condition=" '$(LinkerDumpDependencies)' == '' ">false</LinkerDumpDependencies>
|
||||
<UsedApplicationAssemblyAction Condition=" '$(UsedApplicationAssemblyAction)' == '' ">Copy</UsedApplicationAssemblyAction>
|
||||
<UnusedApplicationAssemblyAction Condition=" '$(UnusedApplicationAssemblyAction)' == '' ">Delete</UnusedApplicationAssemblyAction>
|
||||
<UsedPlatformAssemblyAction Condition=" '$(UsedPlatformAssemblyAction)' == '' ">Link</UsedPlatformAssemblyAction>
|
||||
<UnusedPlatformAssemblyAction Condition=" '$(UnusedPlatformAssemblyAction)' == '' ">Delete</UnusedPlatformAssemblyAction>
|
||||
<UsedPlatformAssemblyAction Condition=" '$(UsedPlatformAssemblyAction)' == '' and '$(SelfContained)' == 'true' ">AddBypassNGen</UsedPlatformAssemblyAction>
|
||||
<UsedPlatformAssemblyAction Condition=" '$(UsedPlatformAssemblyAction)' == '' ">Skip</UsedPlatformAssemblyAction>
|
||||
<UnusedPlatformAssemblyAction Condition=" '$(UnusedPlatformAssemblyAction)' == '' and '$(SelfContained)' == 'true' ">Delete</UnusedPlatformAssemblyAction>
|
||||
<UnusedPlatformAssemblyAction Condition=" '$(UnusedPlatformAssemblyAction)' == '' ">Skip</UnusedPlatformAssemblyAction>
|
||||
<RootAllApplicationAssemblies Condition=" '$(RootAllApplicationAssemblies)' == '' ">true</RootAllApplicationAssemblies>
|
||||
<RootAllApplicationAssemblies Condition=" '$(RootAllApplicationAssemblies)' != 'true' ">false</RootAllApplicationAssemblies>
|
||||
<LinkerTrimNativeDeps Condition=" '$(LinkerTrimNativeDeps)' == '' ">true</LinkerTrimNativeDeps>
|
||||
<LinkerTrimNativeDeps Condition=" '$(LinkerTrimNativeDeps)' != 'true' ">false</LinkerTrimNativeDeps>
|
||||
<ClearInitLocals Condition=" '$(ClearInitLocals)' == '' ">false</ClearInitLocals>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- This depends on LinkDuringPublish, so it needs to be imported
|
||||
@@ -95,7 +100,7 @@
|
||||
<ResolvedAssembliesToPublish Include="@(_NativeKeptDepsToPublish)" />
|
||||
<ResolvedAssembliesToPublish Include="@(_LinkedResolvedAssemblies)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<!-- Rewrite IntermediateAssembly, which is an input to
|
||||
ComputeFilesToPublish. -->
|
||||
<ItemGroup>
|
||||
@@ -110,7 +115,7 @@
|
||||
<_DebugSymbolsIntermediatePath Include="@(_LinkedDebugSymbols)" Condition=" '$(_DebugSymbolsProduced)' == 'true' " />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- The SDK has a target called ComputeRefAssembliesToPublish that
|
||||
runs after ComputeFilesToPublish and rewrites
|
||||
ResolvedFileToPublish to include any reference assemblies that
|
||||
@@ -203,7 +208,7 @@
|
||||
<_ManagedAssembliesToLink Include="@(_ManagedAssembliesToLinkWithActions)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<!-- This calls the linker. Inputs are the managed assemblies to
|
||||
link, and root specifications. The semaphore enables msbuild to
|
||||
skip linking during an incremental build, when the semaphore is
|
||||
@@ -218,13 +223,15 @@
|
||||
the future we will want to generate these depending on the
|
||||
scenario in which the linker is invoked. -->
|
||||
<PropertyGroup>
|
||||
<ExtraLinkerArgs Condition=" '$(ExtraLinkerArgs)' == '' ">-t -l none -b true</ExtraLinkerArgs>
|
||||
<ExtraLinkerArgs Condition=" '$(ExtraLinkerArgs)' == '' ">-t -l none -b true --skip-unresolved true --verbose</ExtraLinkerArgs>
|
||||
</PropertyGroup>
|
||||
<ILLink AssemblyPaths="@(_ManagedAssembliesToLink)"
|
||||
RootAssemblyNames="@(LinkerRootAssemblies)"
|
||||
RootDescriptorFiles="@(LinkerRootDescriptors)"
|
||||
OutputDirectory="$(IntermediateLinkDir)"
|
||||
DumpDependencies="$(LinkerDumpDependencies)"
|
||||
ClearInitLocals="$(ClearInitLocals)"
|
||||
ClearInitLocalsAssemblies="$(ClearInitLocalsAssemblies)"
|
||||
ExtraArgs="$(ExtraLinkerArgs)" />
|
||||
|
||||
<Touch Files="$(_LinkSemaphore)" AlwaysCreate="true">
|
||||
@@ -241,6 +248,7 @@
|
||||
<ItemGroup>
|
||||
<_NativeResolvedDepsToPublish Include="@(ResolvedAssembliesToPublish)" />
|
||||
<_NativeResolvedDepsToPublish Remove="@(_ManagedResolvedAssembliesToPublish)" />
|
||||
<_NativeResolvedDepsToPublish Remove="@(_NativeResolvedDepsToPublish->WithMetadataValue('AssetType', 'resources'))" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -255,11 +263,15 @@
|
||||
<_NativeDepsToAlwaysKeep Include="hostpolicy.dll;libhostpolicy.dylib;libhostpolicy.so" />
|
||||
</ItemGroup>
|
||||
|
||||
<FindNativeDeps ManagedAssemblyPaths="@(_ManagedLinkedAssemblies)"
|
||||
<FindNativeDeps Condition=" '$(LinkerTrimNativeDeps)' == 'true' "
|
||||
ManagedAssemblyPaths="@(_ManagedLinkedAssemblies)"
|
||||
NativeDepsPaths="@(_NativeResolvedDepsToPublish)"
|
||||
NativeDepsToKeep="@(_NativeDepsToAlwaysKeep)">
|
||||
<Output TaskParameter="KeptNativeDepsPaths" ItemName="_NativeKeptDepsToPublish" />
|
||||
</FindNativeDeps>
|
||||
<PropertyGroup>
|
||||
<_NativeKeptDepsToPublish Condition=" '$(LinkerTrimNativeDeps)' != 'true' ">"@(_NativeResolvedDepsToPublish)"</_NativeKeptDepsToPublish>
|
||||
</PropertyGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
@@ -272,6 +284,26 @@
|
||||
<_ManagedAssembliesToLink Include="@(IntermediateAssembly)" />
|
||||
<_ManagedAssembliesToLink Include="@(_ManagedResolvedAssembliesToPublish)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Portable publish: need to supply the linker with any needed
|
||||
reference assemblies as well.
|
||||
|
||||
Sometimes assemblies have separate reference and
|
||||
implementation assemblies. In these cases, prefer the
|
||||
implementation assembly, and prevent inclusion of the ref
|
||||
assembly by filtering on filename instead of the full
|
||||
path. -->
|
||||
<FilterByMetadata Items="@(ReferencePath->'%(ResolvedPath)')"
|
||||
MetadataName="Filename"
|
||||
MetadataValues="@(_ManagedAssembliesToLink->'%(Filename)')"
|
||||
Condition=" '$(SelfContained)' != 'true' ">
|
||||
<Output TaskParameter="FilteredItems" ItemName="_ReferencedLibrariesToExclude" />
|
||||
</FilterByMetadata>
|
||||
<ItemGroup Condition=" '$(SelfContained)' != 'true' ">
|
||||
<_ReferencedLibraries Include="@(ReferencePath->'%(ResolvedPath)')" Exclude="@(_ReferencedLibrariesToExclude)" />
|
||||
<_ManagedAssembliesToLink Include="@(_ReferencedLibraries)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
|
||||
@@ -298,7 +330,7 @@
|
||||
output and the generated deps.json file. Excluding it from
|
||||
_ManagedResolvedAssembliesToPublish will prevent it from
|
||||
getting filtered out of the publish output later.
|
||||
|
||||
|
||||
In the future we may want to detect ngen assemblies and
|
||||
filter them more robustly. -->
|
||||
<!-- TODO: Which .ni files do we expect to be in
|
||||
@@ -330,12 +362,13 @@
|
||||
to work on the publish output. -->
|
||||
<Target Name="_ComputeLinkerRootAssemblies"
|
||||
DependsOnTargets="_ComputeManagedResolvedAssembliesToPublish;_ComputePlatformLibraries;_CheckSystemPrivateCorelibEmbeddedRoots">
|
||||
<!-- If RootAllApplicationAssemblies is true, roots are everything minus the framework
|
||||
assemblies. This doesn't include the intermediate assembly,
|
||||
because we root it separately using an xml file,
|
||||
which lets us explicitly root everything.
|
||||
<!-- If RootAllApplicationAssemblies is true, roots are everything
|
||||
minus the framework assemblies. This doesn't include the
|
||||
intermediate assembly, because we root it separately using an
|
||||
xml file, which lets us explicitly root everything.
|
||||
|
||||
If RootAllApplicationAssemblies is false, only intermediate assembly's Main method is rooted.
|
||||
If RootAllApplicationAssemblies is false, only intermediate
|
||||
assembly's Main method is rooted.
|
||||
|
||||
System.Private.CoreLib is rooted unless it has an embedded
|
||||
xml descriptor file. -->
|
||||
@@ -354,7 +387,7 @@
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="CheckEmbeddedRootDescriptor" AssemblyFile="$(LinkTaskDllPath)" />
|
||||
<Target Name="_CheckSystemPrivateCorelibEmbeddedRoots"
|
||||
<Target Name="_CheckSystemPrivateCorelibEmbeddedRoots" Condition=" '$(SelfContained)' == 'true' "
|
||||
DependsOnTargets="_ComputeManagedAssembliesToLink">
|
||||
<CheckEmbeddedRootDescriptor AssemblyPath="@(_ManagedAssembliesToLink->WithMetadataValue('Filename', 'System.Private.CoreLib'))">
|
||||
<Output TaskParameter="HasEmbeddedRootDescriptor" PropertyName="_SPCHasEmbeddedRootDescriptor" />
|
||||
@@ -364,13 +397,19 @@
|
||||
<!-- Platform libraries are the managed runtime assets needed by the
|
||||
"platform", currently Microsoft.NETCore.App. -->
|
||||
<UsingTask TaskName="GetRuntimeLibraries" AssemblyFile="$(LinkTaskDllPath)" />
|
||||
<Target Name="_ComputePlatformLibraries">
|
||||
<GetRuntimeLibraries AssetsFilePath="$(ProjectAssetsFile)"
|
||||
<Target Name="_ComputePlatformLibraries"
|
||||
DependsOnTargets="_ComputeManagedAssembliesToLink">
|
||||
<GetRuntimeLibraries Condition=" '$(SelfContained)' == 'true' "
|
||||
AssetsFilePath="$(ProjectAssetsFile)"
|
||||
TargetFramework="$(TargetFrameworkMoniker)"
|
||||
RuntimeIdentifier="$(RuntimeIdentifier)"
|
||||
PackageNames="$(MicrosoftNETPlatformLibrary)">
|
||||
<Output TaskParameter="RuntimeLibraries" ItemName="PlatformLibraries" />
|
||||
</GetRuntimeLibraries>
|
||||
<ItemGroup Condition=" '$(SelfContained)' != 'true' ">
|
||||
<!-- Portable publish: computed referenced-not-published set in _ComputeManagedAssembliesToLink -->
|
||||
<PlatformLibraries Include="@(_ReferencedLibraries)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
@@ -416,7 +455,7 @@
|
||||
<ItemGroup>
|
||||
<_RemovedNativeDeps Include="@(_NativeResolvedDepsToPublish)" />
|
||||
<_RemovedNativeDeps Remove="@(_NativeKeptDepsToPublish)" />
|
||||
|
||||
|
||||
<_PublishConflictPackageFiles Include="@(_RemovedManagedAssemblies)" />
|
||||
<_PublishConflictPackageFiles Include="@(_RemovedNativeDeps)" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -46,6 +46,17 @@ namespace ILLink.Tasks
|
||||
/// </summary>
|
||||
public ITaskItem [] RootDescriptorFiles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Boolean specifying whether to clear initlocals flag on methods.
|
||||
/// </summary>
|
||||
public bool ClearInitLocals { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A comma-separated list of assemblies whose methods
|
||||
/// should have initlocals flag cleared if ClearInitLocals is true.
|
||||
/// </summary>
|
||||
public string ClearInitLocalsAssemblies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Extra arguments to pass to illink, delimited by spaces.
|
||||
/// </summary>
|
||||
@@ -61,7 +72,8 @@ namespace ILLink.Tasks
|
||||
string [] args = GenerateCommandLineCommands ();
|
||||
var argsString = String.Join (" ", args);
|
||||
Log.LogMessageFromText ($"illink {argsString}", MessageImportance.Normal);
|
||||
int ret = Mono.Linker.Driver.Main (args);
|
||||
var logger = new AdapterLogger (Log);
|
||||
int ret = Mono.Linker.Driver.Execute (args, logger);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
@@ -104,6 +116,17 @@ namespace ILLink.Tasks
|
||||
args.Add (OutputDirectory.ItemSpec);
|
||||
}
|
||||
|
||||
if (ClearInitLocals) {
|
||||
args.Add ("-s");
|
||||
// Version of ILLink.CustomSteps is passed as a workaround for msbuild issue #3016
|
||||
args.Add ("ILLink.CustomSteps.ClearInitLocalsStep,ILLink.CustomSteps,Version=0.0.0.0:OutputStep");
|
||||
if ((ClearInitLocalsAssemblies != null) && (ClearInitLocalsAssemblies.Length > 0)) {
|
||||
args.Add ("-m");
|
||||
args.Add ("ClearInitLocalsAssemblies");
|
||||
args.Add (ClearInitLocalsAssemblies);
|
||||
}
|
||||
}
|
||||
|
||||
if (ExtraArgs != null) {
|
||||
args.AddRange (ExtraArgs.Split (' '));
|
||||
}
|
||||
|
||||
146
external/linker/corebuild/integration/test/CommandRunner.cs
vendored
Normal file
146
external/linker/corebuild/integration/test/CommandRunner.cs
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace ILLink.Tests
|
||||
{
|
||||
public class CommandRunner
|
||||
{
|
||||
protected readonly ITestOutputHelper outputHelper;
|
||||
|
||||
private string command;
|
||||
private string args;
|
||||
private string workingDir;
|
||||
private string additionalPath;
|
||||
private int timeout = Int32.MaxValue;
|
||||
private string terminatingOutput;
|
||||
|
||||
public CommandRunner(string command, ITestOutputHelper outputHelper) {
|
||||
this.command = command;
|
||||
this.outputHelper = outputHelper;
|
||||
}
|
||||
|
||||
public CommandRunner WithArguments(string args) {
|
||||
this.args = args;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandRunner WithWorkingDir(string workingDir) {
|
||||
this.workingDir = workingDir;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandRunner WithAdditionalPath(string additionalPath) {
|
||||
this.additionalPath = additionalPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandRunner WithTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandRunner WithTerminatingOutput(string terminatingOutput) {
|
||||
this.terminatingOutput = terminatingOutput;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int Run()
|
||||
{
|
||||
return Run(out string commandOutputUnused);
|
||||
}
|
||||
|
||||
public int Run(out string commandOutput)
|
||||
{
|
||||
if (String.IsNullOrEmpty(command)) {
|
||||
throw new Exception("No command was specified specified.");
|
||||
}
|
||||
if (outputHelper == null) {
|
||||
throw new Exception("No output helper present.");
|
||||
}
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = command,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
};
|
||||
outputHelper.WriteLine($"caller working directory: {Environment.CurrentDirectory}");
|
||||
if (!String.IsNullOrEmpty(args)) {
|
||||
psi.Arguments = args;
|
||||
outputHelper.WriteLine($"{command} {args}");
|
||||
} else {
|
||||
outputHelper.WriteLine($"{command}");
|
||||
}
|
||||
if (!String.IsNullOrEmpty(workingDir)) {
|
||||
outputHelper.WriteLine($"working directory: {workingDir}");
|
||||
psi.WorkingDirectory = workingDir;
|
||||
}
|
||||
if (!String.IsNullOrEmpty(additionalPath)) {
|
||||
string path = psi.Environment["PATH"];
|
||||
psi.Environment["PATH"] = path + ";" + additionalPath;
|
||||
}
|
||||
var process = new Process();
|
||||
process.StartInfo = psi;
|
||||
|
||||
// dotnet sets some environment variables that
|
||||
// may cause problems in the child process.
|
||||
psi.Environment.Remove("MSBuildExtensionsPath");
|
||||
psi.Environment.Remove("MSBuildLoadMicrosoftTargetsReadOnly");
|
||||
psi.Environment.Remove("MSBuildSDKsPath");
|
||||
psi.Environment.Remove("VbcToolExe");
|
||||
psi.Environment.Remove("CscToolExe");
|
||||
psi.Environment.Remove("MSBUILD_EXE_PATH");
|
||||
|
||||
outputHelper.WriteLine("environment:");
|
||||
foreach (var item in psi.Environment) {
|
||||
outputHelper.WriteLine($"\t{item.Key}={item.Value}");
|
||||
}
|
||||
|
||||
StringBuilder processOutput = new StringBuilder();
|
||||
DataReceivedEventHandler handler = (sender, e) => {
|
||||
processOutput.Append(e.Data);
|
||||
processOutput.AppendLine();
|
||||
};
|
||||
StringBuilder processError = new StringBuilder();
|
||||
DataReceivedEventHandler ehandler = (sender, e) => {
|
||||
processError.Append(e.Data);
|
||||
processError.AppendLine();
|
||||
};
|
||||
process.OutputDataReceived += handler;
|
||||
process.ErrorDataReceived += ehandler;
|
||||
|
||||
// terminate process if output contains specified string
|
||||
if (!String.IsNullOrEmpty(terminatingOutput)) {
|
||||
DataReceivedEventHandler terminatingOutputHandler = (sender, e) => {
|
||||
if (!String.IsNullOrEmpty(e.Data) && e.Data.Contains(terminatingOutput)) {
|
||||
process.Kill();
|
||||
}
|
||||
};
|
||||
process.OutputDataReceived += terminatingOutputHandler;
|
||||
}
|
||||
|
||||
// start the process
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
if (!process.WaitForExit(timeout)) {
|
||||
outputHelper.WriteLine($"killing process after {timeout} ms");
|
||||
process.Kill();
|
||||
}
|
||||
// WaitForExit with timeout doesn't guarantee
|
||||
// that the async output handlers have been
|
||||
// called, so WaitForExit needs to be called
|
||||
// afterwards.
|
||||
process.WaitForExit();
|
||||
string processOutputStr = processOutput.ToString();
|
||||
string processErrorStr = processError.ToString();
|
||||
outputHelper.WriteLine(processOutputStr);
|
||||
outputHelper.WriteLine(processErrorStr);
|
||||
commandOutput = processOutputStr;
|
||||
return process.ExitCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,21 @@ namespace ILLink.Tests
|
||||
{
|
||||
public class HelloWorldTest : IntegrationTestBase
|
||||
{
|
||||
public HelloWorldTest(ITestOutputHelper output) : base(output) {}
|
||||
private string csproj;
|
||||
|
||||
public HelloWorldTest(ITestOutputHelper output) : base(output) {
|
||||
csproj = SetupProject();
|
||||
}
|
||||
|
||||
public string SetupProject()
|
||||
{
|
||||
string projectRoot = "helloworld";
|
||||
string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj");
|
||||
|
||||
if (File.Exists(csproj)) {
|
||||
output.WriteLine($"using existing project {csproj}");
|
||||
return csproj;
|
||||
}
|
||||
|
||||
if (Directory.Exists(projectRoot)) {
|
||||
Directory.Delete(projectRoot, true);
|
||||
@@ -24,20 +34,28 @@ namespace ILLink.Tests
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj");
|
||||
AddLinkerReference(csproj);
|
||||
|
||||
return csproj;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunHelloWorld()
|
||||
public void RunHelloWorldStandalone()
|
||||
{
|
||||
string csproj = SetupProject();
|
||||
string executablePath = BuildAndLink(csproj, selfContained: true);
|
||||
CheckOutput(executablePath, selfContained: true);
|
||||
}
|
||||
|
||||
AddLinkerReference(csproj);
|
||||
[Fact]
|
||||
public void RunHelloWorldPortable()
|
||||
{
|
||||
string target = BuildAndLink(csproj, selfContained: false);
|
||||
CheckOutput(target, selfContained: false);
|
||||
}
|
||||
|
||||
BuildAndLink(csproj, null);
|
||||
|
||||
int ret = RunApp(csproj, out string commandOutput);
|
||||
void CheckOutput(string target, bool selfContained = false)
|
||||
{
|
||||
int ret = RunApp(target, out string commandOutput, selfContained: selfContained);
|
||||
Assert.True(ret == 0);
|
||||
Assert.True(commandOutput.Contains("Hello World!"));
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ILLink.Tests
|
||||
protected int Dotnet(string args, string workingDir, string additionalPath = null)
|
||||
{
|
||||
return RunCommand(Path.GetFullPath(context.DotnetToolPath), args,
|
||||
workingDir, additionalPath, out string commandOutput);
|
||||
workingDir, additionalPath, out string commandOutput);
|
||||
}
|
||||
|
||||
protected int RunCommand(string command, string args, int timeout = Int32.MaxValue)
|
||||
@@ -43,71 +43,16 @@ namespace ILLink.Tests
|
||||
return RunCommand(command, args, workingDir, null, out string commandOutput);
|
||||
}
|
||||
|
||||
protected int RunCommand(string command, string args, string workingDir, string additionalPath, out string commandOutput, int timeout = Int32.MaxValue)
|
||||
protected int RunCommand(string command, string args, string workingDir, string additionalPath,
|
||||
out string commandOutput, int timeout = Int32.MaxValue, string terminatingOutput = null)
|
||||
{
|
||||
output.WriteLine($"{command} {args}");
|
||||
if (workingDir != null)
|
||||
output.WriteLine($"working directory: {workingDir}");
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = command,
|
||||
Arguments = args,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
WorkingDirectory = workingDir,
|
||||
};
|
||||
|
||||
if (additionalPath != null) {
|
||||
string path = psi.Environment["PATH"];
|
||||
psi.Environment["PATH"] = path + ";" + additionalPath;
|
||||
}
|
||||
var process = new Process();
|
||||
process.StartInfo = psi;
|
||||
|
||||
// dotnet sets some environment variables that
|
||||
// may cause problems in the child process.
|
||||
psi.Environment.Remove("MSBuildExtensionsPath");
|
||||
psi.Environment.Remove("MSBuildLoadMicrosoftTargetsReadOnly");
|
||||
psi.Environment.Remove("MSBuildSDKsPath");
|
||||
psi.Environment.Remove("VbcToolExe");
|
||||
psi.Environment.Remove("CscToolExe");
|
||||
psi.Environment.Remove("MSBUILD_EXE_PATH");
|
||||
|
||||
StringBuilder processOutput = new StringBuilder();
|
||||
DataReceivedEventHandler handler = (sender, e) => {
|
||||
processOutput.Append(e.Data);
|
||||
processOutput.AppendLine();
|
||||
};
|
||||
StringBuilder processError = new StringBuilder();
|
||||
DataReceivedEventHandler ehandler = (sender, e) => {
|
||||
processError.Append(e.Data);
|
||||
processError.AppendLine();
|
||||
};
|
||||
process.OutputDataReceived += handler;
|
||||
process.ErrorDataReceived += ehandler;
|
||||
output.WriteLine("environment:");
|
||||
foreach (var item in psi.Environment) {
|
||||
output.WriteLine($"\t{item.Key}={item.Value}");
|
||||
}
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
if (!process.WaitForExit(timeout)) {
|
||||
output.WriteLine($"killing process after {timeout} ms");
|
||||
process.Kill();
|
||||
}
|
||||
// WaitForExit with timeout doesn't guarantee
|
||||
// that the async output handlers have been
|
||||
// called, so WaitForExit needs to be called
|
||||
// afterwards.
|
||||
process.WaitForExit();
|
||||
string processOutputStr = processOutput.ToString();
|
||||
string processErrorStr = processError.ToString();
|
||||
output.WriteLine(processOutputStr);
|
||||
output.WriteLine(processErrorStr);
|
||||
commandOutput = processOutputStr;
|
||||
return process.ExitCode;
|
||||
return (new CommandRunner(command, output))
|
||||
.WithArguments(args)
|
||||
.WithWorkingDir(workingDir)
|
||||
.WithAdditionalPath(additionalPath)
|
||||
.WithTimeout(timeout)
|
||||
.WithTerminatingOutput(terminatingOutput)
|
||||
.Run(out commandOutput);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -115,14 +60,18 @@ namespace ILLink.Tests
|
||||
/// that the project already contains a reference to the
|
||||
/// linker task package.
|
||||
/// Optionally takes a list of root descriptor files.
|
||||
/// Returns the path to the built app, either the renamed
|
||||
/// host for self-contained publish, or the dll containing
|
||||
/// the entry point.
|
||||
/// </summary>
|
||||
public void BuildAndLink(string csproj, List<string> rootFiles = null, Dictionary<string, string> extraPublishArgs = null)
|
||||
public string BuildAndLink(string csproj, List<string> rootFiles = null, Dictionary<string, string> extraPublishArgs = null, bool selfContained = false)
|
||||
{
|
||||
string rid = context.RuntimeIdentifier;
|
||||
string config = context.Configuration;
|
||||
string demoRoot = Path.GetDirectoryName(csproj);
|
||||
|
||||
string publishArgs = $"publish -r {rid} -c {config} /v:n /p:ShowLinkerSizeComparison=true";
|
||||
string publishArgs = $"publish -c {context.Configuration} /v:n /p:ShowLinkerSizeComparison=true";
|
||||
if (selfContained) {
|
||||
publishArgs += $" -r {context.RuntimeIdentifier}";
|
||||
}
|
||||
string rootFilesStr;
|
||||
if (rootFiles != null && rootFiles.Any()) {
|
||||
rootFilesStr = String.Join(";", rootFiles);
|
||||
@@ -138,28 +87,45 @@ namespace ILLink.Tests
|
||||
if (ret != 0) {
|
||||
output.WriteLine("publish failed, returning " + ret);
|
||||
Assert.True(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public int RunApp(string csproj, out string processOutput, int timeout = Int32.MaxValue)
|
||||
{
|
||||
string demoRoot = Path.GetDirectoryName(csproj);
|
||||
// detect the target framework for which the app was published
|
||||
string tfmDir = Path.Combine(demoRoot, "bin", context.Configuration);
|
||||
string tfm = Directory.GetDirectories(tfmDir).Select(p => Path.GetFileName(p)).Single();
|
||||
string executablePath = Path.Combine(tfmDir, tfm,
|
||||
context.RuntimeIdentifier, "publish",
|
||||
Path.GetFileNameWithoutExtension(csproj)
|
||||
);
|
||||
if (context.RuntimeIdentifier.Contains("win")) {
|
||||
executablePath += ".exe";
|
||||
string builtApp = Path.Combine(tfmDir, tfm);
|
||||
if (selfContained) {
|
||||
builtApp = Path.Combine(builtApp, context.RuntimeIdentifier);
|
||||
}
|
||||
Assert.True(File.Exists(executablePath));
|
||||
builtApp = Path.Combine(builtApp, "publish",
|
||||
Path.GetFileNameWithoutExtension(csproj));
|
||||
if (selfContained) {
|
||||
if (context.RuntimeIdentifier.Contains("win")) {
|
||||
builtApp += ".exe";
|
||||
}
|
||||
} else {
|
||||
builtApp += ".dll";
|
||||
}
|
||||
Assert.True(File.Exists(builtApp));
|
||||
return builtApp;
|
||||
}
|
||||
|
||||
int ret = RunCommand(executablePath, null,
|
||||
Directory.GetParent(executablePath).FullName,
|
||||
null, out processOutput, timeout);
|
||||
public int RunApp(string target, out string processOutput, int timeout = Int32.MaxValue,
|
||||
string terminatingOutput = null, bool selfContained = false)
|
||||
{
|
||||
Assert.True(File.Exists(target));
|
||||
int ret;
|
||||
if (selfContained) {
|
||||
ret = RunCommand(
|
||||
target, null,
|
||||
Directory.GetParent(target).FullName,
|
||||
null, out processOutput, timeout, terminatingOutput);
|
||||
} else {
|
||||
ret = RunCommand(
|
||||
Path.GetFullPath(context.DotnetToolPath),
|
||||
Path.GetFullPath(target),
|
||||
Directory.GetParent(target).FullName,
|
||||
null, out processOutput, timeout, terminatingOutput);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ namespace ILLink.Tests
|
||||
{
|
||||
public class MusicStoreTest : IntegrationTestBase
|
||||
{
|
||||
public MusicStoreTest(ITestOutputHelper output) : base(output) {}
|
||||
|
||||
private static List<string> rootFiles = new List<string> { "MusicStoreReflection.xml" };
|
||||
|
||||
private static string gitRepo = "http://github.com/aspnet/JitBench";
|
||||
@@ -34,40 +32,140 @@ namespace ILLink.Tests
|
||||
// The version of Microsoft.AspNetCore.All to publish with.
|
||||
private static string aspNetVersion = "2.1.0-preview1-27654";
|
||||
|
||||
[Fact]
|
||||
public void RunMusicStore()
|
||||
private static Dictionary<string, string> versionPublishArgs;
|
||||
private static Dictionary<string, string> VersionPublishArgs
|
||||
{
|
||||
string csproj = SetupProject();
|
||||
get {
|
||||
if (versionPublishArgs != null) {
|
||||
return versionPublishArgs;
|
||||
}
|
||||
versionPublishArgs = new Dictionary<string, string>();
|
||||
versionPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion);
|
||||
versionPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion);
|
||||
return versionPublishArgs;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy root files into the project directory
|
||||
string demoRoot= Path.GetDirectoryName(csproj);
|
||||
CopyRootFiles(demoRoot);
|
||||
private static string csproj;
|
||||
|
||||
// This is necessary because JitBench comes with a
|
||||
// NuGet.Config that has a <clear /> line, preventing
|
||||
// NuGet.Config sources defined in outer directories from
|
||||
// applying.
|
||||
string nugetConfig = Path.Combine("JitBench", "NuGet.config");
|
||||
AddLocalNugetFeedAfterClear(nugetConfig);
|
||||
public MusicStoreTest(ITestOutputHelper output) : base(output) {
|
||||
csproj = SetupProject();
|
||||
|
||||
AddLinkerReference(csproj);
|
||||
// MusicStore targets .NET Core 2.1, so it must be built
|
||||
// using an SDK that can target 2.1. We obtain that SDK
|
||||
// here.
|
||||
context.DotnetToolPath = ObtainSDK(context.TestBin, repoName);
|
||||
}
|
||||
|
||||
Dictionary<string, string> extraPublishArgs = new Dictionary<string, string>();
|
||||
extraPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion);
|
||||
extraPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion);
|
||||
BuildAndLink(csproj, rootFiles, extraPublishArgs);
|
||||
[Fact]
|
||||
public void RunMusicStoreStandalone()
|
||||
{
|
||||
string executablePath = BuildAndLink(csproj, rootFiles, VersionPublishArgs, selfContained: true);
|
||||
CheckOutput(executablePath, selfContained: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunMusicStorePortable()
|
||||
{
|
||||
Dictionary<string, string> extraPublishArgs = new Dictionary<string, string>(VersionPublishArgs);
|
||||
extraPublishArgs.Add("PublishWithAspNetCoreTargetManifest", "false");
|
||||
string target = BuildAndLink(csproj, null, extraPublishArgs, selfContained: false);
|
||||
CheckOutput(target, selfContained: false);
|
||||
}
|
||||
|
||||
void CheckOutput(string target, bool selfContained = false)
|
||||
{
|
||||
int ret = RunApp(target, out string commandOutput, selfContained: selfContained);
|
||||
|
||||
int ret = RunApp(csproj, out string commandOutput);
|
||||
Assert.True(commandOutput.Contains("Starting request to http://localhost:5000"));
|
||||
Assert.True(commandOutput.Contains("Response: OK"));
|
||||
Assert.True(commandOutput.Contains("Running 100 requests"));
|
||||
Assert.True(ret == 0);
|
||||
}
|
||||
|
||||
// returns path to .csproj project file
|
||||
string SetupProject()
|
||||
{
|
||||
int ret;
|
||||
string demoRoot = Path.Combine(repoName, Path.Combine("src", "MusicStore"));
|
||||
string csproj = Path.Combine(demoRoot, "MusicStore.csproj");
|
||||
|
||||
if (File.Exists(csproj)) {
|
||||
output.WriteLine($"using existing project {csproj}");
|
||||
return csproj;
|
||||
}
|
||||
|
||||
if (Directory.Exists(repoName)) {
|
||||
Directory.Delete(repoName, true);
|
||||
}
|
||||
|
||||
ret = RunCommand("git", $"clone {gitRepo} {repoName}");
|
||||
if (ret != 0) {
|
||||
output.WriteLine("git failed");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(demoRoot)) {
|
||||
output.WriteLine($"{demoRoot} does not exist");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
ret = RunCommand("git", $"checkout {gitRevision}", demoRoot);
|
||||
if (ret != 0) {
|
||||
output.WriteLine($"problem checking out revision {gitRevision}");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
// Copy root files into the project directory
|
||||
CopyRootFiles(demoRoot);
|
||||
|
||||
// This is necessary because JitBench comes with a
|
||||
// NuGet.Config that has a <clear /> line, preventing
|
||||
// NuGet.Config sources defined in outer directories from
|
||||
// applying.
|
||||
string nugetConfig = Path.Combine(repoName, "NuGet.config");
|
||||
AddLocalNugetFeedAfterClear(nugetConfig);
|
||||
|
||||
AddLinkerReference(csproj);
|
||||
|
||||
AddGlobalJson(repoName);
|
||||
|
||||
return csproj;
|
||||
}
|
||||
|
||||
void AddGlobalJson(string repoDir)
|
||||
{
|
||||
string globalJson = Path.Combine(repoDir, "global.json");
|
||||
string globalJsonContents = "{ \"sdk\": { \"version\": \"" + sdkVersion + "\" } }\n";
|
||||
File.WriteAllText(globalJson, globalJsonContents);
|
||||
}
|
||||
|
||||
|
||||
string GetDotnetToolPath(string dotnetDir)
|
||||
{
|
||||
string dotnetToolName = Directory.GetFiles(dotnetDir)
|
||||
.Select(p => Path.GetFileName(p))
|
||||
.Where(p => p.Contains("dotnet"))
|
||||
.Single();
|
||||
string dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName);
|
||||
|
||||
if (!File.Exists(dotnetToolPath)) {
|
||||
output.WriteLine("repo-local dotnet tool does not exist.");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
return dotnetToolPath;
|
||||
}
|
||||
|
||||
string ObtainSDK(string rootDir, string repoDir)
|
||||
{
|
||||
int ret;
|
||||
string dotnetDirName = ".dotnet";
|
||||
string dotnetDir = Path.Combine(rootDir, dotnetDirName);
|
||||
if (Directory.Exists(dotnetDir)) {
|
||||
return GetDotnetToolPath(dotnetDir);
|
||||
}
|
||||
|
||||
string dotnetInstall = Path.Combine(Path.GetFullPath(repoDir), "dotnet-install");
|
||||
if (context.RuntimeIdentifier.Contains("win")) {
|
||||
dotnetInstall += ".ps1";
|
||||
@@ -103,57 +201,7 @@ namespace ILLink.Tests
|
||||
}
|
||||
}
|
||||
|
||||
string dotnetDir = Path.Combine(rootDir, dotnetDirName);
|
||||
string dotnetToolName = Directory.GetFiles(dotnetDir)
|
||||
.Select(p => Path.GetFileName(p))
|
||||
.Where(p => p.Contains("dotnet"))
|
||||
.Single();
|
||||
string dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName);
|
||||
if (!File.Exists(dotnetToolPath)) {
|
||||
output.WriteLine("repo-local dotnet tool does not exist.");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
string globalJson = Path.Combine(repoDir, "global.json");
|
||||
string globalJsonContents = "{ \"sdk\": { \"version\": \"" + sdkVersion + "\" } }\n";
|
||||
File.WriteAllText(globalJson, globalJsonContents);
|
||||
|
||||
return dotnetToolPath;
|
||||
}
|
||||
|
||||
// returns path to .csproj project file
|
||||
string SetupProject()
|
||||
{
|
||||
int ret;
|
||||
if (Directory.Exists(repoName)) {
|
||||
Directory.Delete(repoName, true);
|
||||
}
|
||||
|
||||
ret = RunCommand("git", $"clone {gitRepo}");
|
||||
if (ret != 0) {
|
||||
output.WriteLine("git failed");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
string demoRoot = Path.Combine("JitBench", Path.Combine("src", "MusicStore"));
|
||||
if (!Directory.Exists(demoRoot)) {
|
||||
output.WriteLine($"{demoRoot} does not exist");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
ret = RunCommand("git", $"checkout {gitRevision}", demoRoot);
|
||||
if (ret != 0) {
|
||||
output.WriteLine($"problem checking out revision {gitRevision}");
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
// MusicStore targets .NET Core 2.1, so it must be built
|
||||
// using an SDK that can target 2.1. We obtain that SDK
|
||||
// here.
|
||||
context.DotnetToolPath = ObtainSDK(context.TestBin, repoName);
|
||||
|
||||
string csproj = Path.Combine(demoRoot, "MusicStore.csproj");
|
||||
return csproj;
|
||||
return GetDotnetToolPath(dotnetDir);
|
||||
}
|
||||
|
||||
static void CopyRootFiles(string demoRoot)
|
||||
|
||||
@@ -8,11 +8,21 @@ namespace ILLink.Tests
|
||||
{
|
||||
public class WebApiTest : IntegrationTestBase
|
||||
{
|
||||
public WebApiTest(ITestOutputHelper output) : base(output) {}
|
||||
private string csproj;
|
||||
|
||||
public WebApiTest(ITestOutputHelper output) : base(output) {
|
||||
csproj = SetupProject();
|
||||
}
|
||||
|
||||
public string SetupProject()
|
||||
{
|
||||
string projectRoot = "webapi";
|
||||
string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj");
|
||||
|
||||
if (File.Exists(csproj)) {
|
||||
output.WriteLine($"using existing project {csproj}");
|
||||
return csproj;
|
||||
}
|
||||
|
||||
if (Directory.Exists(projectRoot)) {
|
||||
Directory.Delete(projectRoot, true);
|
||||
@@ -25,7 +35,10 @@ namespace ILLink.Tests
|
||||
Assert.True(false);
|
||||
}
|
||||
|
||||
string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj");
|
||||
PreventPublishFiltering(csproj);
|
||||
|
||||
AddLinkerReference(csproj);
|
||||
|
||||
return csproj;
|
||||
}
|
||||
|
||||
@@ -49,19 +62,25 @@ namespace ILLink.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RunWebApi()
|
||||
public void RunWebApiStandalone()
|
||||
{
|
||||
string csproj = SetupProject();
|
||||
string executablePath = BuildAndLink(csproj, selfContained: true);
|
||||
CheckOutput(executablePath, selfContained: true);
|
||||
}
|
||||
|
||||
PreventPublishFiltering(csproj);
|
||||
[Fact]
|
||||
public void RunWebApiPortable()
|
||||
{
|
||||
string target = BuildAndLink(csproj, selfContained: false);
|
||||
CheckOutput(target, selfContained: false);
|
||||
}
|
||||
|
||||
AddLinkerReference(csproj);
|
||||
|
||||
BuildAndLink(csproj);
|
||||
|
||||
int ret = RunApp(csproj, out string commandOutput, 10000);
|
||||
void CheckOutput(string target, bool selfContained = false)
|
||||
{
|
||||
string terminatingOutput = "Now listening on: http://localhost:5000";
|
||||
int ret = RunApp(target, out string commandOutput, 60000, terminatingOutput, selfContained: selfContained);
|
||||
Assert.True(commandOutput.Contains("Application started. Press Ctrl+C to shut down."));
|
||||
Assert.True(commandOutput.Contains("Now listening on: http://localhost:5000"));
|
||||
Assert.True(commandOutput.Contains(terminatingOutput));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="CommandRunner.cs" />
|
||||
<Compile Include="IntegrationTestBase.cs" />
|
||||
<Compile Include="TestContext.cs" />
|
||||
<Compile Include="MusicStoreTest.cs" />
|
||||
|
||||
14
external/linker/corebuild/linker.sln
vendored
14
external/linker/corebuild/linker.sln
vendored
@@ -8,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "..\cecil\Mono
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "..\cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb", "..\cecil\symbols\mdb\Mono.Cecil.Mdb.csproj", "{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILLink.CustomSteps", "integration\ILLink.CustomSteps\ILLink.CustomSteps.csproj", "{275C1D10-168A-4AC4-8F3E-AD969F580B9C}"
|
||||
EndProject
|
||||
Global
|
||||
@@ -59,6 +61,18 @@ Global
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x64.Build.0 = netstandard_Release|x64
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x86.ActiveCfg = netstandard_Release|x86
|
||||
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x86.Build.0 = netstandard_Release|x86
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.ActiveCfg = netstandard_Debug|Any CPU
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.Build.0 = netstandard_Debug|Any CPU
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|x64.ActiveCfg = netstandard_Debug|x64
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|x64.Build.0 = netstandard_Debug|x64
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|x86.ActiveCfg = netstandard_Debug|x86
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|x86.Build.0 = netstandard_Debug|x86
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|Any CPU.ActiveCfg = netstandard_Release|Any CPU
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|Any CPU.Build.0 = netstandard_Release|Any CPU
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|x64.ActiveCfg = netstandard_Release|x64
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|x64.Build.0 = netstandard_Release|x64
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|x86.ActiveCfg = netstandard_Release|x86
|
||||
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|x86.Build.0 = netstandard_Release|x86
|
||||
{275C1D10-168A-4AC4-8F3E-AD969F580B9C}.Debug|Any CPU.ActiveCfg = illink_Debug|Any CPU
|
||||
{275C1D10-168A-4AC4-8F3E-AD969F580B9C}.Debug|Any CPU.Build.0 = illink_Debug|Any CPU
|
||||
{275C1D10-168A-4AC4-8F3E-AD969F580B9C}.Debug|x64.ActiveCfg = illink_Debug|x64
|
||||
|
||||
Reference in New Issue
Block a user