Merge pull request #72061 from paulloz/csharp/better-logs-management
C#: MSBuild logs and panel enhancements
This commit is contained in:
commit
8be4feec04
@ -22,8 +22,7 @@ namespace GodotTools.Build
|
||||
// TODO Use List once we have proper serialization
|
||||
public Godot.Collections.Array CustomProperties { get; private set; } = new();
|
||||
|
||||
public string LogsDirPath =>
|
||||
Path.Combine(GodotSharpDirs.BuildLogsDirs, $"{Solution.Md5Text()}_{Configuration}");
|
||||
public string LogsDirPath => GodotSharpDirs.LogsDirPathFor(Solution, Configuration);
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
|
@ -7,6 +7,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Godot;
|
||||
using GodotTools.BuildLogger;
|
||||
using GodotTools.Utils;
|
||||
|
||||
@ -22,9 +23,11 @@ namespace GodotTools.Build
|
||||
if (dotnetPath == null)
|
||||
throw new FileNotFoundException("Cannot find the dotnet executable.");
|
||||
|
||||
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
||||
|
||||
var startInfo = new ProcessStartInfo(dotnetPath);
|
||||
|
||||
BuildArguments(buildInfo, startInfo.ArgumentList);
|
||||
BuildArguments(buildInfo, startInfo.ArgumentList, editorSettings);
|
||||
|
||||
string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString();
|
||||
stdOutHandler?.Invoke(launchMessage);
|
||||
@ -35,6 +38,8 @@ namespace GodotTools.Build
|
||||
startInfo.RedirectStandardError = true;
|
||||
startInfo.UseShellExecute = false;
|
||||
startInfo.CreateNoWindow = true;
|
||||
startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"]
|
||||
= ((string)editorSettings.GetSetting("interface/editor/editor_language")).Replace('_', '-');
|
||||
|
||||
// Needed when running from Developer Command Prompt for VS
|
||||
RemovePlatformVariable(startInfo.EnvironmentVariables);
|
||||
@ -83,9 +88,11 @@ namespace GodotTools.Build
|
||||
if (dotnetPath == null)
|
||||
throw new FileNotFoundException("Cannot find the dotnet executable.");
|
||||
|
||||
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
||||
|
||||
var startInfo = new ProcessStartInfo(dotnetPath);
|
||||
|
||||
BuildPublishArguments(buildInfo, startInfo.ArgumentList);
|
||||
BuildPublishArguments(buildInfo, startInfo.ArgumentList, editorSettings);
|
||||
|
||||
string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString();
|
||||
stdOutHandler?.Invoke(launchMessage);
|
||||
@ -95,6 +102,8 @@ namespace GodotTools.Build
|
||||
startInfo.RedirectStandardOutput = true;
|
||||
startInfo.RedirectStandardError = true;
|
||||
startInfo.UseShellExecute = false;
|
||||
startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"]
|
||||
= ((string)editorSettings.GetSetting("interface/editor/editor_language")).Replace('_', '-');
|
||||
|
||||
// Needed when running from Developer Command Prompt for VS
|
||||
RemovePlatformVariable(startInfo.EnvironmentVariables);
|
||||
@ -124,7 +133,8 @@ namespace GodotTools.Build
|
||||
}
|
||||
}
|
||||
|
||||
private static void BuildArguments(BuildInfo buildInfo, Collection<string> arguments)
|
||||
private static void BuildArguments(BuildInfo buildInfo, Collection<string> arguments,
|
||||
EditorSettings editorSettings)
|
||||
{
|
||||
// `dotnet clean` / `dotnet build` commands
|
||||
arguments.Add(buildInfo.OnlyClean ? "clean" : "build");
|
||||
@ -150,12 +160,14 @@ namespace GodotTools.Build
|
||||
arguments.Add(buildInfo.Configuration);
|
||||
|
||||
// Verbosity
|
||||
arguments.Add("-v");
|
||||
arguments.Add("normal");
|
||||
AddVerbosityArguments(buildInfo, arguments, editorSettings);
|
||||
|
||||
// Logger
|
||||
AddLoggerArgument(buildInfo, arguments);
|
||||
|
||||
// Binary log
|
||||
AddBinaryLogArgument(buildInfo, arguments, editorSettings);
|
||||
|
||||
// Custom properties
|
||||
foreach (var customProperty in buildInfo.CustomProperties)
|
||||
{
|
||||
@ -163,7 +175,8 @@ namespace GodotTools.Build
|
||||
}
|
||||
}
|
||||
|
||||
private static void BuildPublishArguments(BuildInfo buildInfo, Collection<string> arguments)
|
||||
private static void BuildPublishArguments(BuildInfo buildInfo, Collection<string> arguments,
|
||||
EditorSettings editorSettings)
|
||||
{
|
||||
arguments.Add("publish"); // `dotnet publish` command
|
||||
|
||||
@ -193,12 +206,14 @@ namespace GodotTools.Build
|
||||
arguments.Add("true");
|
||||
|
||||
// Verbosity
|
||||
arguments.Add("-v");
|
||||
arguments.Add("normal");
|
||||
AddVerbosityArguments(buildInfo, arguments, editorSettings);
|
||||
|
||||
// Logger
|
||||
AddLoggerArgument(buildInfo, arguments);
|
||||
|
||||
// Binary log
|
||||
AddBinaryLogArgument(buildInfo, arguments, editorSettings);
|
||||
|
||||
// Custom properties
|
||||
foreach (var customProperty in buildInfo.CustomProperties)
|
||||
{
|
||||
@ -213,6 +228,25 @@ namespace GodotTools.Build
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddVerbosityArguments(BuildInfo buildInfo, Collection<string> arguments,
|
||||
EditorSettings editorSettings)
|
||||
{
|
||||
var verbosityLevel =
|
||||
editorSettings.GetSetting(GodotSharpEditor.Settings.VerbosityLevel).As<VerbosityLevelId>();
|
||||
arguments.Add("-v");
|
||||
arguments.Add(verbosityLevel switch
|
||||
{
|
||||
VerbosityLevelId.Quiet => "quiet",
|
||||
VerbosityLevelId.Minimal => "minimal",
|
||||
VerbosityLevelId.Detailed => "detailed",
|
||||
VerbosityLevelId.Diagnostic => "diagnostic",
|
||||
_ => "normal",
|
||||
});
|
||||
|
||||
if ((bool)editorSettings.GetSetting(GodotSharpEditor.Settings.NoConsoleLogging))
|
||||
arguments.Add("-noconlog");
|
||||
}
|
||||
|
||||
private static void AddLoggerArgument(BuildInfo buildInfo, Collection<string> arguments)
|
||||
{
|
||||
string buildLoggerPath = Path.Combine(Internals.GodotSharpDirs.DataEditorToolsDir,
|
||||
@ -222,6 +256,16 @@ namespace GodotTools.Build
|
||||
$"-l:{typeof(GodotBuildLogger).FullName},{buildLoggerPath};{buildInfo.LogsDirPath}");
|
||||
}
|
||||
|
||||
private static void AddBinaryLogArgument(BuildInfo buildInfo, Collection<string> arguments,
|
||||
EditorSettings editorSettings)
|
||||
{
|
||||
if (!(bool)editorSettings.GetSetting(GodotSharpEditor.Settings.CreateBinaryLog))
|
||||
return;
|
||||
|
||||
arguments.Add($"-bl:{Path.Combine(buildInfo.LogsDirPath, "msbuild.binlog")}");
|
||||
arguments.Add("-ds:False"); // Honestly never understood why -bl also switches -ds on.
|
||||
}
|
||||
|
||||
private static void RemovePlatformVariable(StringDictionary environmentVariables)
|
||||
{
|
||||
// EnvironmentVariables is case sensitive? Seriously?
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Godot;
|
||||
using GodotTools.Internals;
|
||||
using static GodotTools.Internals.Globals;
|
||||
@ -14,6 +15,7 @@ namespace GodotTools.Build
|
||||
private Button _errorsBtn;
|
||||
private Button _warningsBtn;
|
||||
private Button _viewLogBtn;
|
||||
private Button _openLogsFolderBtn;
|
||||
|
||||
private void WarningsToggled(bool pressed)
|
||||
{
|
||||
@ -93,6 +95,10 @@ namespace GodotTools.Build
|
||||
|
||||
private void ViewLogToggled(bool pressed) => BuildOutputView.LogVisible = pressed;
|
||||
|
||||
private void OpenLogsFolderPressed() => OS.ShellOpen(
|
||||
$"file://{GodotSharpDirs.LogsDirPathFor("Debug")}"
|
||||
);
|
||||
|
||||
private void BuildMenuOptionPressed(long id)
|
||||
{
|
||||
switch ((BuildMenuOptions)id)
|
||||
@ -171,6 +177,22 @@ namespace GodotTools.Build
|
||||
_viewLogBtn.Toggled += ViewLogToggled;
|
||||
toolBarHBox.AddChild(_viewLogBtn);
|
||||
|
||||
// Horizontal spacer, push everything to the right.
|
||||
toolBarHBox.AddChild(new Control
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.ExpandFill,
|
||||
});
|
||||
|
||||
_openLogsFolderBtn = new Button
|
||||
{
|
||||
Text = "Show Logs in File Manager".TTR(),
|
||||
Icon = GetThemeIcon("Filesystem", "EditorIcons"),
|
||||
ExpandIcon = false,
|
||||
FocusMode = FocusModeEnum.None,
|
||||
};
|
||||
_openLogsFolderBtn.Pressed += OpenLogsFolderPressed;
|
||||
toolBarHBox.AddChild(_openLogsFolderBtn);
|
||||
|
||||
BuildOutputView = new BuildOutputView();
|
||||
AddChild(BuildOutputView);
|
||||
}
|
||||
|
@ -22,6 +22,14 @@ namespace GodotTools
|
||||
{
|
||||
public partial class GodotSharpEditor : EditorPlugin, ISerializationListener
|
||||
{
|
||||
public static class Settings
|
||||
{
|
||||
public const string ExternalEditor = "dotnet/editor/external_editor";
|
||||
public const string VerbosityLevel = "dotnet/build/verbosity_level";
|
||||
public const string NoConsoleLogging = "dotnet/build/no_console_logging";
|
||||
public const string CreateBinaryLog = "dotnet/build/create_binary_log";
|
||||
}
|
||||
|
||||
private EditorSettings _editorSettings;
|
||||
|
||||
private PopupMenu _menuPopup;
|
||||
@ -171,7 +179,7 @@ namespace GodotTools
|
||||
[UsedImplicitly]
|
||||
public Error OpenInExternalEditor(Script script, int line, int col)
|
||||
{
|
||||
var editorId = (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor");
|
||||
var editorId = _editorSettings.GetSetting(Settings.ExternalEditor).As<ExternalEditorId>();
|
||||
|
||||
switch (editorId)
|
||||
{
|
||||
@ -323,8 +331,7 @@ namespace GodotTools
|
||||
[UsedImplicitly]
|
||||
public bool OverridesExternalEditor()
|
||||
{
|
||||
return (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor") !=
|
||||
ExternalEditorId.None;
|
||||
return _editorSettings.GetSetting(Settings.ExternalEditor).As<ExternalEditorId>() != ExternalEditorId.None;
|
||||
}
|
||||
|
||||
public override bool _Build()
|
||||
@ -453,7 +460,10 @@ namespace GodotTools
|
||||
_menuPopup.IdPressed += _MenuOptionPressed;
|
||||
|
||||
// External editor settings
|
||||
EditorDef("mono/editor/external_editor", Variant.From(ExternalEditorId.None));
|
||||
EditorDef(Settings.ExternalEditor, Variant.From(ExternalEditorId.None));
|
||||
EditorDef(Settings.VerbosityLevel, Variant.From(VerbosityLevelId.Normal));
|
||||
EditorDef(Settings.NoConsoleLogging, false);
|
||||
EditorDef(Settings.CreateBinaryLog, false);
|
||||
|
||||
string settingsHintStr = "Disabled";
|
||||
|
||||
@ -481,11 +491,23 @@ namespace GodotTools
|
||||
_editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
||||
{
|
||||
["type"] = (int)Variant.Type.Int,
|
||||
["name"] = "mono/editor/external_editor",
|
||||
["name"] = Settings.ExternalEditor,
|
||||
["hint"] = (int)PropertyHint.Enum,
|
||||
["hint_string"] = settingsHintStr
|
||||
});
|
||||
|
||||
var verbosityLevels = Enum.GetValues<VerbosityLevelId>().Select(level => $"{Enum.GetName(level)}:{(int)level}");
|
||||
_editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
||||
{
|
||||
["type"] = (int)Variant.Type.Int,
|
||||
["name"] = Settings.VerbosityLevel,
|
||||
["hint"] = (int)PropertyHint.Enum,
|
||||
["hint_string"] = string.Join(",", verbosityLevels),
|
||||
});
|
||||
|
||||
OnSettingsChanged();
|
||||
_editorSettings.SettingsChanged += OnSettingsChanged;
|
||||
|
||||
// Export plugin
|
||||
var exportPlugin = new ExportPlugin();
|
||||
AddExportPlugin(exportPlugin);
|
||||
@ -510,6 +532,24 @@ namespace GodotTools
|
||||
AddChild(GodotIdeManager);
|
||||
}
|
||||
|
||||
public override void _DisablePlugin()
|
||||
{
|
||||
base._DisablePlugin();
|
||||
|
||||
_editorSettings.SettingsChanged -= OnSettingsChanged;
|
||||
}
|
||||
|
||||
private void OnSettingsChanged()
|
||||
{
|
||||
// We want to force NoConsoleLogging to true when the VerbosityLevel is at Detailed or above.
|
||||
// At that point, there's so much info logged that it doesn't make sense to display it in
|
||||
// the tiny editor window, and it'd make the editor hang or crash anyway.
|
||||
var verbosityLevel = _editorSettings.GetSetting(Settings.VerbosityLevel).As<VerbosityLevelId>();
|
||||
var hideConsoleLog = (bool)_editorSettings.GetSetting(Settings.NoConsoleLogging);
|
||||
if (verbosityLevel >= VerbosityLevelId.Detailed && !hideConsoleLog)
|
||||
_editorSettings.SetSetting(Settings.NoConsoleLogging, Variant.From(true));
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
|
@ -21,7 +21,8 @@ namespace GodotTools.Ides
|
||||
return _messagingServer;
|
||||
|
||||
_messagingServer?.Dispose();
|
||||
_messagingServer = new MessagingServer(OS.GetExecutablePath(), ProjectSettings.GlobalizePath(GodotSharpDirs.ResMetadataDir), new GodotLogger());
|
||||
_messagingServer = new MessagingServer(OS.GetExecutablePath(),
|
||||
ProjectSettings.GlobalizePath(GodotSharpDirs.ResMetadataDir), new GodotLogger());
|
||||
|
||||
_ = _messagingServer.Listen();
|
||||
|
||||
@ -76,8 +77,8 @@ namespace GodotTools.Ides
|
||||
|
||||
public async Task<EditorPick?> LaunchIdeAsync(int millisecondsTimeout = 10000)
|
||||
{
|
||||
var editorId = (ExternalEditorId)(int)GodotSharpEditor.Instance.GetEditorInterface()
|
||||
.GetEditorSettings().GetSetting("mono/editor/external_editor");
|
||||
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
||||
var editorId = editorSettings.GetSetting(GodotSharpEditor.Settings.ExternalEditor).As<ExternalEditorId>();
|
||||
string editorIdentity = GetExternalEditorIdentity(editorId);
|
||||
|
||||
var runningServer = GetRunningOrNewServer();
|
||||
|
@ -9,7 +9,7 @@ namespace GodotTools.Ides.Rider
|
||||
{
|
||||
public static class RiderPathManager
|
||||
{
|
||||
public static readonly string EditorPathSettingName = "mono/editor/editor_path_optional";
|
||||
public static readonly string EditorPathSettingName = "dotnet/editor/editor_path_optional";
|
||||
|
||||
private static string GetRiderPathFromSettings()
|
||||
{
|
||||
@ -22,7 +22,7 @@ namespace GodotTools.Ides.Rider
|
||||
public static void Initialize()
|
||||
{
|
||||
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
||||
var editor = (ExternalEditorId)(int)editorSettings.GetSetting("mono/editor/external_editor");
|
||||
var editor = editorSettings.GetSetting(GodotSharpEditor.Settings.ExternalEditor).As<ExternalEditorId>();
|
||||
if (editor == ExternalEditorId.Rider)
|
||||
{
|
||||
if (!editorSettings.HasSetting(EditorPathSettingName))
|
||||
|
@ -115,5 +115,11 @@ namespace GodotTools.Internals
|
||||
return _projectCsProjPath;
|
||||
}
|
||||
}
|
||||
|
||||
public static string LogsDirPathFor(string solution, string configuration)
|
||||
=> Path.Combine(BuildLogsDirs, $"{solution.Md5Text()}_{configuration}");
|
||||
|
||||
public static string LogsDirPathFor(string configuration)
|
||||
=> LogsDirPathFor(ProjectSlnPath, configuration);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
namespace GodotTools
|
||||
{
|
||||
public enum VerbosityLevelId : long
|
||||
{
|
||||
Quiet,
|
||||
Minimal,
|
||||
Normal,
|
||||
Detailed,
|
||||
Diagnostic,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user