* Pass custom steps separately from msbuild

* Remove reflection over linker pipeline

* Fix ListExportedSymbols ctor

* Add CoreTypeMapStep

* PR feedback

- Avoid unnecessary tracking of loaded assemblies
   (Use GetLoadedAssembly instead)
- Create extension method on LinkContext
   to avoid conditional code
- Rename dispatchers to reflect when they run

* Fix PreMarkDispatcher

* Fix DoneStep ordering

* Fix other order-dependent steps, test asserts

* Handle cyclic assembly references

* Simplify reference search

By using the already-loaded Assembly closure

* Fix warning number

Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>

* PR feedback

- Undo whitespace changes
- Move comment to a more appropriate place

Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
This commit is contained in:
Sven Boemer 2021-06-14 17:10:29 -07:00 коммит произвёл GitHub
Родитель 2837a9c6bb
Коммит 045ccaf3a6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 300 добавлений и 147 удалений

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

@ -317,11 +317,55 @@
<!-- Mark our entry assembly as a root assembly. --> <!-- Mark our entry assembly as a root assembly. -->
<TrimmerRootAssembly Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.Filename)' == '$(AssemblyName)' And '%(ResolvedFileToPublish.Extension)' == '.dll'" /> <TrimmerRootAssembly Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.Filename)' == '$(AssemblyName)' And '%(ResolvedFileToPublish.Extension)' == '.dll'" />
<!-- add a custom step which inserts any other steps we need --> <!--
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)"> pre-mark custom steps
<BeforeStep>MarkStep</BeforeStep> -->
<Type>Xamarin.SetupStep</Type> <!-- TODO: reverse the pre-mark steps once we get the fix from https://github.com/mono/linker/pull/2082 -->
</_TrimmerCustomSteps> <!-- TODO: these steps should probably run after mark. -->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Condition="'$(_LinkMode)' != 'None'" Type="Xamarin.Linker.Steps.PreMarkDispatcher" />
<!-- The final decision to remove/keep the dynamic registrar must be done before the linking step -->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="MonoTouch.Tuner.RegistrarRemovalTrackingStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="MonoTouch.Tuner.CoreTypeMapStep" />
<!-- Load the list of assemblies loaded by the linker. -->
<!-- This would not be needed if LinkContext.GetAssemblies () was exposed to us. -->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.CollectAssembliesStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.SetupStep" />
<!--
IMarkHandlers which run during Mark
-->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_LinkMode)' != 'None'" Type="Xamarin.Linker.Steps.PreserveBlockCodeHandler" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_LinkMode)' != 'None'" Type="Xamarin.Linker.OptimizeGeneratedCodeHandler" />
<!-- MarkDispatcher substeps will run for all marked assemblies. -->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_LinkMode)' != 'None'" Type="Xamarin.Linker.Steps.MarkDispatcher" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_LinkMode)' != 'None'" Type="Xamarin.Linker.Steps.PreserveSmartEnumConversionsHandler" />
<!--
post-sweep custom steps
-->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" AfterStep="SweepStep" Condition="'$(_LinkMode)' != 'None'" Type="Xamarin.Linker.Steps.PostSweepDispatcher" />
<!--
pre-output custom steps
-->
<!-- TODO: reverse the pre-output steps once we get the fix from https://github.com/mono/linker/pull/2082 -->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="OutputStep" Type="Xamarin.Linker.Steps.PreOutputDispatcher" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="OutputStep" Type="Xamarin.Linker.ExtractBindingLibrariesStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="OutputStep" Type="Xamarin.Linker.LoadNonSkippedAssembliesStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="OutputStep" Type="Xamarin.Linker.Steps.ListExportedSymbols" />
<!--
post-output steps
-->
<!-- TODO: remove AfterStep="OutputStep" from the post-output steps once we get the fix from https://github.com/mono/linker/pull/2082 -->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" AfterStep="OutputStep" Type="Xamarin.Linker.RegistrarStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" AfterStep="OutputStep" Type="Xamarin.GenerateMainStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" AfterStep="OutputStep" Type="Xamarin.GenerateReferencesStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" AfterStep="OutputStep" Type="Xamarin.GatherFrameworksStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" AfterStep="OutputStep" Type="Xamarin.Linker.ComputeNativeBuildFlagsStep" />
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" AfterStep="OutputStep" Type="Xamarin.Linker.ComputeAOTArguments" />
<!-- Must be the last step. -->
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" AfterStep="OutputStep" Type="Xamarin.Linker.DoneStep" />
<!-- _BundlerXmlDefinitions comes from any -xml arguments to mtouch/mmp --> <!-- _BundlerXmlDefinitions comes from any -xml arguments to mtouch/mmp -->
<TrimmerRootDescriptor Include="@(_BundlerXmlDefinitions)" /> <TrimmerRootDescriptor Include="@(_BundlerXmlDefinitions)" />

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

