Weaver: Weave(AssemblyDefinition). WeaveFromFile code moved into CompilationFinishedHook to prepare for ILPP.

This commit is contained in:
vis2k 2021-08-17 11:49:51 +08:00
parent ba067d30bf
commit 5f93a7ce7e
2 changed files with 69 additions and 51 deletions

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Mono.CecilX;
using UnityEditor; using UnityEditor;
using UnityEditor.Compilation; using UnityEditor.Compilation;
using UnityEngine; using UnityEngine;
@ -139,7 +140,7 @@ static void OnCompilationFinished(string assemblyPath, CompilerMessage[] message
Log.Warning = HandleWarning; Log.Warning = HandleWarning;
Log.Error = HandleError; Log.Error = HandleError;
if (!Weaver.Weave(assemblyPath, dependencyPaths.ToArray())) if (!WeaveFromFile(assemblyPath, dependencyPaths.ToArray()))
{ {
// Set false...will be checked in \Editor\EnterPlayModeSettingsCheck.CheckSuccessfulWeave() // Set false...will be checked in \Editor\EnterPlayModeSettingsCheck.CheckSuccessfulWeave()
SessionState.SetBool("MIRROR_WEAVE_SUCCESS", false); SessionState.SetBool("MIRROR_WEAVE_SUCCESS", false);
@ -167,5 +168,29 @@ static HashSet<string> GetDependecyPaths(string assemblyPath)
return dependencyPaths; return dependencyPaths;
} }
// helper function to invoke Weaver with an AssemblyDefinition from a
// file path, with dependencies added.
static bool WeaveFromFile(string assemblyPath, string[] dependencies)
{
// open the file as stream
using (FileStream stream = new FileStream(assemblyPath, FileMode.Open, FileAccess.ReadWrite))
{
using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
using (AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(stream, new ReaderParameters { ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver }))
{
asmResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath));
asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName());
if (dependencies != null)
{
foreach (string path in dependencies)
{
asmResolver.AddSearchDirectory(path);
}
}
return Weaver.Weave(asmDef);
}
}
}
} }
} }

View File

@ -125,72 +125,65 @@ static bool ContainsGeneratedCodeClass(ModuleDefinition module)
td.Name == GeneratedCodeClassName); td.Name == GeneratedCodeClassName);
} }
public static bool Weave(string assName, IEnumerable<string> dependencies) // Weave takes an AssemblyDefinition to be compatible with both old and
// new weavers:
// * old takes a filepath, new takes a in-memory byte[]
// * old uses DefaultAssemblyResolver with added dependencies paths,
// new uses ...?
public static bool Weave(AssemblyDefinition asmDef)
{ {
WeavingFailed = false; WeavingFailed = false;
try try
{ {
using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver()) CurrentAssembly = asmDef;
using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, new ReaderParameters { ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver }))
// fix "No writer found for ..." error
// https://github.com/vis2k/Mirror/issues/2579
// -> when restarting Unity, weaver would try to weave a DLL
// again
// -> resulting in two GeneratedNetworkCode classes (see ILSpy)
// -> the second one wouldn't have all the writer types setup
if (ContainsGeneratedCodeClass(CurrentAssembly.MainModule))
{ {
asmResolver.AddSearchDirectory(Path.GetDirectoryName(assName)); //Log.Warning($"Weaver: skipping {CurrentAssembly.Name} because already weaved");
asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName()); return true;
if (dependencies != null) }
{
foreach (string path in dependencies)
{
asmResolver.AddSearchDirectory(path);
}
}
// fix "No writer found for ..." error WeaverTypes.SetupTargetTypes(CurrentAssembly);
// https://github.com/vis2k/Mirror/issues/2579
// -> when restarting Unity, weaver would try to weave a DLL
// again
// -> resulting in two GeneratedNetworkCode classes (see ILSpy)
// -> the second one wouldn't have all the writer types setup
if (ContainsGeneratedCodeClass(CurrentAssembly.MainModule))
{
//Log.Warning($"Weaver: skipping {CurrentAssembly.Name} because already weaved");
return true;
}
WeaverTypes.SetupTargetTypes(CurrentAssembly); CreateGeneratedCodeClass();
CreateGeneratedCodeClass(); // WeaverList depends on WeaverTypes setup because it uses Import
WeaveLists = new WeaverLists();
// WeaverList depends on WeaverTypes setup because it uses Import System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew();
WeaveLists = new WeaverLists(); // Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages
bool modified = ReaderWriterProcessor.Process(CurrentAssembly);
rwstopwatch.Stop();
Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");
System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew(); ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
// Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages Console.WriteLine($"Script Module: {moduleDefinition.Name}");
bool modified = ReaderWriterProcessor.Process(CurrentAssembly);
rwstopwatch.Stop();
Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");
ModuleDefinition moduleDefinition = CurrentAssembly.MainModule; modified |= WeaveModule(moduleDefinition);
Console.WriteLine($"Script Module: {moduleDefinition.Name}");
modified |= WeaveModule(moduleDefinition); if (WeavingFailed)
{
return false;
}
if (WeavingFailed) if (modified)
{ {
return false; PropertySiteProcessor.Process(moduleDefinition);
}
if (modified) // add class that holds read/write functions
{ moduleDefinition.Types.Add(GeneratedCodeClass);
PropertySiteProcessor.Process(moduleDefinition);
// add class that holds read/write functions ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly);
moduleDefinition.Types.Add(GeneratedCodeClass);
ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly); // write to outputDir if specified, otherwise perform in-place write
WriterParameters writeParams = new WriterParameters { WriteSymbols = true };
// write to outputDir if specified, otherwise perform in-place write CurrentAssembly.Write(writeParams);
WriterParameters writeParams = new WriterParameters { WriteSymbols = true };
CurrentAssembly.Write(writeParams);
}
} }
return true; return true;