|
@@ -29,15 +29,13 @@ namespace GodotTools.Export
|
|
All = CJK | MidEast | Other | Rare | West
|
|
All = CJK | MidEast | Other | Rare | West
|
|
}
|
|
}
|
|
|
|
|
|
- private void AddI18NAssemblies(Godot.Collections.Dictionary<string, string> assemblies, string platform)
|
|
|
|
|
|
+ private void AddI18NAssemblies(Godot.Collections.Dictionary<string, string> assemblies, string bclDir)
|
|
{
|
|
{
|
|
- var codesets = (I18NCodesets) ProjectSettings.GetSetting("mono/export/i18n_codesets");
|
|
|
|
|
|
+ var codesets = (I18NCodesets)ProjectSettings.GetSetting("mono/export/i18n_codesets");
|
|
|
|
|
|
if (codesets == I18NCodesets.None)
|
|
if (codesets == I18NCodesets.None)
|
|
return;
|
|
return;
|
|
|
|
|
|
- string bclDir = DeterminePlatformBclDir(platform) ?? typeof(object).Assembly.Location.GetBaseDir();
|
|
|
|
-
|
|
|
|
void AddI18NAssembly(string name) => assemblies.Add(name, Path.Combine(bclDir, $"{name}.dll"));
|
|
void AddI18NAssembly(string name) => assemblies.Add(name, Path.Combine(bclDir, $"{name}.dll"));
|
|
|
|
|
|
AddI18NAssembly("I18N");
|
|
AddI18NAssembly("I18N");
|
|
@@ -73,6 +71,7 @@ namespace GodotTools.Export
|
|
|
|
|
|
GlobalDef("mono/export/aot/enabled", false);
|
|
GlobalDef("mono/export/aot/enabled", false);
|
|
GlobalDef("mono/export/aot/full_aot", false);
|
|
GlobalDef("mono/export/aot/full_aot", false);
|
|
|
|
+ GlobalDef("mono/export/aot/use_interpreter", true);
|
|
|
|
|
|
// --aot or --aot=opt1,opt2 (use 'mono --aot=help AuxAssembly.dll' to list AOT options)
|
|
// --aot or --aot=opt1,opt2 (use 'mono --aot=help AuxAssembly.dll' to list AOT options)
|
|
GlobalDef("mono/export/aot/extra_aot_options", new string[] { });
|
|
GlobalDef("mono/export/aot/extra_aot_options", new string[] { });
|
|
@@ -86,9 +85,11 @@ namespace GodotTools.Export
|
|
|
|
|
|
private void AddFile(string srcPath, string dstPath, bool remap = false)
|
|
private void AddFile(string srcPath, string dstPath, bool remap = false)
|
|
{
|
|
{
|
|
|
|
+ // Add file to the PCK
|
|
AddFile(dstPath.Replace("\\", "/"), File.ReadAllBytes(srcPath), remap);
|
|
AddFile(dstPath.Replace("\\", "/"), File.ReadAllBytes(srcPath), remap);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // With this method we can override how a file is exported in the PCK
|
|
public override void _ExportFile(string path, string type, string[] features)
|
|
public override void _ExportFile(string path, string type, string[] features)
|
|
{
|
|
{
|
|
base._ExportFile(path, type, features);
|
|
base._ExportFile(path, type, features);
|
|
@@ -110,6 +111,8 @@ namespace GodotTools.Export
|
|
// Sadly, Godot prints errors when adding an empty file (nothing goes wrong, it's just noise).
|
|
// Sadly, Godot prints errors when adding an empty file (nothing goes wrong, it's just noise).
|
|
// Because of this, we add a file which contains a line break.
|
|
// Because of this, we add a file which contains a line break.
|
|
AddFile(path, System.Text.Encoding.UTF8.GetBytes("\n"), remap: false);
|
|
AddFile(path, System.Text.Encoding.UTF8.GetBytes("\n"), remap: false);
|
|
|
|
+
|
|
|
|
+ // Tell the Godot exporter that we already took care of the file
|
|
Skip();
|
|
Skip();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -167,12 +170,7 @@ namespace GodotTools.Export
|
|
|
|
|
|
var dependencies = new Godot.Collections.Dictionary<string, string>();
|
|
var dependencies = new Godot.Collections.Dictionary<string, string>();
|
|
|
|
|
|
- var projectDllName = (string)ProjectSettings.GetSetting("application/config/name");
|
|
|
|
- if (projectDllName.Empty())
|
|
|
|
- {
|
|
|
|
- projectDllName = "UnnamedProject";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ string projectDllName = GodotSharpEditor.ProjectAssemblyName;
|
|
string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig);
|
|
string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig);
|
|
string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll");
|
|
string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll");
|
|
|
|
|
|
@@ -189,10 +187,12 @@ namespace GodotTools.Export
|
|
dependencies["Mono.Android"] = monoAndroidAssemblyPath;
|
|
dependencies["Mono.Android"] = monoAndroidAssemblyPath;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ string bclDir = DeterminePlatformBclDir(platform);
|
|
|
|
+
|
|
var initialDependencies = dependencies.Duplicate();
|
|
var initialDependencies = dependencies.Duplicate();
|
|
- internal_GetExportedAssemblyDependencies(initialDependencies, buildConfig, DeterminePlatformBclDir(platform), dependencies);
|
|
|
|
|
|
+ internal_GetExportedAssemblyDependencies(initialDependencies, buildConfig, bclDir, dependencies);
|
|
|
|
|
|
- AddI18NAssemblies(dependencies, platform);
|
|
|
|
|
|
+ AddI18NAssemblies(dependencies, bclDir);
|
|
|
|
|
|
string outputDataDir = null;
|
|
string outputDataDir = null;
|
|
|
|
|
|
@@ -227,11 +227,34 @@ namespace GodotTools.Export
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // AOT
|
|
|
|
|
|
+ // AOT compilation
|
|
|
|
+ bool aotEnabled = platform == OS.Platforms.iOS || (bool)ProjectSettings.GetSetting("mono/export/aot/enabled");
|
|
|
|
|
|
- if ((bool)ProjectSettings.GetSetting("mono/export/aot/enabled"))
|
|
|
|
|
|
+ if (aotEnabled)
|
|
{
|
|
{
|
|
- AotCompileDependencies(features, platform, isDebug, outputDir, outputDataDir, dependencies);
|
|
|
|
|
|
+ string aotToolchainPath = null;
|
|
|
|
+
|
|
|
|
+ if (platform == OS.Platforms.Android)
|
|
|
|
+ aotToolchainPath = (string)ProjectSettings.GetSetting("mono/export/aot/android_toolchain_path");
|
|
|
|
+
|
|
|
|
+ if (aotToolchainPath == string.Empty)
|
|
|
|
+ aotToolchainPath = null; // Don't risk it being used as current working dir
|
|
|
|
+
|
|
|
|
+ // TODO: LLVM settings are hard-coded and disabled for now
|
|
|
|
+ var aotOpts = new AotOptions
|
|
|
|
+ {
|
|
|
|
+ EnableLLVM = false,
|
|
|
|
+ LLVMOnly = false,
|
|
|
|
+ LLVMPath = "",
|
|
|
|
+ LLVMOutputPath = "",
|
|
|
|
+ FullAot = platform == OS.Platforms.iOS || (bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false),
|
|
|
|
+ UseInterpreter = (bool)ProjectSettings.GetSetting("mono/export/aot/use_interpreter"),
|
|
|
|
+ ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? new string[] { },
|
|
|
|
+ ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? new string[] { },
|
|
|
|
+ ToolchainPath = aotToolchainPath
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, dependencies);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -258,7 +281,8 @@ namespace GodotTools.Export
|
|
{
|
|
{
|
|
string target = isDebug ? "release_debug" : "release";
|
|
string target = isDebug ? "release_debug" : "release";
|
|
|
|
|
|
- // NOTE: Bits is ok for now as all platforms with a data directory have it, but that may change in the future.
|
|
|
|
|
|
+ // NOTE: Bits is ok for now as all platforms with a data directory only have one or two architectures.
|
|
|
|
+ // However, this may change in the future if we add arm linux or windows desktop templates.
|
|
string bits = features.Contains("64") ? "64" : "32";
|
|
string bits = features.Contains("64") ? "64" : "32";
|
|
|
|
|
|
string TemplateDirName() => $"data.mono.{platform}.{bits}.{target}";
|
|
string TemplateDirName() => $"data.mono.{platform}.{bits}.{target}";
|
|
@@ -284,7 +308,7 @@ namespace GodotTools.Export
|
|
if (!validTemplatePathFound)
|
|
if (!validTemplatePathFound)
|
|
throw new FileNotFoundException("Data template directory not found", templateDirPath);
|
|
throw new FileNotFoundException("Data template directory not found", templateDirPath);
|
|
|
|
|
|
- string outputDataDir = Path.Combine(outputDir, DataDirName);
|
|
|
|
|
|
+ string outputDataDir = Path.Combine(outputDir, DetermineDataDirNameForProject());
|
|
|
|
|
|
if (Directory.Exists(outputDataDir))
|
|
if (Directory.Exists(outputDataDir))
|
|
Directory.Delete(outputDataDir, recursive: true); // Clean first
|
|
Directory.Delete(outputDataDir, recursive: true); // Clean first
|
|
@@ -304,333 +328,10 @@ namespace GodotTools.Export
|
|
return outputDataDir;
|
|
return outputDataDir;
|
|
}
|
|
}
|
|
|
|
|
|
- private void AotCompileDependencies(string[] features, string platform, bool isDebug, string outputDir, string outputDataDir, IDictionary<string, string> dependencies)
|
|
|
|
- {
|
|
|
|
- // TODO: WASM
|
|
|
|
-
|
|
|
|
- string bclDir = DeterminePlatformBclDir(platform) ?? typeof(object).Assembly.Location.GetBaseDir();
|
|
|
|
-
|
|
|
|
- string aotTempDir = Path.Combine(Path.GetTempPath(), $"godot-aot-{Process.GetCurrentProcess().Id}");
|
|
|
|
-
|
|
|
|
- if (!Directory.Exists(aotTempDir))
|
|
|
|
- Directory.CreateDirectory(aotTempDir);
|
|
|
|
-
|
|
|
|
- var assemblies = new Dictionary<string, string>();
|
|
|
|
-
|
|
|
|
- foreach (var dependency in dependencies)
|
|
|
|
- {
|
|
|
|
- string assemblyName = dependency.Key;
|
|
|
|
- string assemblyPath = dependency.Value;
|
|
|
|
-
|
|
|
|
- string assemblyPathInBcl = Path.Combine(bclDir, assemblyName + ".dll");
|
|
|
|
-
|
|
|
|
- if (File.Exists(assemblyPathInBcl))
|
|
|
|
- {
|
|
|
|
- // Don't create teporaries for assemblies from the BCL
|
|
|
|
- assemblies.Add(assemblyName, assemblyPathInBcl);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- string tempAssemblyPath = Path.Combine(aotTempDir, assemblyName + ".dll");
|
|
|
|
- File.Copy(assemblyPath, tempAssemblyPath);
|
|
|
|
- assemblies.Add(assemblyName, tempAssemblyPath);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- foreach (var assembly in assemblies)
|
|
|
|
- {
|
|
|
|
- string assemblyName = assembly.Key;
|
|
|
|
- string assemblyPath = assembly.Value;
|
|
|
|
-
|
|
|
|
- string sharedLibExtension = platform == OS.Platforms.Windows ? ".dll" :
|
|
|
|
- platform == OS.Platforms.OSX ? ".dylib" :
|
|
|
|
- platform == OS.Platforms.HTML5 ? ".wasm" :
|
|
|
|
- ".so";
|
|
|
|
-
|
|
|
|
- string outputFileName = assemblyName + ".dll" + sharedLibExtension;
|
|
|
|
-
|
|
|
|
- if (platform == OS.Platforms.Android)
|
|
|
|
- {
|
|
|
|
- // Not sure if the 'lib' prefix is an Android thing or just Godot being picky,
|
|
|
|
- // but we use '-aot-' as well just in case to avoid conflicts with other libs.
|
|
|
|
- outputFileName = "lib-aot-" + outputFileName;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- string outputFilePath = null;
|
|
|
|
- string tempOutputFilePath;
|
|
|
|
-
|
|
|
|
- switch (platform)
|
|
|
|
- {
|
|
|
|
- case OS.Platforms.OSX:
|
|
|
|
- tempOutputFilePath = Path.Combine(aotTempDir, outputFileName);
|
|
|
|
- break;
|
|
|
|
- case OS.Platforms.Android:
|
|
|
|
- tempOutputFilePath = Path.Combine(aotTempDir, "%%ANDROID_ABI%%", outputFileName);
|
|
|
|
- break;
|
|
|
|
- case OS.Platforms.HTML5:
|
|
|
|
- tempOutputFilePath = Path.Combine(aotTempDir, outputFileName);
|
|
|
|
- outputFilePath = Path.Combine(outputDir, outputFileName);
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- tempOutputFilePath = Path.Combine(aotTempDir, outputFileName);
|
|
|
|
- outputFilePath = Path.Combine(outputDataDir, "Mono", platform == OS.Platforms.Windows ? "bin" : "lib", outputFileName);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var data = new Dictionary<string, string>();
|
|
|
|
- var enabledAndroidAbis = platform == OS.Platforms.Android ? GetEnabledAndroidAbis(features).ToArray() : null;
|
|
|
|
-
|
|
|
|
- if (platform == OS.Platforms.Android)
|
|
|
|
- {
|
|
|
|
- Debug.Assert(enabledAndroidAbis != null);
|
|
|
|
-
|
|
|
|
- foreach (var abi in enabledAndroidAbis)
|
|
|
|
- {
|
|
|
|
- data["abi"] = abi;
|
|
|
|
- var outputFilePathForThisAbi = tempOutputFilePath.Replace("%%ANDROID_ABI%%", abi);
|
|
|
|
-
|
|
|
|
- AotCompileAssembly(platform, isDebug, data, assemblyPath, outputFilePathForThisAbi);
|
|
|
|
-
|
|
|
|
- AddSharedObject(outputFilePathForThisAbi, tags: new[] { abi });
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- string bits = features.Contains("64") ? "64" : features.Contains("64") ? "32" : null;
|
|
|
|
-
|
|
|
|
- if (bits != null)
|
|
|
|
- data["bits"] = bits;
|
|
|
|
-
|
|
|
|
- AotCompileAssembly(platform, isDebug, data, assemblyPath, tempOutputFilePath);
|
|
|
|
-
|
|
|
|
- if (platform == OS.Platforms.OSX)
|
|
|
|
- {
|
|
|
|
- AddSharedObject(tempOutputFilePath, tags: null);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- Debug.Assert(outputFilePath != null);
|
|
|
|
- File.Copy(tempOutputFilePath, outputFilePath);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private static void AotCompileAssembly(string platform, bool isDebug, Dictionary<string, string> data, string assemblyPath, string outputFilePath)
|
|
|
|
- {
|
|
|
|
- // Make sure the output directory exists
|
|
|
|
- Directory.CreateDirectory(outputFilePath.GetBaseDir());
|
|
|
|
-
|
|
|
|
- string exeExt = OS.IsWindows ? ".exe" : string.Empty;
|
|
|
|
-
|
|
|
|
- string monoCrossDirName = DetermineMonoCrossDirName(platform, data);
|
|
|
|
- string monoCrossRoot = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "aot-compilers", monoCrossDirName);
|
|
|
|
- string monoCrossBin = Path.Combine(monoCrossRoot, "bin");
|
|
|
|
-
|
|
|
|
- string toolPrefix = DetermineToolPrefix(monoCrossBin);
|
|
|
|
- string monoExeName = System.IO.File.Exists(Path.Combine(monoCrossBin, $"{toolPrefix}mono{exeExt}")) ? "mono" : "mono-sgen";
|
|
|
|
-
|
|
|
|
- string compilerCommand = Path.Combine(monoCrossBin, $"{toolPrefix}{monoExeName}{exeExt}");
|
|
|
|
-
|
|
|
|
- bool fullAot = (bool)ProjectSettings.GetSetting("mono/export/aot/full_aot");
|
|
|
|
-
|
|
|
|
- string EscapeOption(string option) => option.Contains(',') ? $"\"{option}\"" : option;
|
|
|
|
- string OptionsToString(IEnumerable<string> options) => string.Join(",", options.Select(EscapeOption));
|
|
|
|
-
|
|
|
|
- var aotOptions = new List<string>();
|
|
|
|
- var optimizerOptions = new List<string>();
|
|
|
|
-
|
|
|
|
- if (fullAot)
|
|
|
|
- aotOptions.Add("full");
|
|
|
|
-
|
|
|
|
- aotOptions.Add(isDebug ? "soft-debug" : "nodebug");
|
|
|
|
-
|
|
|
|
- if (platform == OS.Platforms.Android)
|
|
|
|
- {
|
|
|
|
- string abi = data["abi"];
|
|
|
|
-
|
|
|
|
- string androidToolchain = (string)ProjectSettings.GetSetting("mono/export/aot/android_toolchain_path");
|
|
|
|
-
|
|
|
|
- if (string.IsNullOrEmpty(androidToolchain))
|
|
|
|
- {
|
|
|
|
- androidToolchain = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "android-toolchains", $"{abi}"); // TODO: $"{abi}-{apiLevel}{(clang?"clang":"")}"
|
|
|
|
-
|
|
|
|
- if (!Directory.Exists(androidToolchain))
|
|
|
|
- throw new FileNotFoundException("Missing android toolchain. Specify one in the AOT export settings.");
|
|
|
|
- }
|
|
|
|
- else if (!Directory.Exists(androidToolchain))
|
|
|
|
- {
|
|
|
|
- throw new FileNotFoundException("Android toolchain not found: " + androidToolchain);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var androidToolPrefixes = new Dictionary<string, string>
|
|
|
|
- {
|
|
|
|
- ["armeabi-v7a"] = "arm-linux-androideabi-",
|
|
|
|
- ["arm64-v8a"] = "aarch64-linux-android-",
|
|
|
|
- ["x86"] = "i686-linux-android-",
|
|
|
|
- ["x86_64"] = "x86_64-linux-android-"
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- aotOptions.Add("tool-prefix=" + Path.Combine(androidToolchain, "bin", androidToolPrefixes[abi]));
|
|
|
|
-
|
|
|
|
- string triple = GetAndroidTriple(abi);
|
|
|
|
- aotOptions.Add($"mtriple={triple}");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- aotOptions.Add($"outfile={outputFilePath}");
|
|
|
|
-
|
|
|
|
- var extraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options");
|
|
|
|
- var extraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options");
|
|
|
|
-
|
|
|
|
- if (extraAotOptions.Length > 0)
|
|
|
|
- aotOptions.AddRange(extraAotOptions);
|
|
|
|
-
|
|
|
|
- if (extraOptimizerOptions.Length > 0)
|
|
|
|
- optimizerOptions.AddRange(extraOptimizerOptions);
|
|
|
|
-
|
|
|
|
- var compilerArgs = new List<string>();
|
|
|
|
-
|
|
|
|
- if (isDebug)
|
|
|
|
- compilerArgs.Add("--debug"); // Required for --aot=soft-debug
|
|
|
|
-
|
|
|
|
- compilerArgs.Add(aotOptions.Count > 0 ? $"--aot={OptionsToString(aotOptions)}" : "--aot");
|
|
|
|
-
|
|
|
|
- if (optimizerOptions.Count > 0)
|
|
|
|
- compilerArgs.Add($"-O={OptionsToString(optimizerOptions)}");
|
|
|
|
-
|
|
|
|
- compilerArgs.Add(ProjectSettings.GlobalizePath(assemblyPath));
|
|
|
|
-
|
|
|
|
- // TODO: Once we move to .NET Standard 2.1 we can use ProcessStartInfo.ArgumentList instead
|
|
|
|
- string CmdLineArgsToString(IEnumerable<string> args)
|
|
|
|
- {
|
|
|
|
- // Not perfect, but as long as we are careful...
|
|
|
|
- return string.Join(" ", args.Select(arg => arg.Contains(" ") ? $@"""{arg}""" : arg));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- using (var process = new Process())
|
|
|
|
- {
|
|
|
|
- process.StartInfo = new ProcessStartInfo(compilerCommand, CmdLineArgsToString(compilerArgs))
|
|
|
|
- {
|
|
|
|
- UseShellExecute = false
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- string platformBclDir = DeterminePlatformBclDir(platform);
|
|
|
|
- process.StartInfo.EnvironmentVariables.Add("MONO_PATH", string.IsNullOrEmpty(platformBclDir) ?
|
|
|
|
- typeof(object).Assembly.Location.GetBaseDir() :
|
|
|
|
- platformBclDir);
|
|
|
|
-
|
|
|
|
- Console.WriteLine($"Running: \"{process.StartInfo.FileName}\" {process.StartInfo.Arguments}");
|
|
|
|
-
|
|
|
|
- if (!process.Start())
|
|
|
|
- throw new Exception("Failed to start process for Mono AOT compiler");
|
|
|
|
-
|
|
|
|
- process.WaitForExit();
|
|
|
|
-
|
|
|
|
- if (process.ExitCode != 0)
|
|
|
|
- throw new Exception($"Mono AOT compiler exited with error code: {process.ExitCode}");
|
|
|
|
-
|
|
|
|
- if (!System.IO.File.Exists(outputFilePath))
|
|
|
|
- throw new Exception("Mono AOT compiler finished successfully but the output file is missing");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private static string DetermineMonoCrossDirName(string platform, IReadOnlyDictionary<string, string> data)
|
|
|
|
- {
|
|
|
|
- switch (platform)
|
|
|
|
- {
|
|
|
|
- case OS.Platforms.Windows:
|
|
|
|
- case OS.Platforms.UWP:
|
|
|
|
- {
|
|
|
|
- string arch = data["bits"] == "64" ? "x86_64" : "i686";
|
|
|
|
- return $"windows-{arch}";
|
|
|
|
- }
|
|
|
|
- case OS.Platforms.OSX:
|
|
|
|
- {
|
|
|
|
- string arch = "x86_64";
|
|
|
|
- return $"{platform}-{arch}";
|
|
|
|
- }
|
|
|
|
- case OS.Platforms.X11:
|
|
|
|
- case OS.Platforms.Server:
|
|
|
|
- {
|
|
|
|
- string arch = data["bits"] == "64" ? "x86_64" : "i686";
|
|
|
|
- return $"linux-{arch}";
|
|
|
|
- }
|
|
|
|
- case OS.Platforms.Haiku:
|
|
|
|
- {
|
|
|
|
- string arch = data["bits"] == "64" ? "x86_64" : "i686";
|
|
|
|
- return $"{platform}-{arch}";
|
|
|
|
- }
|
|
|
|
- case OS.Platforms.Android:
|
|
|
|
- {
|
|
|
|
- string abi = data["abi"];
|
|
|
|
- return $"{platform}-{abi}";
|
|
|
|
- }
|
|
|
|
- case OS.Platforms.HTML5:
|
|
|
|
- return "wasm-wasm32";
|
|
|
|
- default:
|
|
|
|
- throw new NotSupportedException($"Platform not supported: {platform}");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private static string DetermineToolPrefix(string monoCrossBin)
|
|
|
|
- {
|
|
|
|
- string exeExt = OS.IsWindows ? ".exe" : string.Empty;
|
|
|
|
-
|
|
|
|
- if (System.IO.File.Exists(Path.Combine(monoCrossBin, $"mono{exeExt}")))
|
|
|
|
- return string.Empty;
|
|
|
|
-
|
|
|
|
- if (System.IO.File.Exists(Path.Combine(monoCrossBin, $"mono-sgen{exeExt}" + exeExt)))
|
|
|
|
- return string.Empty;
|
|
|
|
-
|
|
|
|
- var files = new DirectoryInfo(monoCrossBin).GetFiles($"*mono{exeExt}" + exeExt, SearchOption.TopDirectoryOnly);
|
|
|
|
- if (files.Length > 0)
|
|
|
|
- {
|
|
|
|
- string fileName = files[0].Name;
|
|
|
|
- return fileName.Substring(0, fileName.Length - $"mono{exeExt}".Length);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- files = new DirectoryInfo(monoCrossBin).GetFiles($"*mono-sgen{exeExt}" + exeExt, SearchOption.TopDirectoryOnly);
|
|
|
|
- if (files.Length > 0)
|
|
|
|
- {
|
|
|
|
- string fileName = files[0].Name;
|
|
|
|
- return fileName.Substring(0, fileName.Length - $"mono-sgen{exeExt}".Length);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- throw new FileNotFoundException($"Cannot find the mono runtime executable in {monoCrossBin}");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private static IEnumerable<string> GetEnabledAndroidAbis(string[] features)
|
|
|
|
- {
|
|
|
|
- var androidAbis = new[]
|
|
|
|
- {
|
|
|
|
- "armeabi-v7a",
|
|
|
|
- "arm64-v8a",
|
|
|
|
- "x86",
|
|
|
|
- "x86_64"
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- return androidAbis.Where(features.Contains);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private static string GetAndroidTriple(string abi)
|
|
|
|
- {
|
|
|
|
- var abiArchs = new Dictionary<string, string>
|
|
|
|
- {
|
|
|
|
- ["armeabi-v7a"] = "armv7",
|
|
|
|
- ["arm64-v8a"] = "aarch64-v8a",
|
|
|
|
- ["x86"] = "i686",
|
|
|
|
- ["x86_64"] = "x86_64"
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- string arch = abiArchs[abi];
|
|
|
|
-
|
|
|
|
- return $"{arch}-linux-android";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
private static bool PlatformHasTemplateDir(string platform)
|
|
private static bool PlatformHasTemplateDir(string platform)
|
|
{
|
|
{
|
|
// OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
|
|
// OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
|
|
- return !new[] { OS.Platforms.OSX, OS.Platforms.Android, OS.Platforms.HTML5 }.Contains(platform);
|
|
|
|
|
|
+ return !new[] { OS.Platforms.OSX, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform);
|
|
}
|
|
}
|
|
|
|
|
|
private static string DeterminePlatformFromFeatures(IEnumerable<string> features)
|
|
private static string DeterminePlatformFromFeatures(IEnumerable<string> features)
|
|
@@ -665,7 +366,7 @@ namespace GodotTools.Export
|
|
if (PlatformRequiresCustomBcl(platform))
|
|
if (PlatformRequiresCustomBcl(platform))
|
|
throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}");
|
|
throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}");
|
|
|
|
|
|
- platformBclDir = null; // Use the one we're running on
|
|
|
|
|
|
+ platformBclDir = typeof(object).Assembly.Location; // Use the one we're running on
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -678,7 +379,7 @@ namespace GodotTools.Export
|
|
/// </summary>
|
|
/// </summary>
|
|
private static bool PlatformRequiresCustomBcl(string platform)
|
|
private static bool PlatformRequiresCustomBcl(string platform)
|
|
{
|
|
{
|
|
- if (new[] { OS.Platforms.Android, OS.Platforms.HTML5 }.Contains(platform))
|
|
|
|
|
|
+ if (new[] { OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform))
|
|
return true;
|
|
return true;
|
|
|
|
|
|
// The 'net_4_x' BCL is not compatible between Windows and the other platforms.
|
|
// The 'net_4_x' BCL is not compatible between Windows and the other platforms.
|
|
@@ -707,6 +408,8 @@ namespace GodotTools.Export
|
|
return "net_4_x";
|
|
return "net_4_x";
|
|
case OS.Platforms.Android:
|
|
case OS.Platforms.Android:
|
|
return "monodroid";
|
|
return "monodroid";
|
|
|
|
+ case OS.Platforms.iOS:
|
|
|
|
+ return "monotouch";
|
|
case OS.Platforms.HTML5:
|
|
case OS.Platforms.HTML5:
|
|
return "wasm";
|
|
return "wasm";
|
|
default:
|
|
default:
|
|
@@ -714,14 +417,11 @@ namespace GodotTools.Export
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private static string DataDirName
|
|
|
|
|
|
+ private static string DetermineDataDirNameForProject()
|
|
{
|
|
{
|
|
- get
|
|
|
|
- {
|
|
|
|
- var appName = (string)ProjectSettings.GetSetting("application/config/name");
|
|
|
|
- string appNameSafe = appName.ToSafeDirName(allowDirSeparator: false);
|
|
|
|
- return $"data_{appNameSafe}";
|
|
|
|
- }
|
|
|
|
|
|
+ var appName = (string)ProjectSettings.GetSetting("application/config/name");
|
|
|
|
+ string appNameSafe = appName.ToSafeDirName(allowDirSeparator: false);
|
|
|
|
+ return $"data_{appNameSafe}";
|
|
}
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|