Compare commits

..

3 Commits

4 changed files with 110 additions and 14 deletions

View File

@ -137,14 +137,7 @@ if %_e%==13 (goto :done) else (goto :dotnet)
echo -----------------------dotnet----------------------------
rmdir "Dependencies/dotnet" /S /Q
mkdir "Dependencies/dotnet/include"
mkdir "Dependencies/dotnet/bin"
powershell -Command "& {wget https://raw.githubusercontent.com/dotnet/runtime/main/src/coreclr/hosts/inc/coreclrhost.h -OutFile "Dependencies/dotnet/include/coreclrhost.h"}"
powershell -Command "& {wget https://download.visualstudio.microsoft.com/download/pr/8686fa48-b378-424e-908b-afbd66d6e120/2d75d5c3574fb5d917c5a3cd3f624287/dotnet-sdk-6.0.400-win-x64.zip -OutFile "Dependencies/dotnet/dotnet.zip"}"
powershell -Command "& {Expand-Archive -LiteralPath Dependencies/dotnet/dotnet.zip -DestinationPath Dependencies/dotnet/tmp}"
robocopy "Dependencies/dotnet/tmp/shared/Microsoft.NETCore.App/6.0.8/" "Dependencies/dotnet/bin/" *.dll /ns /nfl /ndl /nc /njh
rmdir "Dependencies/dotnet/tmp/" /s /q
del "Dependencies/dotnet/dotnet.zip"
powershell -Command "& {Remove-Item "Dependencies/dotnet/dotnet.zip"}"
if %_e%==14 (goto :done) else (goto :tinyddsloader)

View File

@ -113,7 +113,6 @@ project "SHADE_Engine"
{
"xcopy /s /r /y /q \"%{IncludeDir.spdlog}\\bin\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.SDL}\\lib\\SDL2.dll\" \"$(OutDir)\"",
"xcopy /s /r /y /q \"%{IncludeDir.dotnet}\\bin\" \"$(OutDir)\""
}
filter "configurations:Debug"

View File

