[dotnet] Only pass a single custom step to the linker. (#9173)

* [dotnet] Only pass a single custom step to the linker.

The linker will load the assemblies with the custom steps once per custom step
argument, which means that each step is effectively in a different assembly,
making it impossible to share state between steps.

This behavior is filed as a linker bug: https://github.com/mono/linker/issues/1314

Until this is fixed, we can just have a single step that injects all the other
steps programmatically.

* [tests] Adjust .NET tests according to new behavior.
This commit is contained in:
Rolf Bjarne Kvinge 2020-07-24 09:20:52 +02:00 коммит произвёл GitHub
Родитель 25b8cbe22b
Коммит 4a5dc20338
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 38 добавлений и 17 удалений

Просмотреть файл

@ -149,19 +149,11 @@
<_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --verbose</_ExtraTrimmerArgs>
</PropertyGroup>
<ItemGroup>
<!-- add our custom steps -->
<!-- add a custom step which inserts any other steps we need -->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)">
<BeforeStep>LoadReferencesStep</BeforeStep>
<Type>Xamarin.SetupStep</Type>
</_TrimmerCustomSteps>
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)">
<!-- At the end of the pipeline -->
<Type>Xamarin.GenerateMainStep</Type>
</_TrimmerCustomSteps>
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)">
<!-- At the end of the pipeline -->
<Type>Xamarin.GatherFrameworksStep</Type>
</_TrimmerCustomSteps>
</ItemGroup>
<!-- Create the file with our custom linker options -->

Просмотреть файл

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
@ -8,6 +9,8 @@ using Xamarin.Utils;
namespace Xamarin.Tests {
[TestFixture]
public class DotNetProjectTest {
Dictionary<string, string> verbosity = new Dictionary<string, string> { { "_BundlerVerbosity", "1" } };
string GetProjectPath (string project, string subdir = null)
{
var project_dir = Path.Combine (Configuration.SourceRoot, "tests", "dotnet", project);
@ -41,7 +44,7 @@ namespace Xamarin.Tests {
var platform = ApplePlatform.iOS;
var project_path = GetProjectPath ("MySingleView");
Clean (project_path);
var result = DotNet.AssertBuild (project_path);
var result = DotNet.AssertBuild (project_path, verbosity);
AssertThatLinkerExecuted (result);
AssertAppContents (platform, Path.Combine (Path.GetDirectoryName (project_path), "bin", "Debug", "net5.0", "ios-x64", "MySingleView.app"));
}
@ -52,7 +55,7 @@ namespace Xamarin.Tests {
var platform = ApplePlatform.MacOSX;
var project_path = GetProjectPath ("MyCocoaApp");
Clean (project_path);
var result = DotNet.AssertBuild (project_path);
var result = DotNet.AssertBuild (project_path, verbosity);
AssertThatLinkerExecuted (result);
AssertAppContents (platform, Path.Combine (Path.GetDirectoryName (project_path), "bin", "Debug", "net5.0", "osx-x64", "MyCocoaApp.app"));
}
@ -63,7 +66,7 @@ namespace Xamarin.Tests {
var platform = ApplePlatform.TVOS;
var project_path = GetProjectPath ("MyTVApp");
Clean (project_path);
var result = DotNet.AssertBuild (project_path);
var result = DotNet.AssertBuild (project_path, verbosity);
AssertThatLinkerExecuted (result);
AssertAppContents (platform, Path.Combine (Path.GetDirectoryName (project_path), "bin", "Debug", "net5.0", "tvos-x64", "MyTVApp.app"));
}
@ -73,7 +76,7 @@ namespace Xamarin.Tests {
{
var project_path = GetProjectPath ("MyWatchApp");
Clean (project_path);
var result = DotNet.AssertBuildFailure (project_path);
var result = DotNet.AssertBuildFailure (project_path, verbosity);
Assert.That (result.StandardOutput.ToString (), Does.Contain ("The specified RuntimeIdentifier 'watchos-x86' is not recognized."), "Missing runtime pack for watchOS");
}
@ -85,7 +88,7 @@ namespace Xamarin.Tests {
{
var project_path = GetProjectPath ("MyClassLibrary", platform);
Clean (project_path);
var result = DotNet.AssertBuild (project_path);
var result = DotNet.AssertBuild (project_path, verbosity);
Assert.That (result.StandardOutput.ToString (), Does.Not.Contain ("Task \"ILLink\""), "Linker executed unexpectedly.");
}
@ -93,7 +96,7 @@ namespace Xamarin.Tests {
{
var output = result.StandardOutput.ToString ();
Assert.That (output, Does.Contain ("Building target \"_RunILLink\" completely."), "Linker did not executed as expected.");
Assert.That (output, Does.Contain ("Hello SetupStep"), "Custom steps did not run as expected.");
Assert.That (output, Does.Contain ("Pipeline Steps:"), "Custom steps did not run as expected.");
}
void AssertAppContents (ApplePlatform platform, string app_directory)

Просмотреть файл

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Mono.Linker;
using Mono.Linker.Steps;
using Xamarin.Bundler;
@ -10,12 +13,35 @@ namespace Xamarin {
public class SetupStep : ConfigurationAwareStep {
List<IStep> _steps;
public List<IStep> Steps {
get {
if (_steps == null) {
var pipeline = typeof (LinkContext).GetProperty ("Pipeline").GetGetMethod ().Invoke (Context, null);
_steps = (List<IStep>) pipeline.GetType ().GetField ("_steps", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (pipeline);
}
return _steps;
}
}
protected override void Process ()
{
// This will be replaced with something more useful later.
Console.WriteLine ("Hello SetupStep");
// Don't use --custom-step to load each step, because this assembly
// is loaded into the current process once per --custom-step,
// which makes it very difficult to share state between steps.
Steps.Add (new GenerateMainStep ());
Steps.Add (new GatherFrameworksStep ());
Configuration.Write ();
if (Configuration.Verbosity > 0) {
Console.WriteLine ();
Console.WriteLine ("Pipeline Steps:");
foreach (var step in Steps) {
Console.WriteLine ($" {step}");
}
}
ErrorHelper.Platform = Configuration.Platform;
Directory.CreateDirectory (Configuration.ItemsDirectory);
Directory.CreateDirectory (Configuration.CacheDirectory);