|
@@ -4,7 +4,10 @@ using System.Diagnostics;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
+using Godot;
|
|
|
+using GodotTools.Core;
|
|
|
using GodotTools.Internals;
|
|
|
+using Mono.Cecil;
|
|
|
using Directory = GodotTools.Utils.Directory;
|
|
|
using File = GodotTools.Utils.File;
|
|
|
using OS = GodotTools.Utils.OS;
|
|
@@ -415,6 +418,30 @@ MONO_AOT_MODE_LAST = 1000,
|
|
|
cppCode.AppendLine($"\tmono_jit_set_aot_mode({aotModeStr});");
|
|
|
|
|
|
cppCode.AppendLine("} // gd_mono_setup_aot");
|
|
|
+
|
|
|
+ // Prevent symbols from being stripped
|
|
|
+
|
|
|
+ var symbols = CollectSymbols(assemblies);
|
|
|
+
|
|
|
+ foreach (string symbol in symbols)
|
|
|
+ {
|
|
|
+ cppCode.Append("extern void *");
|
|
|
+ cppCode.Append(symbol);
|
|
|
+ cppCode.AppendLine(";");
|
|
|
+ }
|
|
|
+
|
|
|
+ cppCode.AppendLine("__attribute__((used)) __attribute__((optnone)) static void __godot_symbol_referencer() {");
|
|
|
+ cppCode.AppendLine("\tvoid *aux;");
|
|
|
+
|
|
|
+ foreach (string symbol in symbols)
|
|
|
+ {
|
|
|
+ cppCode.Append("\taux = ");
|
|
|
+ cppCode.Append(symbol);
|
|
|
+ cppCode.AppendLine(";");
|
|
|
+ }
|
|
|
+
|
|
|
+ cppCode.AppendLine("} // __godot_symbol_referencer");
|
|
|
+
|
|
|
cppCode.AppendLine("} // extern \"C\"");
|
|
|
cppCode.AppendLine("#endif // !TARGET_OS_SIMULATOR");
|
|
|
|
|
@@ -456,13 +483,89 @@ MONO_AOT_MODE_LAST = 1000,
|
|
|
exporter.AddIosFramework("libiconv.tbd");
|
|
|
exporter.AddIosFramework("GSS.framework");
|
|
|
exporter.AddIosFramework("CFNetwork.framework");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<string> CollectSymbols(IDictionary<string, string> assemblies)
|
|
|
+ {
|
|
|
+ var symbols = new List<string>();
|
|
|
+
|
|
|
+ var resolver = new DefaultAssemblyResolver();
|
|
|
+ foreach (var searchDir in resolver.GetSearchDirectories())
|
|
|
+ resolver.RemoveSearchDirectory(searchDir);
|
|
|
+ foreach (var searchDir in assemblies
|
|
|
+ .Select(a => a.Value.GetBaseDir().NormalizePath()).Distinct())
|
|
|
+ {
|
|
|
+ resolver.AddSearchDirectory(searchDir);
|
|
|
+ }
|
|
|
+
|
|
|
+ AssemblyDefinition ReadAssembly(string fileName)
|
|
|
+ => AssemblyDefinition.ReadAssembly(fileName,
|
|
|
+ new ReaderParameters {AssemblyResolver = resolver});
|
|
|
+
|
|
|
+ foreach (var assembly in assemblies)
|
|
|
+ {
|
|
|
+ using (var assemblyDef = ReadAssembly(assembly.Value))
|
|
|
+ CollectSymbolsFromAssembly(assemblyDef, symbols);
|
|
|
+ }
|
|
|
+
|
|
|
+ return symbols;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void CollectSymbolsFromAssembly(AssemblyDefinition assembly, ICollection<string> symbols)
|
|
|
+ {
|
|
|
+ if (!assembly.MainModule.HasTypes)
|
|
|
+ return;
|
|
|
+
|
|
|
+ foreach (var type in assembly.MainModule.Types)
|
|
|
+ {
|
|
|
+ CollectSymbolsFromType(type, symbols);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void CollectSymbolsFromType(TypeDefinition type, ICollection<string> symbols)
|
|
|
+ {
|
|
|
+ if (type.HasNestedTypes)
|
|
|
+ {
|
|
|
+ foreach (var nestedType in type.NestedTypes)
|
|
|
+ CollectSymbolsFromType(nestedType, symbols);
|
|
|
+ }
|
|
|
|
|
|
- // Force load and export dynamic are needed for the linker to not strip required symbols.
|
|
|
- // In theory we shouldn't be relying on this for P/Invoked functions (as is the case with
|
|
|
- // functions in System.Native/libmono-native). Instead, we should use cecil to search for
|
|
|
- // DllImports in assemblies and pass them to 'ld' as '-u/--undefined {pinvoke_symbol}'.
|
|
|
- exporter.AddIosLinkerFlags("-rdynamic");
|
|
|
- exporter.AddIosLinkerFlags($"-force_load \"$(SRCROOT)/{MonoFrameworkFile("libmono-native")}\"");
|
|
|
+ if (type.Module.HasModuleReferences)
|
|
|
+ CollectPInvokeSymbols(type, symbols);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void CollectPInvokeSymbols(TypeDefinition type, ICollection<string> symbols)
|
|
|
+ {
|
|
|
+ if (!type.HasMethods)
|
|
|
+ return;
|
|
|
+
|
|
|
+ foreach (var method in type.Methods)
|
|
|
+ {
|
|
|
+ if (!method.IsPInvokeImpl || !method.HasPInvokeInfo)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ var pInvokeInfo = method.PInvokeInfo;
|
|
|
+
|
|
|
+ if (pInvokeInfo == null)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ switch (pInvokeInfo.Module.Name)
|
|
|
+ {
|
|
|
+ case "__Internal":
|
|
|
+ case "libSystem.Net.Security.Native":
|
|
|
+ case "System.Net.Security.Native":
|
|
|
+ case "libSystem.Security.Cryptography.Native.Apple":
|
|
|
+ case "System.Security.Cryptography.Native.Apple":
|
|
|
+ case "libSystem.Native":
|
|
|
+ case "System.Native":
|
|
|
+ case "libSystem.Globalization.Native":
|
|
|
+ case "System.Globalization.Native":
|
|
|
+ {
|
|
|
+ symbols.Add(pInvokeInfo.EntryPoint);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// Converts an assembly name to a valid symbol name in the same way the AOT compiler does
|