Exemplo n.º 1
0
        // 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);
        }
Exemplo n.º 2
0
        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);
                }
            }
        }