@ -443,14 +443,14 @@ namespace Xamarin.Tests {
{ {
var output = BinLog.PrintToString (result.BinLogPath); var output = BinLog.PrintToString (result.BinLogPath);
Assert.That (output, Does.Contain ("Building target \"_RunILLink\" completely."), "Linker did not executed as expected."); Assert.That (output, Does.Contain ("Building target \"_RunILLink\" completely."), "Linker did not executed as expected.");
Assert.That (output, Does.Contain ("Pipeline Steps:"), "Custom steps did not run as expected."); Assert.That (output, Does.Contain ("LinkerConfiguration:"), "Custom steps did not run as expected.");
} }
void AssertThatLinkerDidNotExecute (ExecutionResult result) void AssertThatLinkerDidNotExecute (ExecutionResult result)
{ {
var output = BinLog.PrintToString (result.BinLogPath); var output = BinLog.PrintToString (result.BinLogPath);
Assert.That (output, Does.Not.Contain ("Building target \"_RunILLink\" completely."), "Linker did not executed as expected."); Assert.That (output, Does.Not.Contain ("Building target \"_RunILLink\" completely."), "Linker did not executed as expected.");
Assert.That (output, Does.Not.Contain ("Pipeline Steps:"), "Custom steps did not run as expected."); Assert.That (output, Does.Not.Contain ("LinkerConfiguration:"), "Custom steps did not run as expected.");
} }
void AssertAppContents (ApplePlatform platform, string app_directory) void AssertAppContents (ApplePlatform platform, string app_directory)

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

@ -0,0 +1,32 @@
using Mono.Cecil;
using Mono.Linker;
using Mono.Tuner;
using System;
namespace Xamarin.Linker {
public static class Extensions {
public static bool Inherits (this TypeReference self, string @namespace, string name, IMetadataResolver resolver)
{
if (@namespace == null)
throw new ArgumentNullException ("namespace");
if (name == null)
throw new ArgumentNullException ("name");
if (self == null)
return false;
TypeReference current = resolver.Resolve (self);
while (current != null) {
if (current.Is (@namespace, name))
return true;
if (current.Is ("System", "Object"))
return false;
TypeDefinition td = resolver.Resolve (current);
if (td == null)
return false; // could not resolve type
current = td.BaseType;
}
return false;
}
}
}

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

@ -17,129 +17,12 @@ namespace Xamarin {
protected override string Name { get; } = "Setup"; protected override string Name { get; } = "Setup";
protected override int ErrorCode { get; } = 2300; protected override int ErrorCode { get; } = 2300;
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;
}
}
List<IMarkHandler> _markHandlers;
List<IMarkHandler> MarkHandlers {
get {
if (_markHandlers == null) {
var pipeline = typeof (LinkContext).GetProperty ("Pipeline").GetGetMethod ().Invoke (Context, null);
_markHandlers = (List<IMarkHandler>) pipeline.GetType ().GetProperty ("MarkHandlers").GetValue (pipeline);
}
return _markHandlers;
}
}
void InsertBefore (IStep step, string stepName)
{
for (int i = 0; i < Steps.Count; i++) {
if (Steps [i].GetType ().Name == stepName) {
Steps.Insert (i, step);
return;
}
}
DumpSteps ();
throw new InvalidOperationException ($"Could not insert {step} before {stepName} because {stepName} wasn't found.");
}
void InsertAfter (IStep step, string stepName)
{
for (int i = 0; i < Steps.Count;) {
if (Steps [i++].GetType ().Name == stepName) {
Steps.Insert (i, step);
return;
}
}
DumpSteps ();
throw new InvalidOperationException ($"Could not insert {step} after {stepName} because {stepName} wasn't found.");
}
protected override void TryProcess () protected override void TryProcess ()
{ {
// 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.
// Load the list of assemblies loaded by the linker.
// This would not be needed of LinkContext.GetAssemblies () was exposed to us.
InsertBefore (new CollectAssembliesStep (), "MarkStep");
// the final decision to remove/keep the dynamic registrar must be done before the linking step
InsertBefore (new RegistrarRemovalTrackingStep (), "MarkStep");
var pre_mark_substeps = new DotNetSubStepDispatcher ();
InsertBefore (pre_mark_substeps, "MarkStep");
var post_sweep_substeps = new DotNetSubStepDispatcher ();
InsertAfter (post_sweep_substeps, "SweepStep");
if (Configuration.LinkMode != LinkMode.None) {
MarkHandlers.Add (new PreserveBlockCodeHandler ());
// We need to run the ApplyPreserveAttribute step even we're only linking sdk assemblies, because even
// though we know that sdk assemblies will never have Preserve attributes, user assemblies may have
// [assembly: LinkSafe] attributes, which means we treat them as sdk assemblies and those may have
// Preserve attributes.
MarkHandlers.Add (new DotNetMarkAssemblySubStepDispatcher (new ApplyPreserveAttribute ()));
MarkHandlers.Add (new OptimizeGeneratedCodeHandler ());
MarkHandlers.Add (new DotNetMarkAssemblySubStepDispatcher (new MarkNSObjects ()));
MarkHandlers.Add (new PreserveSmartEnumConversionsHandler ());
// This step could be run after Mark to avoid tracking all members:
// https://github.com/xamarin/xamarin-macios/issues/11447
pre_mark_substeps.Add (new CollectUnmarkedMembersSubStep ());
pre_mark_substeps.Add (new StoreAttributesStep ());
post_sweep_substeps.Add (new RemoveAttributesStep ());
}
InsertBefore (new ListExportedSymbols (null), "OutputStep");
InsertBefore (new LoadNonSkippedAssembliesStep (), "OutputStep");
InsertBefore (new ExtractBindingLibrariesStep (), "OutputStep");
InsertBefore (new DotNetSubStepDispatcher (new RemoveUserResourcesSubStep ()), "OutputStep");
Steps.Add (new RegistrarStep ());
Steps.Add (new GenerateMainStep ());
Steps.Add (new GenerateReferencesStep ());
Steps.Add (new GatherFrameworksStep ());
Steps.Add (new ComputeNativeBuildFlagsStep ());
Steps.Add (new ComputeAOTArguments ());
Steps.Add (new DoneStep ()); // Must be the last step.
Configuration.Write (); Configuration.Write ();
if (Configuration.Verbosity > 0) {
DumpSteps ();
}
ErrorHelper.Platform = Configuration.Platform; ErrorHelper.Platform = Configuration.Platform;
Directory.CreateDirectory (Configuration.ItemsDirectory); Directory.CreateDirectory (Configuration.ItemsDirectory);
Directory.CreateDirectory (Configuration.CacheDirectory); Directory.CreateDirectory (Configuration.CacheDirectory);
} }
void DumpSteps ()
{
Console.WriteLine ();
Console.WriteLine ("Pipeline Steps:");
foreach (var step in Steps) {
Console.WriteLine ($" {step}");
if (step is SubStepsDispatcher) {
var substeps = typeof (SubStepsDispatcher).GetField ("substeps", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue (step) as IEnumerable<ISubStep>;
if (substeps != null) {
foreach (var substep in substeps) {
Console.WriteLine ($" {substep}");
}
}
}
}
}
} }
} }

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