@ -21,6 +21,8 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies
#include <shlwapi.h> // PathRemoveFileSpecA
#include "Tools/Logger/SHLogger.h"
#include "Tools/Utilities/SHExecUtilities.h"
#include "Tools/Utilities/SHStringUtilities.h"
namespace SHADE
{
@ -59,6 +61,10 @@ namespace SHADE
if (initialised)
throw std::runtime_error("[DotNetRuntime] Failed to initialise as it was already initialised or was deinitialised into an invalid state.");
const auto DOT_NET_PATH = getDotNetRuntimePath();
if (!DOT_NET_PATH)
throw std::runtime_error("[DotNetRuntime] .NET Runtime installation is missing.");
// Get the current executable directory
std::string runtimePath(MAX_PATH, '\0');
GetModuleFileNameA(nullptr, runtimePath.data(), MAX_PATH);
@ -70,15 +76,14 @@ namespace SHADE
if (coreClr == nullptr)
{
// Construct the CoreCLR path
std::string coreClrPath(runtimePath); // Works
coreClrPath += "\\coreclr.dll";
const std::string CORE_CLR_PATH = DOT_NET_PATH->string() + "\\coreclr.dll";
// Load the CoreCLR DLL
coreClr = LoadLibraryExA(coreClrPath.c_str(), nullptr, 0);
coreClr = LoadLibraryExA(CORE_CLR_PATH.c_str(), nullptr, 0);
if (!coreClr)
{
std::ostringstream oss;
oss << "[DotNetRuntime] Error #" << GetLastError() << " Failed to load CoreCLR from \"" << coreClrPath << "\"\n";
oss << "[DotNetRuntime] Error #" << GetLastError() << " Failed to load CoreCLR from \"" << CORE_CLR_PATH << "\"\n";
throw std::runtime_error(oss.str());
}
@ -94,7 +99,7 @@ namespace SHADE
// trusted system assemblies (similar to the .NET Framework GAC).
// For this host (as with most), assemblies next to CoreCLR will
// be included in the TPA list
std::string tpaList = buildTpaList(runtimePath);
std::string tpaList = buildTpaList(DOT_NET_PATH->string()) + buildTpaList(runtimePath);
// Define CoreCLR properties
std::array propertyKeys =
@ -153,7 +158,7 @@ namespace SHADE
std::string SHDotNetRuntime::buildTpaList(const std::string& directory)
{
// Constants
static const std::string SEARCH_PATH = directory + "\\*.dll";
const std::string SEARCH_PATH = directory + "\\*.dll";
static constexpr char PATH_DELIMITER = ';';
// Create a osstream object to compile the string
@ -195,4 +200,90 @@ namespace SHADE
throw std::runtime_error(oss.str());
}
}
std::optional<std::filesystem::path> SHDotNetRuntime::getDotNetRuntimePath()
{
// Check if dotnet is installed
const auto DOT_NET_PATH = std::filesystem::path(L"C:\\Program Files\\dotnet\\dotnet.exe");
if (!std::filesystem::exists(DOT_NET_PATH))
return {};
// Execute dotnet to search for
const auto RUNTIME_SEARCH = SHExecUtilties::ExecBlockingProcess(DOT_NET_PATH.wstring(), L" --list-runtimes", true, false);
if (RUNTIME_SEARCH.Code != 0)
return {};
// Remove all except Microsoft.NETCore.App entries
auto runtimeEntries = SHStringUtilities::Split(RUNTIME_SEARCH.StdOutput, L'\n');
std::erase_if(runtimeEntries, [](const std::wstring& str)
{
return str.find(L".NETCore.App") == std::wstring::npos;
});
// Early exit if there is none
if (runtimeEntries.empty())
return {};
// Select the highest version
std::wstring highestVersion;
int major = 0; int minor = 0; int revision = 0;
for (const auto& entry : runtimeEntries)
{
auto start = entry.find_first_of(L"1234567890");
auto end = entry.find_last_of(L"1234567890");
// No version string found
if (start == std::wstring::npos)
continue;
// Grab the version string and tokenize it to parts
const std::wstring VER_STR = entry.substr(start, end - start + 1);
const auto VERSION_TOKENS = SHStringUtilities::Split(VER_STR, L'.');
// Invalid version string
if (VERSION_TOKENS.size() < 3)
continue;
// Get version strings
const auto thisMajor = stoi(VERSION_TOKENS[0]);
const auto thisMinor = stoi(VERSION_TOKENS[1]);
const auto thisRevision = stoi(VERSION_TOKENS[2]);
// Only pass if the version is greater
if (major > thisMajor)
continue;
else if (major == thisMajor)
{
if (minor > thisMinor)
continue;
else if (minor == thisMinor)
{
if (revision > thisRevision)
continue;
}
}
major = thisMajor;
minor = thisMinor;
revision = thisRevision;
highestVersion = VER_STR;
}
// No suitable version found
if (highestVersion.empty())
return {};
// Extract path string
const std::wstring& ENTRY = runtimeEntries[0];
const auto START = ENTRY.find_first_of(L'[');
const auto END = ENTRY.find_last_of(L']');
// - Can't extract string
if (START == std::wstring::npos || END == std::wstring::npos)
return {};
// - Extract string
const std::wstring DIR_PATH = ENTRY.substr(START + 1, END - START - 1);
// Form resulting path based on found version
return std::filesystem::path(DIR_PATH) / highestVersion;
}
}

View File

@ -201,6 +201,19 @@ namespace SHADE
*/
/***********************************************************************************/
static void throwIfFailed(const std::string& errMsg, int resultCode);
/***********************************************************************************/
/*!
\brief
Searches for the dotnet runtime binary folder and returns it if it exists.
If multiple versions are present, the latest version will be returned.
\return
The path to the dotnet runtime binary folder. Null if none was found.
*/
/***********************************************************************************/
static std::optional<std::filesystem::path> getDotNetRuntimePath();
};
}