From 7cc6a89fc666e9ffd21be07c500f1eab594da217 Mon Sep 17 00:00:00 2001 From: loicb Date: Fri, 5 Jun 2026 11:27:54 +0800 Subject: [PATCH 1/2] fix(magic-unity): select workaround signature assemblies from player compilation references (#23) GenerateGenericWorkaroundMethods collected dispatch target signatures by walking the type reference closure from Assembly-CSharp against the editor's full desktop BCL, trimmed only by a Unity prefix check. On Windows that closure reaches editor-only assemblies like Mono.WebBrowser, and signatures referencing them break the IL2CPP build. Replace the prefix heuristic with an allowlist derived from CompilationPipeline player compilation references: an assembly's methods can only be dynamic dispatch targets in the player if player scripts compile against it. Editor-only assemblies are excluded structurally on any platform, with no name list to maintain. References added via rsp files are part of the player compilation reference set, so they stay in the signature pool. Init logs the reference set and each skip logs its reason so selection changes are auditable in build logs, and a guard fails the build if the reference set ever looks degenerate, instead of silently generating no workarounds. Verified on the smoke project: IL2CPP build and run, 41/41 checks passed. --- .../GenerateGenericWorkaroundMethods.cs | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/magic-unity/Editor/GenerateGenericWorkaroundMethods.cs b/magic-unity/Editor/GenerateGenericWorkaroundMethods.cs index 3bc258d1..6fae0abf 100644 --- a/magic-unity/Editor/GenerateGenericWorkaroundMethods.cs +++ b/magic-unity/Editor/GenerateGenericWorkaroundMethods.cs @@ -5,6 +5,7 @@ using Mono.Cecil; using Mono.Cecil.Rocks; using Mono.Cecil.Cil; +using UnityEditor.Compilation; namespace Magic.Unity { @@ -21,10 +22,35 @@ struct DynamicCallSiteInfo static List AllMethods = new List(); static TypeDefinition MagicRuntimeDelegateHelpers = null; - static bool ShouldCollectReferencedAssembly(AssemblyDefinition assy) + static HashSet PlayerReferenceNames = null; + + // The collected assemblies feed AllMethods, the pool of candidate dynamic + // dispatch targets whose GetMethodDelegateFast instantiations get emitted + // into the shipped .clj.dlls. A signature referencing an assembly absent + // from the player build breaks the IL2CPP build; the type-reference + // closure resolves against the editor's full desktop BCL, which on + // Windows reaches editor-only assemblies like Mono.WebBrowser. So collect + // an assembly only if player scripts compile against it. Desktop-only BCL + // assemblies are never player compilation references, while UnityEngine + // modules, the player BCL profile, plugins (including .clj.dlls), and + // user script assemblies all are. + static HashSet CollectPlayerReferenceNames() { - return !assy.FullName.StartsWith("Unity") || assy.FullName.StartsWith("UnityEngine"); + var names = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var assembly in CompilationPipeline.GetAssemblies(AssembliesType.PlayerWithoutTestAssemblies)) + { + names.Add(assembly.name); + foreach (var reference in assembly.allReferences) + { + names.Add(System.IO.Path.GetFileNameWithoutExtension(reference)); + } + } + return names; + } + static bool ShouldCollectReferencedAssembly(AssemblyDefinition assy) + { + return PlayerReferenceNames.Contains(assy.Name.Name); } static HashSet CollectAllReferencedAssemblies(AssemblyDefinition assydef, HashSet seen = null) @@ -51,7 +77,7 @@ static HashSet CollectAllReferencedAssemblies(AssemblyDefini } else { - UnityEngine.Debug.Log($"[CollectAllReferencedAssemblies] Skip {resolved.Module.Assembly}"); + UnityEngine.Debug.Log($"[CollectAllReferencedAssemblies] Skip {resolved.Module.Assembly} (not a player compilation reference)"); } } } @@ -66,6 +92,18 @@ static HashSet CollectAllReferencedAssemblies(AssemblyDefini public static void Init() { + PlayerReferenceNames = CollectPlayerReferenceNames(); + // A degenerate reference set would silently turn workaround + // generation into a no-op: the build stays green and devices throw + // ExecutionEngineException at runtime. Fail the build instead. Any + // sane player reference set contains a core library and at least + // one UnityEngine module. + if (!(PlayerReferenceNames.Contains("mscorlib") || PlayerReferenceNames.Contains("netstandard")) + || !PlayerReferenceNames.Any(n => n.StartsWith("UnityEngine"))) + { + throw new InvalidOperationException($"[Magic.Unity] player compilation reference set looks degenerate ({PlayerReferenceNames.Count} entries), refusing to generate IL2CPP workarounds from it"); + } + UnityEngine.Debug.Log($"[CollectAllReferencedAssemblies] player compilation references: {string.Join(",", PlayerReferenceNames.OrderBy(n => n))}"); var assemblyCSharp = AssemblyDefinition.ReadAssembly("Library/ScriptAssemblies/Assembly-CSharp.dll"); var referencedAssemblies = CollectAllReferencedAssemblies(assemblyCSharp); UnityEngine.Debug.Log($"[CollectAllReferencedAssemblies] {string.Join(",", referencedAssemblies)}"); From 72ad4f81b4795e14a8003c9151dce7705c22e553 Mon Sep 17 00:00:00 2001 From: loicb Date: Fri, 5 Jun 2026 11:46:45 +0800 Subject: [PATCH 2/2] chore(release): v0.5.1 --- CHANGELOG.md | 7 +++++++ magic-unity/package.json | 2 +- version.edn | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab7b1435..5d52d712 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## v0.5.1 - 2026-06-05 + +Hotfix for Windows IL2CPP builds in the Unity package. + +### Magic.Unity +- IL2CPP workaround generation selects signature assemblies from the player compilation reference set (`CompilationPipeline`) instead of a Unity name-prefix check, so editor-only desktop assemblies (`Mono.WebBrowser`, reached through a `csc.rsp` `System.Web` reference on Windows) no longer leak into emitted signatures and break the build. Keep and skip decisions are logged, and a degenerate reference set fails the build instead of silently emitting no workarounds - [#23](https://github.com/flybot-sg/magic/issues/23). + ## v0.5.0 - 2026-06-04 Consumer quality-of-life fixes from the 0.4.0 rollout. diff --git a/magic-unity/package.json b/magic-unity/package.json index 25423779..15682bb6 100644 --- a/magic-unity/package.json +++ b/magic-unity/package.json @@ -1,6 +1,6 @@ { "name": "sg.flybot.magic.unity", - "version": "0.5.0", + "version": "0.5.1", "displayName": "MAGIC Unity Integration", "description": "The integration of the MAGIC Clojure compiler into Unity", "unity": "2021.2", diff --git a/version.edn b/version.edn index 879b88c2..03443473 100644 --- a/version.edn +++ b/version.edn @@ -1 +1 @@ -{:version "0.5.0"} +{:version "0.5.1"}