Skip to content

Commit

Permalink
C#: Add option to embed dotnet build outputs into the data file
Browse files Browse the repository at this point in the history
  • Loading branch information
RedworkDE committed Jun 28, 2023
1 parent c83f912 commit 777d959
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 15 deletions.
50 changes: 46 additions & 4 deletions modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using GodotTools.Build;
using GodotTools.Core;
using GodotTools.Internals;
Expand Down Expand Up @@ -45,6 +47,17 @@ public partial class ExportPlugin : EditorExportPlugin
}
},
{ "default_value", true }
},
new Godot.Collections.Dictionary()
{
{
"option", new Godot.Collections.Dictionary()
{
{ "name", "dotnet/embed_build_outputs" },
{ "type", (int)Variant.Type.Bool }
}
},
{ "default_value", false }
}
};
}
Expand Down Expand Up @@ -146,6 +159,8 @@ private void _ExportBeginImpl(string[] features, bool isDebug, string path, long
}
}

bool embedBuildResults = (bool)GetOption("dotnet/embed_build_outputs");

foreach (var arch in archs)
{
string ridOS = DetermineRuntimeIdentifierOS(platform);
Expand Down Expand Up @@ -190,17 +205,44 @@ private void _ExportBeginImpl(string[] features, bool isDebug, string path, long
"Publish succeeded but project assembly not found in the output directory");
}

// Add to the exported project shared object list.
var manifest = new StringBuilder();

// Add to the exported project shared object list or packed resources.
foreach (string file in Directory.GetFiles(publishOutputTempDir, "*", SearchOption.AllDirectories))
{
AddSharedObject(file, tags: null,
Path.Join(projectDataDirName,
Path.GetRelativePath(publishOutputTempDir, Path.GetDirectoryName(file))));
if (embedBuildResults)
{
var filePath = SanitizeSlashes(Path.GetRelativePath(publishOutputTempDir, file));
var fileData = File.ReadAllBytes(file);
var hash = Convert.ToBase64String(SHA512.HashData(fileData));

manifest.Append($"{filePath}\t{hash}\n");

AddFile($"res://.godot/mono/publish/{arch}/{filePath}", fileData, false);
}
else
{
AddSharedObject(file, tags: null,
Path.Join(projectDataDirName,
Path.GetRelativePath(publishOutputTempDir, Path.GetDirectoryName(file))));
}
}

if (embedBuildResults)
{
var fileData = Encoding.Default.GetBytes(manifest.ToString());
AddFile($"res://.godot/mono/publish/{arch}/.dotnet-publish-manifest", fileData, false);
}
}
}

private string SanitizeSlashes(string path)
{
if (Path.DirectorySeparatorChar == '\\')
return path.Replace('\\', '/');
return path;
}

private string DetermineRuntimeIdentifierOS(string platform)
=> OS.DotNetOSPlatformMap[platform];

Expand Down
55 changes: 44 additions & 11 deletions modules/mono/godotsharp_dirs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,19 +141,52 @@ class _GodotSharpDirs {
#else // TOOLS_ENABLED
String arch = Engine::get_singleton()->get_architecture_name();
String appname_safe = path::get_csharp_project_name();
String data_dir_root = exe_dir.path_join("data_" + appname_safe + "_" + arch);
if (!DirAccess::exists(data_dir_root)) {
data_dir_root = exe_dir.path_join("data_Godot_" + arch);
}
String packed_path = "res://.godot/mono/publish/" + arch;
if (DirAccess::exists(packed_path)) {
// The dotnet publish data is packed in the pck/zip.
String data_dir_root = OS::get_singleton()->get_cache_path().path_join("data_" + appname_safe + "_" + arch);
bool has_data = false;
if (!has_data) {
// 1. Try to access the data directly.
String global_packed = ProjectSettings::get_singleton()->globalize_path(packed_path);
if (global_packed.is_absolute_path() && FileAccess::exists(global_packed.path_join(".dotnet-publish-manifest"))) {
data_dir_root = global_packed;
has_data = true;
}
}
if (!has_data) {
// 2. Check if the data was extracted before and is up-to-date.
String packed_manifest = packed_path.path_join(".dotnet-publish-manifest");
String extracted_manifest = data_dir_root.path_join(".dotnet-publish-manifest");
if (FileAccess::exists(packed_manifest) && FileAccess::exists(extracted_manifest)) {
if (FileAccess::get_file_as_bytes(packed_manifest) == FileAccess::get_file_as_bytes(extracted_manifest)) {
has_data = true;
}
}
}
if (!has_data) {
// 3. Extract the data to a temporary location to load from there.
Ref<DirAccess> da = DirAccess::create_for_path(packed_path);
ERR_FAIL_NULL(da);
ERR_FAIL_COND(da->copy_dir(packed_path, data_dir_root) != OK);
}
api_assemblies_dir = data_dir_root;
} else {
// The dotnet publish data is in a directory next to the executable.
String data_dir_root = exe_dir.path_join("data_" + appname_safe + "_" + arch);
if (!DirAccess::exists(data_dir_root)) {
data_dir_root = exe_dir.path_join("data_Godot_" + arch);
}
#ifdef MACOS_ENABLED
if (!DirAccess::exists(data_dir_root)) {
data_dir_root = res_dir.path_join("data_" + appname_safe + "_" + arch);
}
if (!DirAccess::exists(data_dir_root)) {
data_dir_root = res_dir.path_join("data_Godot_" + arch);
}
if (!DirAccess::exists(data_dir_root)) {
data_dir_root = res_dir.path_join("data_" + appname_safe + "_" + arch);
}
if (!DirAccess::exists(data_dir_root)) {
data_dir_root = res_dir.path_join("data_Godot_" + arch);
}
#endif
api_assemblies_dir = data_dir_root;
api_assemblies_dir = data_dir_root;
}
#endif
}

Expand Down

0 comments on commit 777d959

Please sign in to comment.