@ -1,11 +0,0 @@
using Mono.Linker.Steps;
namespace Xamarin.Linker.Steps {
// MarkSubStepsDispatcher is abstract, so create a subclass we can instantiate.
// Can be removed when we update to the preview4 linker, which makes MarkSubStepsDispatcher non-abstract.
class DotNetMarkAssemblySubStepDispatcher : MarkSubStepsDispatcher {
public DotNetMarkAssemblySubStepDispatcher (params BaseSubStep[] subSteps) : base (subSteps)
{
}
}
}

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

@ -0,0 +1,14 @@
using Mono.Linker.Steps;
using Xamarin.Linker;
namespace Xamarin.Linker.Steps {
class MarkDispatcher : MarkSubStepsDispatcher {
public MarkDispatcher ()
: base (new BaseSubStep[] {
new ApplyPreserveAttribute (),
new MarkNSObjects ()
})
{
}
}
}

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

@ -0,0 +1,11 @@
using Mono.Linker.Steps;
using Xamarin.Linker;
namespace Xamarin.Linker.Steps {
class PostSweepDispatcher : SubStepsDispatcher {
public PostSweepDispatcher ()
: base (new [] { new RemoveAttributesStep () })
{
}
}
}

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

@ -0,0 +1,14 @@
using Mono.Linker.Steps;
using Xamarin.Linker;
namespace Xamarin.Linker.Steps {
class PreMarkDispatcher : SubStepsDispatcher {
public PreMarkDispatcher ()
: base (new BaseSubStep [] {
new CollectUnmarkedMembersSubStep (),
new StoreAttributesStep ()
})
{
}
}
}

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

