1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-12 13:20:55 +00:00

Merge pull request #72061 from paulloz/csharp/better-logs-management

C#: MSBuild logs and panel enhancements
This commit is contained in:
Rémi Verschelde
2023-02-07 19:37:43 +01:00
8 changed files with 143 additions and 20 deletions

View File

@@ -22,8 +22,7 @@ namespace GodotTools.Build
// TODO Use List once we have proper serialization // TODO Use List once we have proper serialization
public Godot.Collections.Array CustomProperties { get; private set; } = new(); public Godot.Collections.Array CustomProperties { get; private set; } = new();
public string LogsDirPath => public string LogsDirPath => GodotSharpDirs.LogsDirPathFor(Solution, Configuration);
Path.Combine(GodotSharpDirs.BuildLogsDirs, $"{Solution.Md5Text()}_{Configuration}");
public override bool Equals(object? obj) public override bool Equals(object? obj)
{ {

View File

@@ -7,6 +7,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Godot;
using GodotTools.BuildLogger; using GodotTools.BuildLogger;
using GodotTools.Utils; using GodotTools.Utils;
@@ -22,9 +23,11 @@ namespace GodotTools.Build
if (dotnetPath == null) if (dotnetPath == null)
throw new FileNotFoundException("Cannot find the dotnet executable."); throw new FileNotFoundException("Cannot find the dotnet executable.");
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
var startInfo = new ProcessStartInfo(dotnetPath); var startInfo = new ProcessStartInfo(dotnetPath);
BuildArguments(buildInfo, startInfo.ArgumentList); BuildArguments(buildInfo, startInfo.ArgumentList, editorSettings);
string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString(); string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString();
stdOutHandler?.Invoke(launchMessage); stdOutHandler?.Invoke(launchMessage);
@@ -35,6 +38,8 @@ namespace GodotTools.Build
startInfo.RedirectStandardError = true; startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false; startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true; 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 // Needed when running from Developer Command Prompt for VS
RemovePlatformVariable(startInfo.EnvironmentVariables); RemovePlatformVariable(startInfo.EnvironmentVariables);
@@ -83,9 +88,11 @@ namespace GodotTools.Build
if (dotnetPath == null) if (dotnetPath == null)
throw new FileNotFoundException("Cannot find the dotnet executable."); throw new FileNotFoundException("Cannot find the dotnet executable.");
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
var startInfo = new ProcessStartInfo(dotnetPath); var startInfo = new ProcessStartInfo(dotnetPath);
BuildPublishArguments(buildInfo, startInfo.ArgumentList); BuildPublishArguments(buildInfo, startInfo.ArgumentList, editorSettings);
string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString(); string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString();
stdOutHandler?.Invoke(launchMessage); stdOutHandler?.Invoke(launchMessage);
@@ -95,6 +102,8 @@ namespace GodotTools.Build
startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true; startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false; 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 // Needed when running from Developer Command Prompt for VS
RemovePlatformVariable(startInfo.EnvironmentVariables); 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 // `dotnet clean` / `dotnet build` commands
arguments.Add(buildInfo.OnlyClean ? "clean" : "build"); arguments.Add(buildInfo.OnlyClean ? "clean" : "build");
@@ -150,12 +160,14 @@ namespace GodotTools.Build
arguments.Add(buildInfo.Configuration); arguments.Add(buildInfo.Configuration);
// Verbosity // Verbosity
arguments.Add("-v"); AddVerbosityArguments(buildInfo, arguments, editorSettings);
arguments.Add("normal");
// Logger // Logger
AddLoggerArgument(buildInfo, arguments); AddLoggerArgument(buildInfo, arguments);
// Binary log
AddBinaryLogArgument(buildInfo, arguments, editorSettings);
// Custom properties // Custom properties
foreach (var customProperty in buildInfo.CustomProperties) 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 arguments.Add("publish"); // `dotnet publish` command
@@ -193,12 +206,14 @@ namespace GodotTools.Build
arguments.Add("true"); arguments.Add("true");
// Verbosity // Verbosity
arguments.Add("-v"); AddVerbosityArguments(buildInfo, arguments, editorSettings);
arguments.Add("normal");
// Logger // Logger
AddLoggerArgument(buildInfo, arguments); AddLoggerArgument(buildInfo, arguments);
// Binary log
AddBinaryLogArgument(buildInfo, arguments, editorSettings);
// Custom properties // Custom properties
foreach (var customProperty in buildInfo.CustomProperties) 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) private static void AddLoggerArgument(BuildInfo buildInfo, Collection<string> arguments)
{ {
string buildLoggerPath = Path.Combine(Internals.GodotSharpDirs.DataEditorToolsDir, string buildLoggerPath = Path.Combine(Internals.GodotSharpDirs.DataEditorToolsDir,
@@ -222,6 +256,16 @@ namespace GodotTools.Build
$"-l:{typeof(GodotBuildLogger).FullName},{buildLoggerPath};{buildInfo.LogsDirPath}"); $"-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) private static void RemovePlatformVariable(StringDictionary environmentVariables)
{ {
// EnvironmentVariables is case sensitive? Seriously? // EnvironmentVariables is case sensitive? Seriously?

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.IO;
using Godot; using Godot;
using GodotTools.Internals; using GodotTools.Internals;
using static GodotTools.Internals.Globals; using static GodotTools.Internals.Globals;
@@ -14,6 +15,7 @@ namespace GodotTools.Build
private Button _errorsBtn; private Button _errorsBtn;
private Button _warningsBtn; private Button _warningsBtn;
private Button _viewLogBtn; private Button _viewLogBtn;
private Button _openLogsFolderBtn;
private void WarningsToggled(bool pressed) private void WarningsToggled(bool pressed)
{ {
@@ -93,6 +95,10 @@ namespace GodotTools.Build
private void ViewLogToggled(bool pressed) => BuildOutputView.LogVisible = pressed; private void ViewLogToggled(bool pressed) => BuildOutputView.LogVisible = pressed;
private void OpenLogsFolderPressed() => OS.ShellOpen(
$"file://{GodotSharpDirs.LogsDirPathFor("Debug")}"
);
private void BuildMenuOptionPressed(long id) private void BuildMenuOptionPressed(long id)
{ {
switch ((BuildMenuOptions)id) switch ((BuildMenuOptions)id)
@@ -171,6 +177,22 @@ namespace GodotTools.Build
_viewLogBtn.Toggled += ViewLogToggled; _viewLogBtn.Toggled += ViewLogToggled;
toolBarHBox.AddChild(_viewLogBtn); 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(); BuildOutputView = new BuildOutputView();
AddChild(BuildOutputView); AddChild(BuildOutputView);
} }

View File

@@ -22,6 +22,14 @@ namespace GodotTools
{ {
public partial class GodotSharpEditor : EditorPlugin, ISerializationListener 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 EditorSettings _editorSettings;
private PopupMenu _menuPopup; private PopupMenu _menuPopup;
@@ -171,7 +179,7 @@ namespace GodotTools
[UsedImplicitly] [UsedImplicitly]
public Error OpenInExternalEditor(Script script, int line, int col) 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) switch (editorId)
{ {
@@ -323,8 +331,7 @@ namespace GodotTools
[UsedImplicitly] [UsedImplicitly]
public bool OverridesExternalEditor() public bool OverridesExternalEditor()
{ {
return (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor") != return _editorSettings.GetSetting(Settings.ExternalEditor).As<ExternalEditorId>() != ExternalEditorId.None;
ExternalEditorId.None;
} }
public override bool _Build() public override bool _Build()
@@ -453,7 +460,10 @@ namespace GodotTools
_menuPopup.IdPressed += _MenuOptionPressed; _menuPopup.IdPressed += _MenuOptionPressed;
// External editor settings // 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"; string settingsHintStr = "Disabled";
@@ -481,11 +491,23 @@ namespace GodotTools
_editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary _editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
{ {
["type"] = (int)Variant.Type.Int, ["type"] = (int)Variant.Type.Int,
["name"] = "mono/editor/external_editor", ["name"] = Settings.ExternalEditor,
["hint"] = (int)PropertyHint.Enum, ["hint"] = (int)PropertyHint.Enum,
["hint_string"] = settingsHintStr ["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 // Export plugin
var exportPlugin = new ExportPlugin(); var exportPlugin = new ExportPlugin();
AddExportPlugin(exportPlugin); AddExportPlugin(exportPlugin);
@@ -510,6 +532,24 @@ namespace GodotTools
AddChild(GodotIdeManager); 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) protected override void Dispose(bool disposing)
{ {
if (disposing) if (disposing)

View File

@@ -21,7 +21,8 @@ namespace GodotTools.Ides
return _messagingServer; return _messagingServer;
_messagingServer?.Dispose(); _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(); _ = _messagingServer.Listen();
@@ -76,8 +77,8 @@ namespace GodotTools.Ides
public async Task<EditorPick?> LaunchIdeAsync(int millisecondsTimeout = 10000) public async Task<EditorPick?> LaunchIdeAsync(int millisecondsTimeout = 10000)
{ {
var editorId = (ExternalEditorId)(int)GodotSharpEditor.Instance.GetEditorInterface() var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
.GetEditorSettings().GetSetting("mono/editor/external_editor"); var editorId = editorSettings.GetSetting(GodotSharpEditor.Settings.ExternalEditor).As<ExternalEditorId>();
string editorIdentity = GetExternalEditorIdentity(editorId); string editorIdentity = GetExternalEditorIdentity(editorId);
var runningServer = GetRunningOrNewServer(); var runningServer = GetRunningOrNewServer();

View File

@@ -9,7 +9,7 @@ namespace GodotTools.Ides.Rider
{ {
public static class RiderPathManager 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() private static string GetRiderPathFromSettings()
{ {
@@ -22,7 +22,7 @@ namespace GodotTools.Ides.Rider
public static void Initialize() public static void Initialize()
{ {
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings(); 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 (editor == ExternalEditorId.Rider)
{ {
if (!editorSettings.HasSetting(EditorPathSettingName)) if (!editorSettings.HasSetting(EditorPathSettingName))

View File

@@ -115,5 +115,11 @@ namespace GodotTools.Internals
return _projectCsProjPath; 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);
} }
} }

View File

@@ -0,0 +1,11 @@
namespace GodotTools
{
public enum VerbosityLevelId : long
{
Quiet,
Minimal,
Normal,
Detailed,
Diagnostic,
}
}