Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
44 changes: 41 additions & 3 deletions magic-unity/Editor/GenerateGenericWorkaroundMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Mono.Cecil;
using Mono.Cecil.Rocks;
using Mono.Cecil.Cil;
using UnityEditor.Compilation;

namespace Magic.Unity
{
Expand All @@ -21,10 +22,35 @@ struct DynamicCallSiteInfo
static List<MethodDefinition> AllMethods = new List<MethodDefinition>();
static TypeDefinition MagicRuntimeDelegateHelpers = null;

static bool ShouldCollectReferencedAssembly(AssemblyDefinition assy)
static HashSet<string> 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<string> CollectPlayerReferenceNames()
{
return !assy.FullName.StartsWith("Unity") || assy.FullName.StartsWith("UnityEngine");
var names = new HashSet<string>(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<AssemblyDefinition> CollectAllReferencedAssemblies(AssemblyDefinition assydef, HashSet<AssemblyDefinition> seen = null)
Expand All @@ -51,7 +77,7 @@ static HashSet<AssemblyDefinition> CollectAllReferencedAssemblies(AssemblyDefini
}
else
{
UnityEngine.Debug.Log($"[CollectAllReferencedAssemblies] Skip {resolved.Module.Assembly}");
UnityEngine.Debug.Log($"[CollectAllReferencedAssemblies] Skip {resolved.Module.Assembly} (not a player compilation reference)");
}
}
}
Expand All @@ -66,6 +92,18 @@ static HashSet<AssemblyDefinition> 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)}");
Expand Down
2 changes: 1 addition & 1 deletion magic-unity/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
2 changes: 1 addition & 1 deletion version.edn
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{:version "0.5.0"}
{:version "0.5.1"}
Loading