private static void TickCompile() { if (CurrentJob == null) return; if (!CurrentJob.Task.IsCompleted) { CompilationContext.CompilePhase currentPhase = CurrentJob.Context.CurrentPhase; float phaseProgress = CurrentJob.Context.PhaseProgress; float totalProgress = (phaseProgress / (int) CompilationContext.CompilePhase.Count) + ((int) currentPhase / (float)(int)CompilationContext.CompilePhase.Count); UdonSharpUtils.ShowAsyncProgressBar($"U#: {currentPhase}", totalProgress); return; } if (!CurrentJob.CompileOptions.DisableLogging) { foreach (var diagnostic in CurrentJob.Context.Diagnostics) { string filePath = ""; if (diagnostic.Location != null) filePath = CurrentJob.Context.TranslateLocationToFileName(diagnostic.Location); LinePosition? linePosition = diagnostic.Location?.GetLineSpan().StartLinePosition; int line = (linePosition?.Line ?? 0) + 1; int character = (linePosition?.Character ?? 0) + 1; string fileStr = $"{filePath ?? "Unknown File"}({line},{character})"; string logStr = $"{fileStr}: {diagnostic.Message}"; switch (diagnostic.Severity) { case DiagnosticSeverity.Error: UdonSharpUtils.LogBuildError(diagnostic.Message, filePath, line, character); break; case DiagnosticSeverity.Warning: UdonSharpUtils.LogWarning(logStr); break; case DiagnosticSeverity.Log: UdonSharpUtils.Log(logStr); break; } } } // Translate the diagnostic types and apply them to the cache, todo: consider merging the two structures UdonSharpEditorCache.CompileDiagnostic[] diagnostics = new UdonSharpEditorCache.CompileDiagnostic[CurrentJob.Context.Diagnostics.Count]; CompilationContext.CompileDiagnostic[] compileDiagnostics = CurrentJob.Context.Diagnostics.ToArray(); for (int i = 0; i < diagnostics.Length; ++i) { LinePosition diagLine = compileDiagnostics[i]?.Location?.GetLineSpan().StartLinePosition ?? LinePosition.Zero; diagnostics[i] = new UdonSharpEditorCache.CompileDiagnostic() { severity = compileDiagnostics[i].Severity, message = compileDiagnostics[i].Message, file = CurrentJob.Context.TranslateLocationToFileName(compileDiagnostics[i].Location) ?? "", line = diagLine.Line, character = diagLine.Character, }; } UdonSharpEditorCache.Instance.LastCompileDiagnostics = diagnostics; if (CurrentJob.Task.IsFaulted) { UdonSharpUtils.LogError("internal compiler error, dumping exceptions. Please report to Merlin"); if (CurrentJob.Task.Exception != null) { foreach (Exception innerException in CurrentJob.Task.Exception.InnerExceptions) { UdonSharpUtils.LogError(innerException); } } CleanupCompile(); return; } if (CurrentJob.Context.ErrorCount > 0) { CleanupCompile(); return; } foreach (ModuleBinding rootBinding in CurrentJob.Context.ModuleBindings) { if (rootBinding.programAsset == null) continue; rootBinding.programAsset.ApplyProgram(); UdonSharpEditorCache.Instance.SetUASMStr(rootBinding.programAsset, rootBinding.assembly); rootBinding.programAsset.CompiledVersion = UdonSharpProgramVersion.CurrentVersion; EditorUtility.SetDirty(rootBinding.programAsset); } try { UdonSharpEditorCache.Instance.RehashAllScripts(); UdonSharpEditorManager.RunPostBuildSceneFixup(); } catch (Exception e) { UdonSharpUtils.LogError($"Exception while running post build fixup:\n{e}"); CleanupCompile(); return; } UdonSharpEditorCache.Instance.LastBuildType = CurrentJob.CompileOptions.IsEditorBuild ? UdonSharpEditorCache.DebugInfoType.Editor : UdonSharpEditorCache.DebugInfoType.Client; int scriptCount = CurrentJob.Context.ModuleBindings.Count(e => e.programAsset != null); UdonSharpUtils.Log($"Compile of {scriptCount} script{(scriptCount != 1 ? "s" : "")} finished in {CurrentJob.CompileTimer.Elapsed:mm\\:ss\\.fff}"); CleanupCompile(); if (_compileQueued) { Compile(_queuedOptions); _compileQueued = false; _queuedOptions = null; } }
public static void CompileSync(UdonSharpCompileOptions options = null) { WaitForCompile(); Compile(options); WaitForCompile(); }
public static void Compile(UdonSharpCompileOptions options = null) { if (options == null) options = new UdonSharpCompileOptions(); if (UdonSharpUtils.DoesUnityProjectHaveCompileErrors()) { UdonSharpUtils.LogError("All Unity C# compiler errors must be resolved before running an UdonSharp compile."); return; } if (CurrentJob != null) { _compileQueued = true; _queuedOptions = options; return; } Localization.Loc.InitLocalization(); UdonSharpProgramAsset[] allPrograms = UdonSharpProgramAsset.GetAllUdonSharpPrograms(); bool hasError = !ValidateProgramAssetCollisions(allPrograms); Dictionary<string, ProgramAssetInfo> rootProgramLookup = new Dictionary<string, ProgramAssetInfo>(); foreach (UdonSharpProgramAsset udonSharpProgram in allPrograms) { if (udonSharpProgram.sourceCsScript == null) { UdonSharpUtils.LogError($"Source C# script on {udonSharpProgram} is null", udonSharpProgram); hasError = true; continue; } string assetPath = AssetDatabase.GetAssetPath(udonSharpProgram.sourceCsScript); if (string.IsNullOrEmpty(assetPath)) { UdonSharpUtils.LogError($"Source C# script on {udonSharpProgram} is null", udonSharpProgram); hasError = true; continue; } rootProgramLookup.Add(assetPath.Replace('\\', '/'), new ProgramAssetInfo() { programAsset = udonSharpProgram ? udonSharpProgram : null, scriptClass = udonSharpProgram != null ? udonSharpProgram.GetClass() : null }); } if (hasError) { UdonSharpEditorCache.Instance.LastCompileDiagnostics = new [] { new UdonSharpEditorCache.CompileDiagnostic() { file = "", message = "Compile validation failed, check console output for details.", severity = DiagnosticSeverity.Error, } }; return; } // var allSourcePaths = new HashSet<string>(UdonSharpProgramAsset.GetAllUdonSharpPrograms().Where(e => e.isV1Root).Select(e => AssetDatabase.GetAssetPath(e.sourceCsScript).Replace('\\', '/'))); HashSet<string> allSourcePaths = new HashSet<string>(CompilationContext.GetAllFilteredSourcePaths(options.IsEditorBuild)); if (!ValidateUdonSharpBehaviours(allPrograms, allSourcePaths)) return; CompilationContext compilationContext = new CompilationContext(options); string[] defines = UdonSharpUtils.GetProjectDefines(options.IsEditorBuild); EditorApplication.LockReloadAssemblies(); Task compileTask = new Task(() => Compile(compilationContext, rootProgramLookup, allSourcePaths, defines)); CurrentJob = new CompileJob() { Context = compilationContext, Task = compileTask, CompileTimer = Stopwatch.StartNew(), CompileOptions = options }; compileTask.Start(); }
public CompilationContext(UdonSharpCompileOptions options) { Options = options; }