// Returns true when compilation is finished due to one of these reasons // * Was stopped (CompilationTask.Stopped will be true) // * Compilation had errors (CompilationTask.CompileErrors will be true) // * Compilation succesfully completed without errors. public bool Poll() { HandleOnCompilationTaskStarted(); if (Stopped) { HandleOnCompilationTaskFinished(); return(true); } Dictionary <ScriptAssembly, ScriptCompilerBase> finishedCompilerTasks = null; // Check if any compiler processes are finished. foreach (var task in compilerTasks) { var compiler = task.Value; // Did compiler task finish? if (compiler.Poll()) { if (finishedCompilerTasks == null) { finishedCompilerTasks = new Dictionary <ScriptAssembly, ScriptCompilerBase>(); } var assembly = task.Key; finishedCompilerTasks.Add(assembly, compiler); } } // Save compiler messages from finished compiler processes and check for compile errors. if (finishedCompilerTasks != null) { foreach (var task in finishedCompilerTasks) { var assembly = task.Key; var compiler = task.Value; var messages = compiler.GetCompilerMessages(); var messagesList = messages.ToList(); compiledAssemblies.Add(assembly, messagesList.ToArray()); if (RunPostProcessors && !messagesList.Any(m => m.type == CompilerMessageType.Error)) { var sourcePath = AssetPath.Combine(buildOutputDirectory, assembly.Filename); try { File.Copy(sourcePath, assembly.FullPath, true); var postProcessorTask = new PostProcessorTask(assembly, messagesList, buildOutputDirectory, postProcessFunc); postProcessorTask.Poll(); OnPostProcessingStarted?.Invoke(assembly); postProcessorTasks.Add(postProcessorTask); } catch (IOException e) { UnityEngine.Debug.LogError($"Fail to copy {sourcePath} to {assembly.FullPath} before post processing the assembly. Skipping post processing.\n{e}"); // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(assembly, messagesList); processedAssemblies.Add(assembly, messagesList.ToArray()); } } else { // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(assembly, messagesList); processedAssemblies.Add(assembly, messagesList.ToArray()); } if (!CompileErrors) { CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); } compilerTasks.Remove(assembly); compiler.Dispose(); } } HashSet <PostProcessorTask> finishedPostProcessorTasks = null; foreach (var postProcessorTask in postProcessorTasks) { // We break out of this loop instead to continuing to ensure that // OnCompilationFinished events are emitted in the same order as // they finished compiling. if (!postProcessorTask.Poll()) { break; } // Do not copy the post processed assembly in OnCompilationFinished // if any of the running compilers have a reference to the assembly. // As we might copy it while the compiler has the assembly open. if (AnyRunningCompilerHasReference(postProcessorTask.Assembly)) { break; } var messagesList = postProcessorTask.CompilerMessages; // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(postProcessorTask.Assembly, messagesList); processedAssemblies.Add(postProcessorTask.Assembly, messagesList.ToArray()); if (!CompileErrors) { CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); } if (finishedPostProcessorTasks == null) { finishedPostProcessorTasks = new HashSet <PostProcessorTask>(); } finishedPostProcessorTasks.Add(postProcessorTask); } if (finishedPostProcessorTasks != null) { foreach (var finishedPostProcessorTask in finishedPostProcessorTasks) { postProcessorTasks.Remove(finishedPostProcessorTask); } } // If StopOnFirstError is set, do not queue assemblies for compilation in case of compile errors. bool stopOnFirstError = (compilationTaskOptions & CompilationTaskOptions.StopOnFirstError) == CompilationTaskOptions.StopOnFirstError; if (stopOnFirstError && CompileErrors) { pendingAssemblies.Clear(); if (FinishedCompilation) { HandleOnCompilationTaskFinished(); } return(FinishedCompilation); } // Queue pending assemblies for compilation if we have no running compilers or if compilers have finished. if (compilerTasks.Count == 0 || (finishedCompilerTasks != null && finishedCompilerTasks.Count > 0)) { QueuePendingAssemblies(); } if (FinishedCompilation) { HandleOnCompilationTaskFinished(); } return(FinishedCompilation); }
void PollPostProcessors() { if (pendingPostProcessorTasks.Count == 0 && postProcessorTasks.Count == 0) { return; } // Not all codegen assemblies have been compiled yet. if (!AreAllCodegenAssembliesCompiled) { // If any codegen assemblies are not getting compiled, clear // pending il post processing tasks. if (notCompiledCodeGenAssemblies.Any()) { pendingPostProcessorTasks.Clear(); } return; } List <PostProcessorTask> startedPostProcessorTasks = null; // Check if any pending post processors can be run foreach (var postProcessorTask in pendingPostProcessorTasks) { if (RunningMaxConcurrentProcesses) { break; } var assembly = postProcessorTask.Assembly; // We break out of this loop instead to continuing to ensure that // OnCompilationFinished events are emitted in the same order as // they finished compiling. if (IsAnyProcessUsingAssembly(assembly)) { break; } if (startedPostProcessorTasks == null) { startedPostProcessorTasks = new List <PostProcessorTask>(); } startedPostProcessorTasks.Add(postProcessorTask); postProcessorTask.Start(); LogStartInfo($"# Starting IL post processing on {assembly.Filename}", postProcessorTask.GetProcessStartInfo()); OnPostProcessingStarted?.Invoke(assembly); postProcessorTasks.Add(postProcessorTask); } if (startedPostProcessorTasks != null) { foreach (var postProcessorTask in startedPostProcessorTasks) { pendingPostProcessorTasks.Remove(postProcessorTask); } } HashSet <PostProcessorTask> finishedPostProcessorTasks = null; foreach (var postProcessorTask in postProcessorTasks) { // We break out of this loop instead to continuing to ensure that // OnCompilationFinished events are emitted in the same order as // they finished compiling. if (!postProcessorTask.Poll()) { break; } // Do not copy the post processed assembly in OnCompilationFinished // if any of the running compilers have a reference to the assembly. // As we might copy it while the compiler has the assembly open. if (IsAnyProcessUsingAssembly(postProcessorTask.Assembly)) { break; } var messagesList = postProcessorTask.GetCompilerMessages(); // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(postProcessorTask.Assembly, messagesList); processedAssemblies.Add(postProcessorTask.Assembly, messagesList.ToArray()); if (!CompileErrors) { CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); } if (finishedPostProcessorTasks == null) { finishedPostProcessorTasks = new HashSet <PostProcessorTask>(); } finishedPostProcessorTasks.Add(postProcessorTask); } if (finishedPostProcessorTasks != null) { foreach (var finishedPostProcessorTask in finishedPostProcessorTasks) { finishedPostProcessorTask.Dispose(); postProcessorTasks.Remove(finishedPostProcessorTask); } } }