static int Fix(ApplePlatform platform, string output) { var frameworks = Frameworks.GetFrameworks(platform, false).Values.Where(v => !v.Unavailable); var sb = new StringBuilder(); #if NET sb.AppendLine("#if NET"); #else sb.AppendLine("#if !NET"); #endif sb.AppendLine("namespace ObjCRuntime {"); sb.AppendLine("\tpublic static partial class Constants {"); foreach (var grouped in frameworks.GroupBy(v => v.Version)) { sb.AppendLine($"\t\t// {platform} {grouped.Key}"); foreach (var fw in grouped.OrderBy(v => v.Name)) { sb.AppendLine($"\t\tpublic const string {fw.Namespace}Library = \"{fw.LibraryPath}\";"); } sb.AppendLine(); } sb.AppendLine("\t}"); sb.AppendLine("}"); #if NET sb.AppendLine("#endif // NET"); #else sb.AppendLine("#endif // !NET"); #endif File.WriteAllText(output, sb.ToString()); return(0); }
public void Process(LinkContext context) { var profile = (Profile.Current as BaseProfile); AssemblyDefinition assembly; if (!context.TryGetLinkedAssembly(profile.ProductAssembly, out assembly)) { return; } HashSet <string> namespaces = new HashSet <string> (); foreach (TypeDefinition type in assembly.MainModule.Types) { namespaces.Add(type.Namespace); } // Compute our map // there can be multiple namespaces for the same library var frameworks = Frameworks.GetFrameworks(((DerivedLinkContext)context).App.Platform, false); var map = new Dictionary <string, List <string> > (); foreach (var fw in frameworks.Values) { if (!map.TryGetValue(fw.LibraryPath, out var list)) { map [fw.LibraryPath] = list = new List <string> (); } list.Add(fw.Namespace); } // clean NSObject from loading them var nsobject = assembly.MainModule.GetType(Namespaces.Foundation + ".NSObject"); var nsobject_cctor = nsobject.GetTypeConstructor(); var instructions = nsobject_cctor.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { Instruction ins = instructions [i]; if (ins.OpCode.Code != Code.Ldstr) { continue; } // To be safe we only remove the ones we know about *and* // only when we know the namespace is not being used by the app // Based on the list from xamcore/src/Foundation/NSObjectMac.cs bool remove_dlopen = false; if (map.TryGetValue(ins.Operand as string, out var targetNamespaces)) { remove_dlopen = !targetNamespaces.Any(v => namespaces.Contains(v)); } #if DEBUG else { string libname = ins.Operand as string; if (libname.StartsWith("/", StringComparison.Ordinal)) { Console.WriteLine("Unprocessed library / namespace {0}", libname); } } #endif if (remove_dlopen) { FieldDefinition f = Nop(ins); if (f != null) { i += 3; nsobject.Fields.Remove(f); } } } }