123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Collections.Specialized;
- using System.Diagnostics;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Godot;
- using GodotTools.BuildLogger;
- using GodotTools.Utils;
- namespace GodotTools.Build
- {
- public static class BuildSystem
- {
- private static Process LaunchBuild(BuildInfo buildInfo, Action<string> stdOutHandler,
- Action<string> stdErrHandler)
- {
- string dotnetPath = DotNetFinder.FindDotNetExe();
- 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, editorSettings);
- string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString();
- stdOutHandler?.Invoke(launchMessage);
- if (Godot.OS.IsStdOutVerbose())
- Console.WriteLine(launchMessage);
- startInfo.RedirectStandardOutput = true;
- 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);
- var process = new Process { StartInfo = startInfo };
- if (stdOutHandler != null)
- process.OutputDataReceived += (_, e) => stdOutHandler.Invoke(e.Data);
- if (stdErrHandler != null)
- process.ErrorDataReceived += (_, e) => stdErrHandler.Invoke(e.Data);
- process.Start();
- process.BeginOutputReadLine();
- process.BeginErrorReadLine();
- return process;
- }
- public static int Build(BuildInfo buildInfo, Action<string> stdOutHandler, Action<string> stdErrHandler)
- {
- using (var process = LaunchBuild(buildInfo, stdOutHandler, stdErrHandler))
- {
- process.WaitForExit();
- return process.ExitCode;
- }
- }
- public static async Task<int> BuildAsync(BuildInfo buildInfo, Action<string> stdOutHandler,
- Action<string> stdErrHandler)
- {
- using (var process = LaunchBuild(buildInfo, stdOutHandler, stdErrHandler))
- {
- await process.WaitForExitAsync();
- return process.ExitCode;
- }
- }
- private static Process LaunchPublish(BuildInfo buildInfo, Action<string> stdOutHandler,
- Action<string> stdErrHandler)
- {
- string dotnetPath = DotNetFinder.FindDotNetExe();
- 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, editorSettings);
- string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString();
- stdOutHandler?.Invoke(launchMessage);
- if (Godot.OS.IsStdOutVerbose())
- Console.WriteLine(launchMessage);
- 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);
- var process = new Process { StartInfo = startInfo };
- if (stdOutHandler != null)
- process.OutputDataReceived += (_, e) => stdOutHandler.Invoke(e.Data);
- if (stdErrHandler != null)
- process.ErrorDataReceived += (_, e) => stdErrHandler.Invoke(e.Data);
- process.Start();
- process.BeginOutputReadLine();
- process.BeginErrorReadLine();
- return process;
- }
- public static int Publish(BuildInfo buildInfo, Action<string> stdOutHandler, Action<string> stdErrHandler)
- {
- using (var process = LaunchPublish(buildInfo, stdOutHandler, stdErrHandler))
- {
- process.WaitForExit();
- return process.ExitCode;
- }
- }
- private static void BuildArguments(BuildInfo buildInfo, Collection<string> arguments,
- EditorSettings editorSettings)
- {
- // `dotnet clean` / `dotnet build` commands
- arguments.Add(buildInfo.OnlyClean ? "clean" : "build");
- // Solution
- arguments.Add(buildInfo.Solution);
- // `dotnet clean` doesn't recognize these options
- if (!buildInfo.OnlyClean)
- {
- // Restore
- // `dotnet build` restores by default, unless requested not to
- if (!buildInfo.Restore)
- arguments.Add("--no-restore");
- // Incremental or rebuild
- if (buildInfo.Rebuild)
- arguments.Add("--no-incremental");
- }
- // Configuration
- arguments.Add("-c");
- arguments.Add(buildInfo.Configuration);
- // Verbosity
- AddVerbosityArguments(buildInfo, arguments, editorSettings);
- // Logger
- AddLoggerArgument(buildInfo, arguments);
- // Binary log
- AddBinaryLogArgument(buildInfo, arguments, editorSettings);
- // Custom properties
- foreach (var customProperty in buildInfo.CustomProperties)
- {
- arguments.Add("-p:" + (string)customProperty);
- }
- }
- private static void BuildPublishArguments(BuildInfo buildInfo, Collection<string> arguments,
- EditorSettings editorSettings)
- {
- arguments.Add("publish"); // `dotnet publish` command
- // Solution
- arguments.Add(buildInfo.Solution);
- // Restore
- // `dotnet publish` restores by default, unless requested not to
- if (!buildInfo.Restore)
- arguments.Add("--no-restore");
- // Incremental or rebuild
- // TODO: Not supported in `dotnet publish` (https://github.com/dotnet/sdk/issues/11099)
- // if (buildInfo.Rebuild)
- // arguments.Add("--no-incremental");
- // Configuration
- arguments.Add("-c");
- arguments.Add(buildInfo.Configuration);
- // Runtime Identifier
- arguments.Add("-r");
- arguments.Add(buildInfo.RuntimeIdentifier!);
- // Self-published
- arguments.Add("--self-contained");
- arguments.Add("true");
- // Verbosity
- AddVerbosityArguments(buildInfo, arguments, editorSettings);
- // Logger
- AddLoggerArgument(buildInfo, arguments);
- // Binary log
- AddBinaryLogArgument(buildInfo, arguments, editorSettings);
- // Custom properties
- foreach (var customProperty in buildInfo.CustomProperties)
- {
- arguments.Add("-p:" + (string)customProperty);
- }
- // Publish output directory
- if (buildInfo.PublishOutputDir != null)
- {
- arguments.Add("-o");
- arguments.Add(buildInfo.PublishOutputDir);
- }
- }
- 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,
- "GodotTools.BuildLogger.dll");
- arguments.Add(
- $"-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?
- var platformEnvironmentVariables = new List<string>();
- foreach (string env in environmentVariables.Keys)
- {
- if (env.ToUpperInvariant() == "PLATFORM")
- platformEnvironmentVariables.Add(env);
- }
- foreach (string env in platformEnvironmentVariables)
- environmentVariables.Remove(env);
- }
- }
- }
|