In c# use the environment variable DOTNET_ROOT support to first check before using path which parallels modules/mono/editor/hostfxr_resolver.cpp's get_dotnet_root_from_env which does this check for c++ side.
Additionally supports editor settings for environments where environment variables dont work: Fixes Issue: https://github.com/godotengine/godot/issues/97501 Implements Proposal: https://github.com/godotengine/godot-proposals/issues/1941 removed unused variable
This commit is contained in:
parent
4c4e673344
commit
4e2df6aa79
4 changed files with 123 additions and 14 deletions
|
@ -20,13 +20,13 @@ namespace GodotTools.Build
|
||||||
private static Process LaunchBuild(BuildInfo buildInfo, Action<string?>? stdOutHandler,
|
private static Process LaunchBuild(BuildInfo buildInfo, Action<string?>? stdOutHandler,
|
||||||
Action<string?>? stdErrHandler)
|
Action<string?>? stdErrHandler)
|
||||||
{
|
{
|
||||||
string? dotnetPath = DotNetFinder.FindDotNetExe();
|
var editorSettings = EditorInterface.Singleton.GetEditorSettings();
|
||||||
|
|
||||||
|
string? dotnetPath = DotNetFinder.FindDotNetExe(editorSettings.GetSetting(GodotSharpEditor.Settings.OverrideDotnetExecutable).As<string>());
|
||||||
|
|
||||||
if (dotnetPath == null)
|
if (dotnetPath == null)
|
||||||
throw new FileNotFoundException("Cannot find the dotnet executable.");
|
throw new FileNotFoundException("Cannot find the dotnet executable.");
|
||||||
|
|
||||||
var editorSettings = EditorInterface.Singleton.GetEditorSettings();
|
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo(dotnetPath);
|
var startInfo = new ProcessStartInfo(dotnetPath);
|
||||||
|
|
||||||
BuildArguments(buildInfo, startInfo.ArgumentList, editorSettings);
|
BuildArguments(buildInfo, startInfo.ArgumentList, editorSettings);
|
||||||
|
@ -91,13 +91,13 @@ namespace GodotTools.Build
|
||||||
private static Process LaunchPublish(BuildInfo buildInfo, Action<string?>? stdOutHandler,
|
private static Process LaunchPublish(BuildInfo buildInfo, Action<string?>? stdOutHandler,
|
||||||
Action<string?>? stdErrHandler)
|
Action<string?>? stdErrHandler)
|
||||||
{
|
{
|
||||||
string? dotnetPath = DotNetFinder.FindDotNetExe();
|
var editorSettings = EditorInterface.Singleton.GetEditorSettings();
|
||||||
|
|
||||||
|
string? dotnetPath = DotNetFinder.FindDotNetExe(editorSettings.GetSetting(GodotSharpEditor.Settings.OverrideDotnetExecutable).As<string>());
|
||||||
|
|
||||||
if (dotnetPath == null)
|
if (dotnetPath == null)
|
||||||
throw new FileNotFoundException("Cannot find the dotnet executable.");
|
throw new FileNotFoundException("Cannot find the dotnet executable.");
|
||||||
|
|
||||||
var editorSettings = EditorInterface.Singleton.GetEditorSettings();
|
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo(dotnetPath);
|
var startInfo = new ProcessStartInfo(dotnetPath);
|
||||||
|
|
||||||
BuildPublishArguments(buildInfo, startInfo.ArgumentList, editorSettings);
|
BuildPublishArguments(buildInfo, startInfo.ArgumentList, editorSettings);
|
||||||
|
|
|
@ -11,8 +11,55 @@ namespace GodotTools.Build
|
||||||
{
|
{
|
||||||
public static class DotNetFinder
|
public static class DotNetFinder
|
||||||
{
|
{
|
||||||
public static string? FindDotNetExe()
|
private static string DOTNET_ROOT_ENVIRONMENT_VARIABLE = "DOTNET_ROOT";
|
||||||
|
|
||||||
|
public static string? FindDotNetExe(string? overrideDotnetExecutable)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(overrideDotnetExecutable) == false)
|
||||||
|
{
|
||||||
|
if (File.Exists(overrideDotnetExecutable))
|
||||||
|
{
|
||||||
|
return overrideDotnetExecutable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Simplified parallel to modules/mono/editor/hostfxr_resolver.cpp's get_dotnet_root_from_env where
|
||||||
|
// DOTNET_ROOT is checked before path.
|
||||||
|
// https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#net-sdk-and-cli-environment-variables
|
||||||
|
// Further support would be to handle DOTNET_ROOT, DOTNET_ROOT(x86), DOTNET_ROOT_X86, DOTNET_ROOT_X64 for specific architectures.
|
||||||
|
string envVariableToDotnetPath = Environment.GetEnvironmentVariable(DOTNET_ROOT_ENVIRONMENT_VARIABLE);
|
||||||
|
if (string.IsNullOrEmpty(envVariableToDotnetPath) == false)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(envVariableToDotnetPath))
|
||||||
|
{
|
||||||
|
string defaultDotnet = OS.PathWhich("dotnet");
|
||||||
|
if (string.IsNullOrEmpty(defaultDotnet) == false)
|
||||||
|
{
|
||||||
|
string fileName = Path.GetFileName(defaultDotnet);
|
||||||
|
|
||||||
|
string dotnetExecutable = Path.Join(envVariableToDotnetPath, fileName);
|
||||||
|
if (File.Exists(dotnetExecutable))
|
||||||
|
{
|
||||||
|
return dotnetExecutable;
|
||||||
|
}
|
||||||
|
else if (Godot.OS.IsStdOutVerbose())
|
||||||
|
{
|
||||||
|
Console.WriteLine(
|
||||||
|
$"Environment Variable \"{DOTNET_ROOT_ENVIRONMENT_VARIABLE}\"= \"{envVariableToDotnetPath}\" but does not contain a valid path to \"{dotnetExecutable}\".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Godot.OS.IsStdOutVerbose())
|
||||||
|
{
|
||||||
|
Console.WriteLine(
|
||||||
|
$"No default dotnet to use as method to connect \"{DOTNET_ROOT_ENVIRONMENT_VARIABLE}\" with correct executable name for platform.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Godot.OS.IsStdOutVerbose())
|
||||||
|
{
|
||||||
|
Console.WriteLine(
|
||||||
|
$"Environment Variable \"{DOTNET_ROOT_ENVIRONMENT_VARIABLE}\" = \"{envVariableToDotnetPath}\" but is not a directory.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// In the future, this method may do more than just search in PATH. We could look in
|
// In the future, this method may do more than just search in PATH. We could look in
|
||||||
// known locations or use Godot's linked nethost to search from the hostfxr location.
|
// known locations or use Godot's linked nethost to search from the hostfxr location.
|
||||||
|
|
||||||
|
@ -38,6 +85,7 @@ namespace GodotTools.Build
|
||||||
|
|
||||||
public static bool TryFindDotNetSdk(
|
public static bool TryFindDotNetSdk(
|
||||||
Version expectedVersion,
|
Version expectedVersion,
|
||||||
|
string? overrideDotnetExecutable,
|
||||||
[NotNullWhen(true)] out Version? version,
|
[NotNullWhen(true)] out Version? version,
|
||||||
[NotNullWhen(true)] out string? path
|
[NotNullWhen(true)] out string? path
|
||||||
)
|
)
|
||||||
|
@ -45,7 +93,7 @@ namespace GodotTools.Build
|
||||||
version = null;
|
version = null;
|
||||||
path = null;
|
path = null;
|
||||||
|
|
||||||
string? dotNetExe = FindDotNetExe();
|
string? dotNetExe = FindDotNetExe(overrideDotnetExecutable);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(dotNetExe))
|
if (string.IsNullOrEmpty(dotNetExe))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace GodotTools
|
||||||
public const string NoConsoleLogging = "dotnet/build/no_console_logging";
|
public const string NoConsoleLogging = "dotnet/build/no_console_logging";
|
||||||
public const string CreateBinaryLog = "dotnet/build/create_binary_log";
|
public const string CreateBinaryLog = "dotnet/build/create_binary_log";
|
||||||
public const string ProblemsLayout = "dotnet/build/problems_layout";
|
public const string ProblemsLayout = "dotnet/build/problems_layout";
|
||||||
|
public const string OverrideDotnetExecutable = "dotnet/build/override_dotnet_executable";
|
||||||
}
|
}
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
@ -264,8 +265,7 @@ namespace GodotTools
|
||||||
GodotSharpDirs.ProjectSlnPath,
|
GodotSharpDirs.ProjectSlnPath,
|
||||||
line >= 0 ? $"{scriptPath};{line + 1};{col + 1}" : scriptPath
|
line >= 0 ? $"{scriptPath};{line + 1};{col + 1}" : scriptPath
|
||||||
};
|
};
|
||||||
|
string command = DotNetFinder.FindDotNetExe(_editorSettings.GetSetting(GodotSharpEditor.Settings.OverrideDotnetExecutable).As<string>()) ?? "dotnet";
|
||||||
string command = DotNetFinder.FindDotNetExe() ?? "dotnet";
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -456,9 +456,14 @@ namespace GodotTools
|
||||||
|
|
||||||
var dotNetSdkSearchVersion = Environment.Version;
|
var dotNetSdkSearchVersion = Environment.Version;
|
||||||
|
|
||||||
|
_editorSettings = EditorInterface.Singleton.GetEditorSettings();
|
||||||
|
|
||||||
|
string? dotnetExecutableEditorSettings = _editorSettings.GetSetting(GodotSharpEditor.Settings.OverrideDotnetExecutable)
|
||||||
|
.As<string>();
|
||||||
|
|
||||||
// First we try to find the .NET Sdk ourselves to make sure we get the
|
// First we try to find the .NET Sdk ourselves to make sure we get the
|
||||||
// correct version first, otherwise pick the latest.
|
// correct version first, otherwise pick the latest.
|
||||||
if (DotNetFinder.TryFindDotNetSdk(dotNetSdkSearchVersion, out var sdkVersion, out string? sdkPath))
|
if (DotNetFinder.TryFindDotNetSdk(dotNetSdkSearchVersion, dotnetExecutableEditorSettings, out var sdkVersion, out string? sdkPath))
|
||||||
{
|
{
|
||||||
if (Godot.OS.IsStdOutVerbose())
|
if (Godot.OS.IsStdOutVerbose())
|
||||||
Console.WriteLine($"Found .NET Sdk version '{sdkVersion}': {sdkPath}");
|
Console.WriteLine($"Found .NET Sdk version '{sdkVersion}': {sdkPath}");
|
||||||
|
@ -483,8 +488,6 @@ namespace GodotTools
|
||||||
|
|
||||||
var editorBaseControl = EditorInterface.Singleton.GetBaseControl();
|
var editorBaseControl = EditorInterface.Singleton.GetBaseControl();
|
||||||
|
|
||||||
_editorSettings = EditorInterface.Singleton.GetEditorSettings();
|
|
||||||
|
|
||||||
_errorDialog = new AcceptDialog();
|
_errorDialog = new AcceptDialog();
|
||||||
_errorDialog.SetUnparentWhenInvisible(true);
|
_errorDialog.SetUnparentWhenInvisible(true);
|
||||||
|
|
||||||
|
@ -542,6 +545,7 @@ namespace GodotTools
|
||||||
EditorDef(Settings.VerbosityLevel, Variant.From(VerbosityLevelId.Normal));
|
EditorDef(Settings.VerbosityLevel, Variant.From(VerbosityLevelId.Normal));
|
||||||
EditorDef(Settings.NoConsoleLogging, false);
|
EditorDef(Settings.NoConsoleLogging, false);
|
||||||
EditorDef(Settings.CreateBinaryLog, false);
|
EditorDef(Settings.CreateBinaryLog, false);
|
||||||
|
EditorDef(Settings.OverrideDotnetExecutable, "");
|
||||||
EditorDef(Settings.ProblemsLayout, Variant.From(BuildProblemsView.ProblemsLayout.Tree));
|
EditorDef(Settings.ProblemsLayout, Variant.From(BuildProblemsView.ProblemsLayout.Tree));
|
||||||
|
|
||||||
string settingsHintStr = "Disabled";
|
string settingsHintStr = "Disabled";
|
||||||
|
|
|
@ -67,6 +67,7 @@ SOFTWARE.
|
||||||
#include "core/io/dir_access.h"
|
#include "core/io/dir_access.h"
|
||||||
#include "core/io/file_access.h"
|
#include "core/io/file_access.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
#include "editor/editor_settings.h"
|
||||||
|
|
||||||
#ifdef WINDOWS_ENABLED
|
#ifdef WINDOWS_ENABLED
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
@ -318,6 +319,61 @@ bool get_dotnet_root_from_env(String &r_dotnet_root) {
|
||||||
return get_file_path_from_env(dotnet_root_env, r_dotnet_root);
|
return get_file_path_from_env(dotnet_root_env, r_dotnet_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StringName get_dotnet_editor_settings_name() {
|
||||||
|
return StringName("dotnet/build/override_dotnet_executable");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_dotnet_exe_from_settings(String &r_dotnet_exe) {
|
||||||
|
const EditorSettings *editor_settings = EditorSettings::get_singleton();
|
||||||
|
if (editor_settings == nullptr) {
|
||||||
|
// load editor settings.
|
||||||
|
EditorSettings::create();
|
||||||
|
editor_settings = EditorSettings::get_singleton();
|
||||||
|
if (editor_settings == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const StringName editor_settings_name = get_dotnet_editor_settings_name();
|
||||||
|
// Use EDITOR_DEF to default it to "", if not found.
|
||||||
|
const Variant property_val = EDITOR_DEF(editor_settings_name, "");
|
||||||
|
if (property_val.is_string() == false) {
|
||||||
|
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||||
|
ERR_PRINT("The editor setting (" + editor_settings_name + ") is not referencing a valid string path.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String dotnet_exe = property_val;
|
||||||
|
if (dotnet_exe.is_empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
r_dotnet_exe = path::abspath(path::realpath(dotnet_exe));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_dotnet_root_from_settings(String &r_dotnet_root) {
|
||||||
|
String dotnet_exe;
|
||||||
|
|
||||||
|
if (!get_dotnet_exe_from_settings(dotnet_exe)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
r_dotnet_root = dotnet_exe.get_base_dir();
|
||||||
|
|
||||||
|
if (!DirAccess::exists(r_dotnet_root)) {
|
||||||
|
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||||
|
ERR_PRINT("The editor setting (" + get_dotnet_editor_settings_name() + ") is not referencing a valid string path (" + r_dotnet_root + ").");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|
||||||
bool godotsharp::hostfxr_resolver::try_get_path_from_dotnet_root(const String &p_dotnet_root, String &r_fxr_path) {
|
bool godotsharp::hostfxr_resolver::try_get_path_from_dotnet_root(const String &p_dotnet_root, String &r_fxr_path) {
|
||||||
|
@ -332,7 +388,8 @@ bool godotsharp::hostfxr_resolver::try_get_path_from_dotnet_root(const String &p
|
||||||
}
|
}
|
||||||
|
|
||||||
bool godotsharp::hostfxr_resolver::try_get_path(String &r_dotnet_root, String &r_fxr_path) {
|
bool godotsharp::hostfxr_resolver::try_get_path(String &r_dotnet_root, String &r_fxr_path) {
|
||||||
if (!get_dotnet_root_from_env(r_dotnet_root) &&
|
if (!get_dotnet_root_from_settings(r_dotnet_root) &&
|
||||||
|
!get_dotnet_root_from_env(r_dotnet_root) &&
|
||||||
!get_dotnet_self_registered_dir(r_dotnet_root) &&
|
!get_dotnet_self_registered_dir(r_dotnet_root) &&
|
||||||
!get_default_installation_dir(r_dotnet_root)) {
|
!get_default_installation_dir(r_dotnet_root)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue