C#: Use Godot's LipO implementation instead of Xcode's lipo command

This commit is contained in:
Raul Santos 2024-04-21 19:51:02 +02:00
parent 1bd740d18d
commit c2efbf3012
No known key found for this signature in database
GPG Key ID: B532473AE3A803E4
4 changed files with 30 additions and 106 deletions

View File

@ -355,24 +355,23 @@ namespace GodotTools.Export
if (outputPaths.Count > 2) if (outputPaths.Count > 2)
{ {
// lipo the simulator binaries together // lipo the simulator binaries together
// TODO: Move this to the native lipo implementation we have in the macos export plugin.
var lipoArgs = new List<string>();
lipoArgs.Add("-create");
lipoArgs.AddRange(outputPaths.Skip(1).Select(x => Path.Combine(x, $"{GodotSharpDirs.ProjectAssemblyName}.dylib")));
lipoArgs.Add("-output");
lipoArgs.Add(Path.Combine(outputPaths[1], $"{GodotSharpDirs.ProjectAssemblyName}.dylib"));
int lipoExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("lipo"), lipoArgs); string outputPath = Path.Combine(outputPaths[1], $"{GodotSharpDirs.ProjectAssemblyName}.dylib");
if (lipoExitCode != 0) string[] files = outputPaths
throw new InvalidOperationException($"Command 'lipo' exited with code: {lipoExitCode}."); .Skip(1)
.Select(path => Path.Combine(path, $"{GodotSharpDirs.ProjectAssemblyName}.dylib"))
.ToArray();
if (!Internal.LipOCreateFile(outputPath, files))
{
throw new InvalidOperationException($"Failed to 'lipo' simulator binaries.");
}
outputPaths.RemoveRange(2, outputPaths.Count - 2); outputPaths.RemoveRange(2, outputPaths.Count - 2);
} }
var xcFrameworkPath = Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, publishConfig.BuildConfig, string xcFrameworkPath = Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, publishConfig.BuildConfig, $"{GodotSharpDirs.ProjectAssemblyName}_aot.xcframework");
$"{GodotSharpDirs.ProjectAssemblyName}_aot.xcframework"); if (!BuildManager.GenerateXCFrameworkBlocking(outputPaths, xcFrameworkPath))
if (!BuildManager.GenerateXCFrameworkBlocking(outputPaths,
Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, publishConfig.BuildConfig, xcFrameworkPath)))
{ {
throw new InvalidOperationException("Failed to generate xcframework."); throw new InvalidOperationException("Failed to generate xcframework.");
} }

View File

@ -1,93 +0,0 @@
using System;
using System.IO;
namespace GodotTools.Export
{
public static class XcodeHelper
{
private static string? _XcodePath = null;
public static string XcodePath
{
get
{
if (_XcodePath == null)
{
_XcodePath = FindXcode();
if (_XcodePath == null)
throw new FileNotFoundException("Could not find Xcode.");
}
return _XcodePath;
}
}
private static string? FindSelectedXcode()
{
var outputWrapper = new Godot.Collections.Array();
int exitCode = Godot.OS.Execute("xcode-select", new string[] { "--print-path" }, output: outputWrapper);
if (exitCode == 0)
{
string output = (string)outputWrapper[0];
return output.Trim();
}
Console.Error.WriteLine($"'xcode-select --print-path' exited with code: {exitCode}");
return null;
}
public static string? FindXcode()
{
string? selectedXcode = FindSelectedXcode();
if (selectedXcode != null)
{
if (Directory.Exists(Path.Combine(selectedXcode, "Contents", "Developer")))
return selectedXcode;
// The path already pointed to Contents/Developer
var dirInfo = new DirectoryInfo(selectedXcode);
if (dirInfo is not { Parent.Name: "Contents", Name: "Developer" })
{
Console.WriteLine(Path.GetDirectoryName(selectedXcode));
Console.WriteLine(System.IO.Directory.GetParent(selectedXcode)?.Name);
Console.Error.WriteLine("Unrecognized path for selected Xcode");
}
else
{
return System.IO.Path.GetFullPath($"{selectedXcode}/../..");
}
}
else
{
Console.Error.WriteLine("Could not find the selected Xcode; trying with a hint path");
}
const string XcodeHintPath = "/Applications/Xcode.app";
if (Directory.Exists(XcodeHintPath))
{
if (Directory.Exists(Path.Combine(XcodeHintPath, "Contents", "Developer")))
return XcodeHintPath;
Console.Error.WriteLine($"Found Xcode at '{XcodeHintPath}' but it's missing the 'Contents/Developer' sub-directory");
}
return null;
}
public static string FindXcodeTool(string toolName)
{
string XcodeDefaultToolchain = Path.Combine(XcodePath, "Contents", "Developer", "Toolchains", "XcodeDefault.xctoolchain");
string path = Path.Combine(XcodeDefaultToolchain, "usr", "bin", toolName);
if (File.Exists(path))
return path;
throw new FileNotFoundException($"Cannot find Xcode tool: {toolName}");
}
}
}

