[linker] Mark protocol interfaces when using the dynamic registrar. (#5988)

* [linker] Mark protocol interfaces when using the dynamic registrar.

Fixes this monotouch-test failure when using the dynamic registrar and the
linker at the same time:

    [FAIL] RegistrarTest.TestProtocolRegistration :   UIApplicationDelegate/17669
      Expected: True
      But was:  False

* [tests] Adjust test after linker change.

All Xamarin.iOS apps will now link with QuickLook when using the dynamic
registrar, because NSUrl implements a QuickLook protocol:
fcac64ad6e/src/foundation.cs (L5445).

Adjust LinkAll_Frameworks accordingly, and add a new test that verifies that
the old behavior (not linking with QuickLook when linking all assemblies) is
still correct.
This commit is contained in:
Rolf Bjarne Kvinge 2019-05-06 13:21:02 +02:00 коммит произвёл GitHub
Родитель 72afd997d6
Коммит 682f54da87
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 17 добавлений и 0 удалений

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

@ -2078,11 +2078,21 @@ public class B
using (var mtouch = new MTouchTool ()) {
mtouch.CreateTemporaryApp ();
mtouch.Linker = MTouchLinker.LinkAll;
mtouch.CreateTemporaryCacheDirectory ();
mtouch.AssertExecute (MTouchAction.BuildSim);
var load_commands = ExecutionHelper.Execute ("otool", $"-l {StringUtils.Quote (mtouch.NativeExecutablePath)}", hide_output: true);
Asserts.DoesNotContain ("SafariServices", load_commands, "SafariServices");
Asserts.DoesNotContain ("GameController", load_commands, "GameController");
Asserts.DoesNotContain ("NewsstandKit", load_commands, "NewsstandKit");
// Try again with the static registrar
mtouch.Registrar = MTouchRegistrar.Static;
mtouch.AssertExecute (MTouchAction.BuildSim);
load_commands = ExecutionHelper.Execute ("otool", $"-l {StringUtils.Quote (mtouch.NativeExecutablePath)}", hide_output: true);
Asserts.DoesNotContain ("SafariServices", load_commands, "SafariServices");
Asserts.DoesNotContain ("GameController", load_commands, "GameController");
Asserts.DoesNotContain ("QuickLook", load_commands, "QuickLook");
Asserts.DoesNotContain ("NewsstandKit", load_commands, "NewsstandKit");
}

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

@ -270,6 +270,7 @@ namespace xharness
switch (test.TestName) {
case "monotouch-test":
// The default is to run monotouch-test with the dynamic registrar (in the simulator), so that's already covered
yield return new TestData { Variation = "Debug (LinkSdk)", Debug = true, Profiling = false, LinkMode = "LinkSdk" };
yield return new TestData { Variation = "Debug (static registrar)", MTouchExtraArgs = "--registrar:static", Debug = true, Profiling = false, Undefines = "DYNAMIC_REGISTRAR" };
yield return new TestData { Variation = "Release (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all", Debug = false, Profiling = false, LinkMode = "Full", Defines = "OPTIMIZEALL", Undefines = "DYNAMIC_REGISTRAR" };
yield return new TestData { Variation = "Debug (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all,-remove-uithread-checks", Debug = true, Profiling = false, LinkMode = "Full", Defines = "OPTIMIZEALL", Undefines = "DYNAMIC_REGISTRAR", Ignored = !IncludeAll };

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

@ -310,6 +310,12 @@ namespace Xamarin.Linker.Steps {
if (isProtocol && !IgnoreScope (type.Scope)) {
LinkContext.StoreProtocolMethods (resolvedInterfaceType);
}
} else if (LinkContext.App.Registrar == Bundler.RegistrarMode.Dynamic) {
// If we're using the dynamic registrar, we need to mark interfaces that represent protocols
// even if it doesn't look like the interfaces are used, since we need them at runtime.
var isProtocol = type.IsNSObject (LinkContext) && resolvedInterfaceType.HasCustomAttribute (LinkContext, Namespaces.Foundation, "ProtocolAttribute");
if (isProtocol)
return true;
}
return base.ShouldMarkInterfaceImplementation (type, iface, resolvedInterfaceType);