From 5f93a7ce7ecb989817c74769d677ffeb6ba8c533 Mon Sep 17 00:00:00 2001 From: vis2k Date: Tue, 17 Aug 2021 11:49:51 +0800 Subject: [PATCH] Weaver: Weave(AssemblyDefinition). WeaveFromFile code moved into CompilationFinishedHook to prepare for ILPP. --- .../EntryPoint/CompilationFinishedHook.cs | 27 +++++- Assets/Mirror/Editor/Weaver/Weaver.cs | 93 +++++++++---------- 2 files changed, 69 insertions(+), 51 deletions(-) diff --git a/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs index 635c3dd91..41cc90378 100644 --- a/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs +++ b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Mono.CecilX; using UnityEditor; using UnityEditor.Compilation; using UnityEngine; @@ -139,7 +140,7 @@ static void OnCompilationFinished(string assemblyPath, CompilerMessage[] message Log.Warning = HandleWarning; Log.Error = HandleError; - if (!Weaver.Weave(assemblyPath, dependencyPaths.ToArray())) + if (!WeaveFromFile(assemblyPath, dependencyPaths.ToArray())) { // Set false...will be checked in \Editor\EnterPlayModeSettingsCheck.CheckSuccessfulWeave() SessionState.SetBool("MIRROR_WEAVE_SUCCESS", false); @@ -167,5 +168,29 @@ static HashSet GetDependecyPaths(string assemblyPath) 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); + } + } + } } } diff --git a/Assets/Mirror/Editor/Weaver/Weaver.cs b/Assets/Mirror/Editor/Weaver/Weaver.cs index e7ea60339..e94a5f459 100644 --- a/Assets/Mirror/Editor/Weaver/Weaver.cs +++ b/Assets/Mirror/Editor/Weaver/Weaver.cs @@ -125,72 +125,65 @@ static bool ContainsGeneratedCodeClass(ModuleDefinition module) td.Name == GeneratedCodeClassName); } - public static bool Weave(string assName, IEnumerable 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; try { - using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver()) - using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, new ReaderParameters { ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver })) + CurrentAssembly = asmDef; + + // 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)); - asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName()); - if (dependencies != null) - { - foreach (string path in dependencies) - { - asmResolver.AddSearchDirectory(path); - } - } + //Log.Warning($"Weaver: skipping {CurrentAssembly.Name} because already weaved"); + return true; + } - // 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)) - { - //Log.Warning($"Weaver: skipping {CurrentAssembly.Name} because already weaved"); - return true; - } + WeaverTypes.SetupTargetTypes(CurrentAssembly); - 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 - WeaveLists = new WeaverLists(); + System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew(); + // 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(); - // 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"); + ModuleDefinition moduleDefinition = CurrentAssembly.MainModule; + Console.WriteLine($"Script Module: {moduleDefinition.Name}"); - ModuleDefinition moduleDefinition = CurrentAssembly.MainModule; - Console.WriteLine($"Script Module: {moduleDefinition.Name}"); + modified |= WeaveModule(moduleDefinition); - modified |= WeaveModule(moduleDefinition); + if (WeavingFailed) + { + return false; + } - if (WeavingFailed) - { - return false; - } + if (modified) + { + PropertySiteProcessor.Process(moduleDefinition); - if (modified) - { - PropertySiteProcessor.Process(moduleDefinition); + // add class that holds read/write functions + moduleDefinition.Types.Add(GeneratedCodeClass); - // add class that holds read/write functions - moduleDefinition.Types.Add(GeneratedCodeClass); + ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly); - ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly); - - // write to outputDir if specified, otherwise perform in-place write - WriterParameters writeParams = new WriterParameters { WriteSymbols = true }; - CurrentAssembly.Write(writeParams); - } + // write to outputDir if specified, otherwise perform in-place write + WriterParameters writeParams = new WriterParameters { WriteSymbols = true }; + CurrentAssembly.Write(writeParams); } return true;