From c7ec9d738f6e2dab93c9436179ab38ec568c69db Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 17 Jul 2026 18:02:51 +0200 Subject: [PATCH] Add `EditorUtilities::GetSDK` to query SDKs via `Flax.Build` from editor --- Source/Editor/Cooker/Steps/DeployDataStep.cpp | 17 ++------ Source/Editor/Utilities/EditorUtilities.cpp | 41 +++++++++++++++++++ Source/Editor/Utilities/EditorUtilities.h | 9 +++- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/Source/Editor/Cooker/Steps/DeployDataStep.cpp b/Source/Editor/Cooker/Steps/DeployDataStep.cpp index f8b31959a..2fce92cf6 100644 --- a/Source/Editor/Cooker/Steps/DeployDataStep.cpp +++ b/Source/Editor/Cooker/Steps/DeployDataStep.cpp @@ -86,20 +86,8 @@ bool DeployDataStep::Perform(CookingData& data) if (canUseSystemDotnet && (aotMode == DotNetAOTModes::None || aotMode == DotNetAOTModes::ILC)) { // Ask Flax.Build to provide .NET SDK location for the current platform - String sdks; - bool failed = ScriptsBuilder::RunBuildTool(String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printSDKs {}"), data.GetDotnetCommandArg()), data.CacheDirectory); - failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks); - int32 idx = sdks.Find(TEXT("DotNetSdk, "), StringSearchCase::CaseSensitive); - if (idx != -1) - { - idx = sdks.Find(TEXT(", "), StringSearchCase::CaseSensitive, idx + 12); - idx += 2; - int32 end = sdks.Find(TEXT("\n"), StringSearchCase::CaseSensitive, idx); - if (sdks[end] == '\r') - end--; - srcDotnet = String(sdks.Get() + idx, end - idx).TrimTrailing(); - } - if (failed || !FileSystem::DirectoryExists(srcDotnet)) + srcDotnet = EditorUtilities::GetSDK(TEXT("DotNetSdk"), data.GetDotnetCommandArg(), data.CacheDirectory / TEXT("SDKs.txt")); + if (srcDotnet.IsEmpty() || !FileSystem::DirectoryExists(srcDotnet)) { data.Error(TEXT("Failed to get .NET SDK location for the current host platform.")); return true; @@ -161,6 +149,7 @@ bool DeployDataStep::Perform(CookingData& data) FileSystem::CopyFile(dstDotnet / TEXT("LICENSE.TXT"), srcDotnet / TEXT("LICENSE.TXT")); FileSystem::CopyFile(dstDotnet / TEXT("THIRD-PARTY-NOTICES.TXT"), srcDotnet / TEXT("ThirdPartyNotices.txt")); FileSystem::CopyFile(dstDotnet / TEXT("THIRD-PARTY-NOTICES.TXT"), srcDotnet / TEXT("THIRD-PARTY-NOTICES.TXT")); + bool failed = false; if (usAOT) { failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet, srcDotnet / TEXT("shared/Microsoft.NETCore.App") / version); diff --git a/Source/Editor/Utilities/EditorUtilities.cpp b/Source/Editor/Utilities/EditorUtilities.cpp index 250687d79..6ffb10986 100644 --- a/Source/Editor/Utilities/EditorUtilities.cpp +++ b/Source/Editor/Utilities/EditorUtilities.cpp @@ -1,6 +1,7 @@ // Copyright (c) Wojciech Figat. All rights reserved. #include "EditorUtilities.h" +#include "Editor/Scripting/ScriptsBuilder.h" #include "Engine/Engine/Globals.h" #include "Engine/Platform/File.h" #include "Engine/Platform/FileSystem.h" @@ -310,6 +311,46 @@ bool EditorUtilities::GenerateCertificate(const String& name, const String& outp return false; } +String EditorUtilities::GetSDK(StringView sdk, StringView customArgs, StringView logFilePath, String* version) +{ + String logTempPath; + if (logFilePath.IsEmpty()) + { + logTempPath = Globals::TemporaryFolder / TEXT("SDKs.txt"); + logFilePath = logTempPath; + } + + // Log to file + if (ScriptsBuilder::RunBuildTool(String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=\"{}\" -printSDKs {}"), logFilePath, customArgs))) + return String::Empty; + + // Read outputs + String sdks; + if (File::ReadAllText(logFilePath, sdks)) + return String::Empty; + + // Search SDK path in the log + int32 idx = sdks.Find(*sdk, StringSearchCase::CaseSensitive), end; + if (idx != -1) + { + // Format: "Name, Version, Path\n" + idx = sdks.Find(TEXT(", "), StringSearchCase::CaseSensitive, idx + sdk.Length()); + if (version) + { + end = sdks.Find(TEXT(", "), StringSearchCase::CaseSensitive, idx + 2); + *version = String(sdks.Get() + idx + 2, end - idx - 2).TrimTrailing(); + } + idx = sdks.Find(TEXT(", "), StringSearchCase::CaseSensitive, idx + 2); + idx += 2; + end = sdks.Find(TEXT("\n"), StringSearchCase::CaseSensitive, idx); + if (sdks[end] == '\r') + end--; + return String(sdks.Get() + idx, end - idx).TrimTrailing(); + } + + return String::Empty; +} + bool EditorUtilities::IsInvalidPathChar(Char c) { char illegalChars[] = diff --git a/Source/Editor/Utilities/EditorUtilities.h b/Source/Editor/Utilities/EditorUtilities.h index f8de2a570..831588cff 100644 --- a/Source/Editor/Utilities/EditorUtilities.h +++ b/Source/Editor/Utilities/EditorUtilities.h @@ -43,12 +43,19 @@ public: } public: - static bool FindWDKBin(String& outputWdkBinPath); static bool GenerateCertificate(const String& name, const String& outputPfxFilePath); static bool GenerateCertificate(const String& name, const String& outputPfxFilePath, const String& outputCerFilePath, const String& outputPvkFilePath); public: + /// + /// Gets the path to the SDK using Flax.Build to query it via '-printSDKs' command. + /// + /// Name of the SDK (eg. VulkanSdk). + /// Custom arguments to pass to Flax.Build invocation when printing SDKs. + /// Custom log file path to use, otherwise will use a temp file. + /// Optional output for the SDK version. + static String GetSDK(StringView sdk, StringView customArgs = StringView::Empty, StringView logFilePath = StringView::Empty, String* version = nullptr); /// /// Determines whether the specified path character is invalid.