View File

@ -35,6 +35,13 @@ namespace GodotTools.Internals
return godot_icall_Internal_IsMacOSAppBundleInstalled(bundleIdIn); return godot_icall_Internal_IsMacOSAppBundleInstalled(bundleIdIn);
} }
public static bool LipOCreateFile(string outputPath, string[] files)
{
using godot_string outputPathIn = Marshaling.ConvertStringToNative(outputPath);
using godot_packed_string_array filesIn = Marshaling.ConvertSystemArrayToNativePackedStringArray(files);
return godot_icall_Internal_LipOCreateFile(outputPathIn, filesIn);
}
public static bool GodotIs32Bits() => godot_icall_Internal_GodotIs32Bits(); public static bool GodotIs32Bits() => godot_icall_Internal_GodotIs32Bits();
public static bool GodotIsRealTDouble() => godot_icall_Internal_GodotIsRealTDouble(); public static bool GodotIsRealTDouble() => godot_icall_Internal_GodotIsRealTDouble();
@ -121,6 +128,8 @@ namespace GodotTools.Internals
private static partial bool godot_icall_Internal_IsMacOSAppBundleInstalled(in godot_string bundleId); private static partial bool godot_icall_Internal_IsMacOSAppBundleInstalled(in godot_string bundleId);
private static partial bool godot_icall_Internal_LipOCreateFile(in godot_string outputPath, in godot_packed_string_array files);
private static partial bool godot_icall_Internal_GodotIs32Bits(); private static partial bool godot_icall_Internal_GodotIs32Bits();
private static partial bool godot_icall_Internal_GodotIsRealTDouble(); private static partial bool godot_icall_Internal_GodotIsRealTDouble();

View File

@ -44,6 +44,7 @@
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_paths.h" #include "editor/editor_paths.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/export/lipo.h"
#include "editor/gui/editor_run_bar.h" #include "editor/gui/editor_run_bar.h"
#include "editor/plugins/script_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h"
#include "editor/themes/editor_scale.h" #include "editor/themes/editor_scale.h"
@ -117,6 +118,13 @@ bool godot_icall_Internal_IsMacOSAppBundleInstalled(const godot_string *p_bundle
#endif #endif
} }
bool godot_icall_Internal_LipOCreateFile(const godot_string *p_output_path, const godot_packed_array *p_files) {
String output_path = *reinterpret_cast<const String *>(p_output_path);
PackedStringArray files = *reinterpret_cast<const PackedStringArray *>(p_files);
LipO lip;
return lip.create_file(output_path, files);
}
bool godot_icall_Internal_GodotIs32Bits() { bool godot_icall_Internal_GodotIs32Bits() {
return sizeof(void *) == 4; return sizeof(void *) == 4;
} }
@ -258,6 +266,7 @@ static const void *unmanaged_callbacks[]{
(void *)godot_icall_EditorProgress_Step, (void *)godot_icall_EditorProgress_Step,
(void *)godot_icall_Internal_FullExportTemplatesDir, (void *)godot_icall_Internal_FullExportTemplatesDir,
(void *)godot_icall_Internal_IsMacOSAppBundleInstalled, (void *)godot_icall_Internal_IsMacOSAppBundleInstalled,
(void *)godot_icall_Internal_LipOCreateFile,
(void *)godot_icall_Internal_GodotIs32Bits, (void *)godot_icall_Internal_GodotIs32Bits,
(void *)godot_icall_Internal_GodotIsRealTDouble, (void *)godot_icall_Internal_GodotIsRealTDouble,
(void *)godot_icall_Internal_GodotMainIteration, (void *)godot_icall_Internal_GodotMainIteration,