public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) { if (!WillProcess(compiledAssembly)) { return(null); } var logger = new Logger(); var weaver = new Weaver(logger); AssemblyDefinition assemblyDefinition = weaver.Weave(compiledAssembly); // write var pe = new MemoryStream(); var pdb = new MemoryStream(); var writerParameters = new WriterParameters { SymbolWriterProvider = new PortablePdbWriterProvider(), SymbolStream = pdb, WriteSymbols = true }; assemblyDefinition?.Write(pe, writerParameters); return(new ILPostProcessResult(new InMemoryAssembly(pe.ToArray(), pdb.ToArray()), logger.Diagnostics)); }
public static AssemblyDefinition Build(IWeaverLogger logger) { AssemblyDefinition assembly = null; var assemblyBuilder = new AssemblyBuilder(Path.Combine(OutputDirectory, OutputFile), SourceFiles.ToArray()) { referencesOptions = ReferencesOptions.UseEngineModules }; if (AllowUnsafe) { assemblyBuilder.compilerOptions.AllowUnsafeCode = true; } assemblyBuilder.buildFinished += delegate(string assemblyPath, CompilerMessage[] compilerMessages) { CompilerMessages.AddRange(compilerMessages); foreach (CompilerMessage cm in compilerMessages) { if (cm.type == CompilerMessageType.Error) { Debug.LogErrorFormat("{0}:{1} -- {2}", cm.file, cm.line, cm.message); CompilerErrors = true; } } // assembly builder does not call ILPostProcessor (WTF Unity?), so we must invoke it ourselves. var compiledAssembly = new CompiledAssembly(assemblyPath) { Defines = assemblyBuilder.defaultDefines, References = assemblyBuilder.defaultReferences }; var weaver = new Weaver(logger); assembly = weaver.Weave(compiledAssembly); }; // Start build of assembly if (!assemblyBuilder.Build()) { Debug.LogErrorFormat("Failed to start build of assembly {0}", assemblyBuilder.assemblyPath); return(assembly); } while (assemblyBuilder.status != AssemblyBuilderStatus.Finished) { System.Threading.Thread.Sleep(10); } return(assembly); }
// helper function to invoke Weaver with an AssemblyDefinition from a // file path, with dependencies added. static bool WeaveFromFile(string assemblyPath, string[] dependencies) { // resolve assembly from stream using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver()) using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters { ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver })) { // add this assembly's path and unity's assembly path asmResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath)); asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName()); // add dependencies if (dependencies != null) { foreach (string path in dependencies) { asmResolver.AddSearchDirectory(path); } } // create weaver with logger weaver = new Weaver(new CompilationFinishedLogger()); if (weaver.Weave(assembly, asmResolver, out bool modified)) { // write changes to file if modified if (modified) { assembly.Write(new WriterParameters { WriteSymbols = true }); } return(true); } return(false); } }
public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) { //Log.Warning($"Processing {compiledAssembly.Name}"); // load the InMemoryAssembly peData into a MemoryStream byte[] peData = compiledAssembly.InMemoryAssembly.PeData; //LogDiagnostics($" peData.Length={peData.Length} bytes"); using (MemoryStream stream = new MemoryStream(peData)) using (ILPostProcessorAssemblyResolver asmResolver = new ILPostProcessorAssemblyResolver(compiledAssembly, Log)) { // we need to load symbols. otherwise we get: // "(0,0): error Mono.CecilX.Cil.SymbolsNotFoundException: No symbol found for file: " using (MemoryStream symbols = new MemoryStream(compiledAssembly.InMemoryAssembly.PdbData)) { ReaderParameters readerParameters = new ReaderParameters { SymbolStream = symbols, ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver, // custom reflection importer to fix System.Private.CoreLib // not being found in custom assembly resolver above. ReflectionImporterProvider = new ILPostProcessorReflectionImporterProvider() }; using (AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(stream, readerParameters)) { // resolving a Mirror.dll type like NetworkServer while // weaving Mirror.dll does not work. it throws a // NullReferenceException in WeaverTypes.ctor // when Resolve() is called on the first Mirror type. // need to add the AssemblyDefinition itself to use. asmResolver.SetAssemblyDefinitionForCompiledAssembly(asmDef); // weave this assembly. Weaver weaver = new Weaver(Log); if (weaver.Weave(asmDef, asmResolver, out bool modified)) { //Log.Warning($"Weaving succeeded for: {compiledAssembly.Name}"); // write if modified if (modified) { // when weaving Mirror.dll with ILPostProcessor, // Weave() -> WeaverTypes -> resolving the first // type in Mirror.dll adds a reference to // Mirror.dll even though we are in Mirror.dll. // -> this would throw an exception: // "Mirror references itself" and not compile // -> need to detect and fix manually here if (asmDef.MainModule.AssemblyReferences.Any(r => r.Name == asmDef.Name.Name)) { asmDef.MainModule.AssemblyReferences.Remove(asmDef.MainModule.AssemblyReferences.First(r => r.Name == asmDef.Name.Name)); //Log.Warning($"fixed self referencing Assembly: {asmDef.Name.Name}"); } MemoryStream peOut = new MemoryStream(); MemoryStream pdbOut = new MemoryStream(); WriterParameters writerParameters = new WriterParameters { SymbolWriterProvider = new PortablePdbWriterProvider(), SymbolStream = pdbOut, WriteSymbols = true }; asmDef.Write(peOut, writerParameters); InMemoryAssembly inMemory = new InMemoryAssembly(peOut.ToArray(), pdbOut.ToArray()); return(new ILPostProcessResult(inMemory, Log.Logs)); } } // if anything during Weave() fails, we log an error. // don't need to indicate 'weaving failed' again. // in fact, this would break tests only expecting certain errors. //else Log.Error($"Weaving failed for: {compiledAssembly.Name}"); } } } // always return an ILPostProcessResult with Logs. // otherwise we won't see Logs if weaving failed. return(new ILPostProcessResult(compiledAssembly.InMemoryAssembly, Log.Logs)); }