@ -0,0 +1,11 @@
using Mono.Linker.Steps;
using Xamarin.Linker;
namespace Xamarin.Linker.Steps {
class PreOutputDispatcher : SubStepsDispatcher {
public PreOutputDispatcher ()
: base (new [] { new RemoveUserResourcesSubStep () })
{
}
}
}

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

@ -106,6 +106,9 @@
<Compile Include="..\linker\CoreOptimizeGeneratedCode.cs"> <Compile Include="..\linker\CoreOptimizeGeneratedCode.cs">
<Link>external\tools\linker\CoreOptimizeGeneratedCode.cs</Link> <Link>external\tools\linker\CoreOptimizeGeneratedCode.cs</Link>
</Compile> </Compile>
<Compile Include="..\linker\CoreTypeMapStep.cs">
<Link>external\tools\linker\CoreTypeMapStep.cs</Link>
</Compile>
<Compile Include="..\..\src\ObjCRuntime\Registrar.cs"> <Compile Include="..\..\src\ObjCRuntime\Registrar.cs">
<Link>external\src\ObjCRuntime\Registrar.cs</Link> <Link>external\src\ObjCRuntime\Registrar.cs</Link>
</Compile> </Compile>

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

@ -17,6 +17,10 @@ namespace Xamarin.Linker.Steps {
HashSet<TypeDefinition> preserve_synonyms; HashSet<TypeDefinition> preserve_synonyms;
#endif #endif
// We need to run the ApplyPreserveAttribute step even if we're only linking sdk assemblies, because even
// though we know that sdk assemblies will never have Preserve attributes, user assemblies may have
// [assembly: LinkSafe] attributes, which means we treat them as sdk assemblies and those may have
// Preserve attributes.
public override bool IsActiveFor (AssemblyDefinition assembly) public override bool IsActiveFor (AssemblyDefinition assembly)
{ {
return Annotations.GetAction (assembly) == AssemblyAction.Link; return Annotations.GetAction (assembly) == AssemblyAction.Link;

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

@ -9,6 +9,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using Mono.Cecil; using Mono.Cecil;
using Mono.Linker.Steps; using Mono.Linker.Steps;
@ -20,27 +21,152 @@ using Xamarin.Tuner;
namespace MonoTouch.Tuner { namespace MonoTouch.Tuner {
// This class is shared between Xamarin.Mac and Xamarin.iOS // This class is shared between Xamarin.Mac and Xamarin.iOS
public class CoreTypeMapStep : TypeMapStep { public class CoreTypeMapStep :
HashSet<TypeDefinition> cached_isnsobject = new HashSet<TypeDefinition> (); #if NET
Dictionary<TypeDefinition, bool?> isdirectbinding_value = new Dictionary<TypeDefinition, bool?> (); ConfigurationAwareStep
#else
TypeMapStep
#endif
{
#if NET
protected override string Name { get; } = "CoreTypeMap";
protected override int ErrorCode { get; } = 2390;
Profile Profile => new Profile (Configuration);
// Get the reverse mapping from assemblies to assemblies which reference them directly.
Dictionary<AssemblyDefinition, HashSet<AssemblyDefinition>> _reversedReferences;
Dictionary<AssemblyDefinition, HashSet<AssemblyDefinition>> GetReversedReferences ()
{
if (_reversedReferences != null)
return _reversedReferences;
_reversedReferences = new Dictionary<AssemblyDefinition, HashSet<AssemblyDefinition>> ();
foreach (var assembly in Configuration.Assemblies) {
if (!_reversedReferences.ContainsKey (assembly))
_reversedReferences.Add (assembly, new HashSet<AssemblyDefinition> ());
foreach (var reference in assembly.MainModule.AssemblyReferences) {
var resolvedReference = Configuration.Context.GetLoadedAssembly (reference.Name);
if (resolvedReference == null)
continue;
if (!_reversedReferences.TryGetValue (resolvedReference, out var referrers)) {
referrers = new HashSet<AssemblyDefinition> ();
_reversedReferences.Add (resolvedReference, referrers);
}
referrers.Add (assembly);
}
}
return _reversedReferences;
}
Dictionary<AssemblyDefinition, bool> _transitivelyReferencesProduct;
bool TransitivelyReferencesProduct (AssemblyDefinition assembly)
{
if (_transitivelyReferencesProduct != null) {
Debug.Assert (_transitivelyReferencesProduct.ContainsKey (assembly));
return _transitivelyReferencesProduct.TryGetValue (assembly, out bool result) && result;
}
_transitivelyReferencesProduct = new Dictionary<AssemblyDefinition, bool> ();
// A depth-first search is insufficient because there are reference cycles, so we
// get the set of transitive references, and do a reverse BFS.
var reversedReferences = GetReversedReferences ();
Debug.Assert (reversedReferences.ContainsKey (assembly));
var referencesProductToProcess = new Queue<AssemblyDefinition> ();
// We start the BFS from the product assembly.
foreach (var reference in reversedReferences.Keys) {
if (Profile.IsProductAssembly (reference)) {
_transitivelyReferencesProduct.Add (reference, true);
referencesProductToProcess.Enqueue (reference);
}
}
// Scan the reverse references to find out which referencing assemblies
// are reachable from the product assembly (that is, transitively reference the product).
while (referencesProductToProcess.TryDequeue (out var reference)) {
foreach (var referrer in reversedReferences[reference]) {
if (_transitivelyReferencesProduct.TryGetValue (referrer, out bool referencesProduct)) {
Debug.Assert (referencesProduct);
// Any which were already determined to reference the product assembly
// don't need to be scanned again.
continue;
}
_transitivelyReferencesProduct.Add (referrer, true);
referencesProductToProcess.Enqueue (referrer);
}
}
// Any remaining references that we didn't discover during the search
// don't reference the product assembly.
foreach (var reference in reversedReferences.Keys)
_transitivelyReferencesProduct.TryAdd (reference, false);
return _transitivelyReferencesProduct[assembly];
}
protected override void TryProcessAssembly (AssemblyDefinition assembly)
{
// We are only interested in types transitively derived from NSObject,
// which lives in the product assembly.
if (!TransitivelyReferencesProduct (assembly))
return;
foreach (var type in assembly.MainModule.Types)
ProcessType (type);
}
void ProcessType (TypeDefinition type)
{
MapType (type);
if (!type.HasNestedTypes)
return;
foreach (var nestedType in type.NestedTypes)
ProcessType (nestedType);
}
DerivedLinkContext LinkContext => Configuration.DerivedLinkContext;
#else
DerivedLinkContext LinkContext { DerivedLinkContext LinkContext {
get { get {
return (DerivedLinkContext) base.Context; return (DerivedLinkContext) base.Context;
} }
} }
#endif
HashSet<TypeDefinition> cached_isnsobject = new HashSet<TypeDefinition> ();
Dictionary<TypeDefinition, bool?> isdirectbinding_value = new Dictionary<TypeDefinition, bool?> ();
#if NET
protected override void TryEndProcess ()
{
#else
protected override void EndProcess () protected override void EndProcess ()
{ {
base.EndProcess (); base.EndProcess ();
#endif
LinkContext.CachedIsNSObject = cached_isnsobject; LinkContext.CachedIsNSObject = cached_isnsobject;
LinkContext.IsDirectBindingValue = isdirectbinding_value; LinkContext.IsDirectBindingValue = isdirectbinding_value;
} }
protected override void MapType (TypeDefinition type) protected
#if !NET
override
#endif
void MapType (TypeDefinition type)
{ {
#if !NET
base.MapType (type); base.MapType (type);
#endif
// additional checks for NSObject to check if the type is a *generated* bindings // additional checks for NSObject to check if the type is a *generated* bindings
// bonus: we cache, for every type, whether or not it inherits from NSObject (very useful later) // bonus: we cache, for every type, whether or not it inherits from NSObject (very useful later)
@ -77,7 +203,7 @@ namespace MonoTouch.Tuner {
bool rv; bool rv;
if (!ci_filter_types.TryGetValue (type, out rv)) { if (!ci_filter_types.TryGetValue (type, out rv)) {
rv = type.Is (Namespaces.CoreImage, "CIFilter") || IsCIFilter (type.Resolve ().BaseType); rv = type.Is (Namespaces.CoreImage, "CIFilter") || IsCIFilter (Context.Resolve (type).BaseType);
ci_filter_types [type] = rv; ci_filter_types [type] = rv;
} }
return rv; return rv;
@ -97,10 +223,10 @@ namespace MonoTouch.Tuner {
// * https://bugzilla.xamarin.com/show_bug.cgi?id=15465 // * https://bugzilla.xamarin.com/show_bug.cgi?id=15465
if (IsCIFilter (type)) { if (IsCIFilter (type)) {
isdirectbinding_value [type] = null; isdirectbinding_value [type] = null;
var base_type = type.BaseType.Resolve (); var base_type = Context.Resolve (type.BaseType);
while (base_type != null && IsNSObject (base_type)) { while (base_type != null && IsNSObject (base_type)) {
isdirectbinding_value [base_type] = null; isdirectbinding_value [base_type] = null;
base_type = base_type.BaseType.Resolve (); base_type = Context.Resolve (base_type.BaseType);
} }
return; return;
} }
@ -111,11 +237,11 @@ namespace MonoTouch.Tuner {
isdirectbinding_value [type] = false; isdirectbinding_value [type] = false;
// We must clear IsDirectBinding for any wrapper superclasses. // We must clear IsDirectBinding for any wrapper superclasses.
var base_type = type.BaseType.Resolve (); var base_type = Context.Resolve (type.BaseType);
while (base_type != null && IsNSObject (base_type)) { while (base_type != null && IsNSObject (base_type)) {
if (IsWrapperType (base_type)) if (IsWrapperType (base_type))
isdirectbinding_value [base_type] = null; isdirectbinding_value [base_type] = null;
base_type = base_type.BaseType.Resolve (); base_type = Context.Resolve (base_type.BaseType);
} }
} else { } else {
isdirectbinding_value [type] = true; // Let's try 'true' first, any derived non-wrapper classes will clear it if needed isdirectbinding_value [type] = true; // Let's try 'true' first, any derived non-wrapper classes will clear it if needed

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

@ -85,7 +85,6 @@ namespace Xamarin.Linker.Steps {
continue; continue;
// not optimal if "Link all" is used as the override might be removed later // not optimal if "Link all" is used as the override might be removed later
// this may miss some overrides with the .NET6 linker (https://github.com/xamarin/xamarin-macios/issues/11449)
if (!IsOverridenInUserCode (method)) if (!IsOverridenInUserCode (method))
continue; continue;

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

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Mono.Cecil; using Mono.Cecil;
using Mono.Linker;
using Mono.Tuner; using Mono.Tuner;
@ -21,5 +22,13 @@ namespace MonoTouch.Tuner {
return null; return null;
} }
// Extension method to avoid conditional code for files shared between
// .NET linker and Legacy (where LinkContext doesn't implement IMetadataResolver).
// This doesn't actually use the LinkContext.
public static TypeDefinition Resolve (this LinkContext context, TypeReference type)
{
return type.Resolve ();
}
} }
} }

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

@ -28,6 +28,10 @@ namespace Xamarin.Linker.Steps
} }
} }
public ListExportedSymbols () : this (null)
{
}
internal ListExportedSymbols (PInvokeWrapperGenerator state, bool skip_sdk_assemblies = false) internal ListExportedSymbols (PInvokeWrapperGenerator state, bool skip_sdk_assemblies = false)
{ {
this.state = state; this.state = state;

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

@ -84,7 +84,13 @@ namespace Xamarin.Linker {
const string INativeObject = Namespaces.ObjCRuntime + ".INativeObject"; const string INativeObject = Namespaces.ObjCRuntime + ".INativeObject";
public static bool IsNSObject (this TypeReference type, DerivedLinkContext link_context) public static bool IsNSObject (this TypeReference type, DerivedLinkContext link_context)
{ {
return type.Resolve ().IsNSObject (link_context); return
#if NET
link_context.LinkerConfiguration.Context.Resolve (type)
#else
type.Resolve ()
#endif
.IsNSObject (link_context);
} }
// warning: *Is* means does 'type' inherits from MonoTouch.Foundation.NSObject ? // warning: *Is* means does 'type' inherits from MonoTouch.Foundation.NSObject ?
@ -93,7 +99,11 @@ namespace Xamarin.Linker {
if (link_context?.CachedIsNSObject != null) if (link_context?.CachedIsNSObject != null)
return link_context.CachedIsNSObject.Contains (type); return link_context.CachedIsNSObject.Contains (type);
return type.Inherits (Namespaces.Foundation, "NSObject"); return type.Inherits (Namespaces.Foundation, "NSObject"
#if NET
, link_context.LinkerConfiguration.Context
#endif
);
} }
public static bool IsNativeObject (this TypeDefinition type) public static bool IsNativeObject (this TypeDefinition type)