|
@@ -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;
|
|
@@ -22,7 +25,12 @@ namespace GodotTools.Export
|
|
|
public bool FullAot;
|
|
|
|
|
|
private bool _useInterpreter;
|
|
|
- public bool UseInterpreter { get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; }
|
|
|
+
|
|
|
+ public bool UseInterpreter
|
|
|
+ {
|
|
|
+ get => _useInterpreter && !LLVMOnly;
|
|
|
+ set => _useInterpreter = value;
|
|
|
+ }
|
|
|
|
|
|
public string[] ExtraAotOptions;
|
|
|
public string[] ExtraOptimizerOptions;
|
|
@@ -82,7 +90,6 @@ namespace GodotTools.Export
|
|
|
|
|
|
public static void CompileAssembliesForAndroid(ExportPlugin exporter, bool isDebug, string[] abis, AotOptions aotOpts, string aotTempDir, IDictionary<string, string> assemblies, string bclDir)
|
|
|
{
|
|
|
-
|
|
|
foreach (var assembly in assemblies)
|
|
|
{
|
|
|
string assemblyName = assembly.Key;
|
|
@@ -107,7 +114,7 @@ namespace GodotTools.Export
|
|
|
ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir);
|
|
|
|
|
|
// The Godot exporter expects us to pass the abi in the tags parameter
|
|
|
- exporter.AddSharedObject(soFilePath, tags: new[] { abi });
|
|
|
+ exporter.AddSharedObject(soFilePath, tags: new[] {abi});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -146,11 +153,101 @@ namespace GodotTools.Export
|
|
|
|
|
|
public static void CompileAssembliesForiOS(ExportPlugin exporter, bool isDebug, string[] architectures, AotOptions aotOpts, string aotTempDir, IDictionary<string, string> assemblies, string bclDir)
|
|
|
{
|
|
|
+ void RunAr(IEnumerable<string> objFilePaths, string outputFilePath)
|
|
|
+ {
|
|
|
+ var arArgs = new List<string>()
|
|
|
+ {
|
|
|
+ "cr",
|
|
|
+ outputFilePath
|
|
|
+ };
|
|
|
+
|
|
|
+ foreach (string objFilePath in objFilePaths)
|
|
|
+ arArgs.Add(objFilePath);
|
|
|
+
|
|
|
+ int arExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("ar"), arArgs);
|
|
|
+ if (arExitCode != 0)
|
|
|
+ throw new Exception($"Command 'ar' exited with code: {arExitCode}");
|
|
|
+ }
|
|
|
+
|
|
|
+ void RunLipo(IEnumerable<string> libFilePaths, string outputFilePath)
|
|
|
+ {
|
|
|
+ var lipoArgs = new List<string>();
|
|
|
+ lipoArgs.Add("-create");
|
|
|
+ lipoArgs.AddRange(libFilePaths);
|
|
|
+ lipoArgs.Add("-output");
|
|
|
+ lipoArgs.Add(outputFilePath);
|
|
|
+
|
|
|
+ int lipoExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("lipo"), lipoArgs);
|
|
|
+ if (lipoExitCode != 0)
|
|
|
+ throw new Exception($"Command 'lipo' exited with code: {lipoExitCode}");
|
|
|
+ }
|
|
|
+
|
|
|
+ void CreateDummyLibForSimulator(string name, string xcFrameworkPath = null)
|
|
|
+ {
|
|
|
+ xcFrameworkPath = xcFrameworkPath ?? MonoFrameworkFromTemplate(name);
|
|
|
+ string simulatorSubDir = Path.Combine(xcFrameworkPath, "ios-arm64_x86_64-simulator");
|
|
|
+
|
|
|
+ string libFilePath = Path.Combine(simulatorSubDir, name + ".a");
|
|
|
+
|
|
|
+ if (File.Exists(libFilePath))
|
|
|
+ return;
|
|
|
+
|
|
|
+ string CompileForArch(string arch)
|
|
|
+ {
|
|
|
+ string baseFilePath = Path.Combine(aotTempDir, $"{name}.{arch}");
|
|
|
+ string sourceFilePath = baseFilePath + ".c";
|
|
|
+
|
|
|
+ string source = $"int _{AssemblyNameToAotSymbol(name)}() {{ return 0; }}\n";
|
|
|
+ File.WriteAllText(sourceFilePath, source);
|
|
|
+
|
|
|
+ const string iOSPlatformName = "iPhoneSimulator";
|
|
|
+ const string versionMin = "10.0";
|
|
|
+ string iOSSdkPath = Path.Combine(XcodeHelper.XcodePath,
|
|
|
+ $"Contents/Developer/Platforms/{iOSPlatformName}.platform/Developer/SDKs/{iOSPlatformName}.sdk");
|
|
|
+
|
|
|
+ string objFilePath = baseFilePath + ".o";
|
|
|
+
|
|
|
+ var clangArgs = new[]
|
|
|
+ {
|
|
|
+ "-isysroot", iOSSdkPath,
|
|
|
+ $"-miphonesimulator-version-min={versionMin}",
|
|
|
+ "-arch", arch,
|
|
|
+ "-c",
|
|
|
+ "-o", objFilePath,
|
|
|
+ sourceFilePath
|
|
|
+ };
|
|
|
+
|
|
|
+ int clangExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("clang"), clangArgs);
|
|
|
+ if (clangExitCode != 0)
|
|
|
+ throw new Exception($"Command 'clang' exited with code: {clangExitCode}");
|
|
|
+
|
|
|
+ string arOutputFilePath = Path.Combine(aotTempDir, baseFilePath + ".a");
|
|
|
+ RunAr(new[] {objFilePath}, arOutputFilePath);
|
|
|
+
|
|
|
+ return arOutputFilePath;
|
|
|
+ }
|
|
|
+
|
|
|
+ RunLipo(new[] {CompileForArch("arm64"), CompileForArch("x86_64")}, libFilePath);
|
|
|
+ }
|
|
|
+
|
|
|
+ string projectAssemblyName = GodotSharpEditor.ProjectAssemblyName;
|
|
|
+ string libAotName = $"lib-aot-{projectAssemblyName}";
|
|
|
+
|
|
|
+ string libAotXcFrameworkPath = Path.Combine(aotTempDir, $"{libAotName}.xcframework");
|
|
|
+ string libAotXcFrameworkDevicePath = Path.Combine(libAotXcFrameworkPath, "ios-arm64");
|
|
|
+ string libAotXcFrameworkSimPath = Path.Combine(libAotXcFrameworkPath, "ios-arm64_x86_64-simulator");
|
|
|
+
|
|
|
+ Directory.CreateDirectory(libAotXcFrameworkPath);
|
|
|
+ Directory.CreateDirectory(libAotXcFrameworkDevicePath);
|
|
|
+ Directory.CreateDirectory(libAotXcFrameworkSimPath);
|
|
|
+
|
|
|
+ string libAotFileName = $"{libAotName}.a";
|
|
|
+ string libAotFilePath = Path.Combine(libAotXcFrameworkDevicePath, libAotFileName);
|
|
|
+
|
|
|
var cppCode = new StringBuilder();
|
|
|
var aotModuleInfoSymbols = new List<string>(assemblies.Count);
|
|
|
|
|
|
- // {arch: paths}
|
|
|
- var objFilePathsForiOSArch = architectures.ToDictionary(arch => arch, arch => new List<string>(assemblies.Count));
|
|
|
+ var aotObjFilePaths = new List<string>(assemblies.Count);
|
|
|
|
|
|
foreach (var assembly in assemblies)
|
|
|
{
|
|
@@ -160,36 +257,29 @@ namespace GodotTools.Export
|
|
|
string asmFileName = assemblyName + ".dll.S";
|
|
|
string objFileName = assemblyName + ".dll.o";
|
|
|
|
|
|
- foreach (string arch in architectures)
|
|
|
{
|
|
|
- string aotArchTempDir = Path.Combine(aotTempDir, arch);
|
|
|
- string asmFilePath = Path.Combine(aotArchTempDir, asmFileName);
|
|
|
+ string asmFilePath = Path.Combine(aotTempDir, asmFileName);
|
|
|
|
|
|
- var compilerArgs = GetAotCompilerArgs(OS.Platforms.iOS, isDebug, arch, aotOpts, assemblyPath, asmFilePath);
|
|
|
-
|
|
|
- // Make sure the output directory exists
|
|
|
- Directory.CreateDirectory(aotArchTempDir);
|
|
|
+ var compilerArgs = GetAotCompilerArgs(OS.Platforms.iOS, isDebug, "arm64", aotOpts, assemblyPath, asmFilePath);
|
|
|
|
|
|
- string compilerDirPath = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "aot-compilers", $"{OS.Platforms.iOS}-{arch}");
|
|
|
+ string compilerDirPath = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "aot-compilers", $"{OS.Platforms.iOS}-arm64");
|
|
|
|
|
|
ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir);
|
|
|
|
|
|
// Assembling
|
|
|
- bool isSim = arch == "i386" || arch == "x86_64"; // Shouldn't really happen as we don't do AOT for the simulator
|
|
|
- string versionMinName = isSim ? "iphonesimulator" : "iphoneos";
|
|
|
- string iOSPlatformName = isSim ? "iPhoneSimulator" : "iPhoneOS";
|
|
|
+ const string iOSPlatformName = "iPhoneOS";
|
|
|
const string versionMin = "10.0"; // TODO: Turn this hard-coded version into an exporter setting
|
|
|
string iOSSdkPath = Path.Combine(XcodeHelper.XcodePath,
|
|
|
- $"Contents/Developer/Platforms/{iOSPlatformName}.platform/Developer/SDKs/{iOSPlatformName}.sdk");
|
|
|
+ $"Contents/Developer/Platforms/{iOSPlatformName}.platform/Developer/SDKs/{iOSPlatformName}.sdk");
|
|
|
|
|
|
- string objFilePath = Path.Combine(aotArchTempDir, objFileName);
|
|
|
+ string objFilePath = Path.Combine(aotTempDir, objFileName);
|
|
|
|
|
|
var clangArgs = new List<string>()
|
|
|
{
|
|
|
"-isysroot", iOSSdkPath,
|
|
|
"-Qunused-arguments",
|
|
|
- $"-m{versionMinName}-version-min={versionMin}",
|
|
|
- "-arch", arch,
|
|
|
+ $"-miphoneos-version-min={versionMin}",
|
|
|
+ "-arch", "arm64",
|
|
|
"-c",
|
|
|
"-o", objFilePath,
|
|
|
"-x", "assembler"
|
|
@@ -204,18 +294,67 @@ namespace GodotTools.Export
|
|
|
if (clangExitCode != 0)
|
|
|
throw new Exception($"Command 'clang' exited with code: {clangExitCode}");
|
|
|
|
|
|
- objFilePathsForiOSArch[arch].Add(objFilePath);
|
|
|
+ aotObjFilePaths.Add(objFilePath);
|
|
|
}
|
|
|
|
|
|
aotModuleInfoSymbols.Add($"mono_aot_module_{AssemblyNameToAotSymbol(assemblyName)}_info");
|
|
|
}
|
|
|
|
|
|
+ RunAr(aotObjFilePaths, libAotFilePath);
|
|
|
+
|
|
|
+ // Archive the AOT object files into a static library
|
|
|
+
|
|
|
+ File.WriteAllText(Path.Combine(libAotXcFrameworkPath, "Info.plist"),
|
|
|
+ $@"<?xml version=""1.0"" encoding=""UTF-8""?>
|
|
|
+<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
|
|
|
+<plist version=""1.0"">
|
|
|
+<dict>
|
|
|
+ <key>AvailableLibraries</key>
|
|
|
+ <array>
|
|
|
+ <dict>
|
|
|
+ <key>LibraryIdentifier</key>
|
|
|
+ <string>ios-arm64</string>
|
|
|
+ <key>LibraryPath</key>
|
|
|
+ <string>{libAotFileName}</string>
|
|
|
+ <key>SupportedArchitectures</key>
|
|
|
+ <array>
|
|
|
+ <string>arm64</string>
|
|
|
+ </array>
|
|
|
+ <key>SupportedPlatform</key>
|
|
|
+ <string>ios</string>
|
|
|
+ </dict>
|
|
|
+ <dict>
|
|
|
+ <key>LibraryIdentifier</key>
|
|
|
+ <string>ios-arm64_x86_64-simulator</string>
|
|
|
+ <key>LibraryPath</key>
|
|
|
+ <string>{libAotFileName}</string>
|
|
|
+ <key>SupportedArchitectures</key>
|
|
|
+ <array>
|
|
|
+ <string>arm64</string>
|
|
|
+ <string>x86_64</string>
|
|
|
+ </array>
|
|
|
+ <key>SupportedPlatform</key>
|
|
|
+ <string>ios</string>
|
|
|
+ <key>SupportedPlatformVariant</key>
|
|
|
+ <string>simulator</string>
|
|
|
+ </dict>
|
|
|
+ </array>
|
|
|
+ <key>CFBundlePackageType</key>
|
|
|
+ <string>XFWK</string>
|
|
|
+ <key>XCFrameworkFormatVersion</key>
|
|
|
+ <string>1.0</string>
|
|
|
+</dict>
|
|
|
+</plist>
|
|
|
+");
|
|
|
+
|
|
|
+ // Add the fat AOT static library to the Xcode project
|
|
|
+ CreateDummyLibForSimulator(libAotName, libAotXcFrameworkPath);
|
|
|
+ exporter.AddIosProjectStaticLib(libAotXcFrameworkPath);
|
|
|
+
|
|
|
// Generate driver code
|
|
|
- cppCode.AppendLine("#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)");
|
|
|
- cppCode.AppendLine("#define IOS_DEVICE");
|
|
|
- cppCode.AppendLine("#endif");
|
|
|
+ cppCode.AppendLine("#include <TargetConditionals.h>");
|
|
|
|
|
|
- cppCode.AppendLine("#ifdef IOS_DEVICE");
|
|
|
+ cppCode.AppendLine("#if !TARGET_OS_SIMULATOR");
|
|
|
cppCode.AppendLine("extern \"C\" {");
|
|
|
cppCode.AppendLine("// Mono API");
|
|
|
cppCode.AppendLine(@"
|
|
@@ -279,59 +418,35 @@ MONO_AOT_MODE_LAST = 1000,
|
|
|
cppCode.AppendLine($"\tmono_jit_set_aot_mode({aotModeStr});");
|
|
|
|
|
|
cppCode.AppendLine("} // gd_mono_setup_aot");
|
|
|
- cppCode.AppendLine("} // extern \"C\"");
|
|
|
- cppCode.AppendLine("#endif // IOS_DEVICE");
|
|
|
-
|
|
|
- // Add the driver code to the Xcode project
|
|
|
- exporter.AddIosCppCode(cppCode.ToString());
|
|
|
|
|
|
- // Archive the AOT object files into a static library
|
|
|
+ // Prevent symbols from being stripped
|
|
|
|
|
|
- var arFilePathsForAllArchs = new List<string>();
|
|
|
- string projectAssemblyName = GodotSharpEditor.ProjectAssemblyName;
|
|
|
+ var symbols = CollectSymbols(assemblies);
|
|
|
|
|
|
- foreach (var archPathsPair in objFilePathsForiOSArch)
|
|
|
+ foreach (string symbol in symbols)
|
|
|
{
|
|
|
- string arch = archPathsPair.Key;
|
|
|
- var objFilePaths = archPathsPair.Value;
|
|
|
-
|
|
|
- string arOutputFilePath = Path.Combine(aotTempDir, $"lib-aot-{projectAssemblyName}.{arch}.a");
|
|
|
-
|
|
|
- var arArgs = new List<string>()
|
|
|
- {
|
|
|
- "cr",
|
|
|
- arOutputFilePath
|
|
|
- };
|
|
|
-
|
|
|
- foreach (string objFilePath in objFilePaths)
|
|
|
- arArgs.Add(objFilePath);
|
|
|
-
|
|
|
- int arExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("ar"), arArgs);
|
|
|
- if (arExitCode != 0)
|
|
|
- throw new Exception($"Command 'ar' exited with code: {arExitCode}");
|
|
|
-
|
|
|
- arFilePathsForAllArchs.Add(arOutputFilePath);
|
|
|
+ cppCode.Append("extern void *");
|
|
|
+ cppCode.Append(symbol);
|
|
|
+ cppCode.AppendLine(";");
|
|
|
}
|
|
|
|
|
|
- // It's lipo time
|
|
|
+ cppCode.AppendLine("__attribute__((used)) __attribute__((optnone)) static void __godot_symbol_referencer() {");
|
|
|
+ cppCode.AppendLine("\tvoid *aux;");
|
|
|
|
|
|
- string fatOutputFileName = $"lib-aot-{projectAssemblyName}.fat.a";
|
|
|
- string fatOutputFilePath = Path.Combine(aotTempDir, fatOutputFileName);
|
|
|
-
|
|
|
- var lipoArgs = new List<string>();
|
|
|
- lipoArgs.Add("-create");
|
|
|
- lipoArgs.AddRange(arFilePathsForAllArchs);
|
|
|
- lipoArgs.Add("-output");
|
|
|
- lipoArgs.Add(fatOutputFilePath);
|
|
|
+ foreach (string symbol in symbols)
|
|
|
+ {
|
|
|
+ cppCode.Append("\taux = ");
|
|
|
+ cppCode.Append(symbol);
|
|
|
+ cppCode.AppendLine(";");
|
|
|
+ }
|
|
|
|
|
|
- int lipoExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("lipo"), lipoArgs);
|
|
|
- if (lipoExitCode != 0)
|
|
|
- throw new Exception($"Command 'lipo' exited with code: {lipoExitCode}");
|
|
|
+ cppCode.AppendLine("} // __godot_symbol_referencer");
|
|
|
|
|
|
- // TODO: Add the AOT lib and interpreter libs as device only to suppress warnings when targeting the simulator
|
|
|
+ cppCode.AppendLine("} // extern \"C\"");
|
|
|
+ cppCode.AppendLine("#endif // !TARGET_OS_SIMULATOR");
|
|
|
|
|
|
- // Add the fat AOT static library to the Xcode project
|
|
|
- exporter.AddIosProjectStaticLib(fatOutputFilePath);
|
|
|
+ // Add the driver code to the Xcode project
|
|
|
+ exporter.AddIosCppCode(cppCode.ToString());
|
|
|
|
|
|
// Add the required Mono libraries to the Xcode project
|
|
|
|
|
@@ -340,15 +455,23 @@ MONO_AOT_MODE_LAST = 1000,
|
|
|
string MonoLibFromTemplate(string libFileName) =>
|
|
|
Path.Combine(Internal.FullTemplatesDir, "iphone-mono-libs", MonoLibFile(libFileName));
|
|
|
|
|
|
- exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmonosgen-2.0"));
|
|
|
+ string MonoFrameworkFile(string frameworkFileName) => frameworkFileName + ".xcframework";
|
|
|
+
|
|
|
+ string MonoFrameworkFromTemplate(string frameworkFileName) =>
|
|
|
+ Path.Combine(Internal.FullTemplatesDir, "iphone-mono-libs", MonoFrameworkFile(frameworkFileName));
|
|
|
+
|
|
|
+ exporter.AddIosProjectStaticLib(MonoFrameworkFromTemplate("libmonosgen-2.0"));
|
|
|
|
|
|
- exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-native"));
|
|
|
+ exporter.AddIosProjectStaticLib(MonoFrameworkFromTemplate("libmono-native"));
|
|
|
|
|
|
if (aotOpts.UseInterpreter)
|
|
|
{
|
|
|
- exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-ee-interp"));
|
|
|
- exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-icall-table"));
|
|
|
- exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-ilgen"));
|
|
|
+ CreateDummyLibForSimulator("libmono-ee-interp");
|
|
|
+ exporter.AddIosProjectStaticLib(MonoFrameworkFromTemplate("libmono-ee-interp"));
|
|
|
+ CreateDummyLibForSimulator("libmono-icall-table");
|
|
|
+ exporter.AddIosProjectStaticLib(MonoFrameworkFromTemplate("libmono-icall-table"));
|
|
|
+ CreateDummyLibForSimulator("libmono-ilgen");
|
|
|
+ exporter.AddIosProjectStaticLib(MonoFrameworkFromTemplate("libmono-ilgen"));
|
|
|
}
|
|
|
|
|
|
// TODO: Turn into an exporter option
|
|
@@ -360,13 +483,91 @@ MONO_AOT_MODE_LAST = 1000,
|
|
|
exporter.AddIosFramework("libiconv.tbd");
|
|
|
exporter.AddIosFramework("GSS.framework");
|
|
|
exporter.AddIosFramework("CFNetwork.framework");
|
|
|
+ if (!aotOpts.UseInterpreter)
|
|
|
+ exporter.AddIosFramework("SystemConfiguration.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);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type.Module.HasModuleReferences)
|
|
|
+ CollectPInvokeSymbols(type, symbols);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void CollectPInvokeSymbols(TypeDefinition type, ICollection<string> symbols)
|
|
|
+ {
|
|
|
+ if (!type.HasMethods)
|
|
|
+ return;
|
|
|
|
|
|
- // 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)/{MonoLibFile("libmono-native")}\"");
|
|
|
+ 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
|
|
@@ -374,11 +575,8 @@ MONO_AOT_MODE_LAST = 1000,
|
|
|
{
|
|
|
var builder = new StringBuilder();
|
|
|
|
|
|
- foreach (var charByte in Encoding.UTF8.GetBytes(assemblyName))
|
|
|
- {
|
|
|
- char @char = (char)charByte;
|
|
|
- builder.Append(Char.IsLetterOrDigit(@char) || @char == '_' ? @char : '_');
|
|
|
- }
|
|
|
+ foreach (char @char in assemblyName)
|
|
|
+ builder.Append(char.IsLetterOrDigit(@char) || @char == '_' ? @char : '_');
|
|
|
|
|
|
return builder.ToString();
|
|
|
}
|
|
@@ -577,27 +775,27 @@ MONO_AOT_MODE_LAST = 1000,
|
|
|
{
|
|
|
case OS.Platforms.Windows:
|
|
|
case OS.Platforms.UWP:
|
|
|
- {
|
|
|
- string arch = bits == "64" ? "x86_64" : "i686";
|
|
|
- return $"windows-{arch}";
|
|
|
- }
|
|
|
+ {
|
|
|
+ string arch = bits == "64" ? "x86_64" : "i686";
|
|
|
+ return $"windows-{arch}";
|
|
|
+ }
|
|
|
case OS.Platforms.OSX:
|
|
|
- {
|
|
|
- Debug.Assert(bits == null || bits == "64");
|
|
|
- string arch = "x86_64";
|
|
|
- return $"{platform}-{arch}";
|
|
|
- }
|
|
|
+ {
|
|
|
+ Debug.Assert(bits == null || bits == "64");
|
|
|
+ string arch = "x86_64";
|
|
|
+ return $"{platform}-{arch}";
|
|
|
+ }
|
|
|
case OS.Platforms.X11:
|
|
|
case OS.Platforms.Server:
|
|
|
- {
|
|
|
- string arch = bits == "64" ? "x86_64" : "i686";
|
|
|
- return $"linux-{arch}";
|
|
|
- }
|
|
|
+ {
|
|
|
+ string arch = bits == "64" ? "x86_64" : "i686";
|
|
|
+ return $"linux-{arch}";
|
|
|
+ }
|
|
|
case OS.Platforms.Haiku:
|
|
|
- {
|
|
|
- string arch = bits == "64" ? "x86_64" : "i686";
|
|
|
- return $"{platform}-{arch}";
|
|
|
- }
|
|
|
+ {
|
|
|
+ string arch = bits == "64" ? "x86_64" : "i686";
|
|
|
+ return $"{platform}-{arch}";
|
|
|
+ }
|
|
|
default:
|
|
|
throw new NotSupportedException($"Platform not supported: {platform}");
|
|
|
}
|