mirror of
https://github.com/qmlnet/qmlnet.git
synced 2026-05-21 06:45:32 -06:00
Support for auto discovery and download of runtimes.
This commit is contained in:
parent
b58be97185
commit
cb67be5a5a
10 changed files with 454 additions and 143 deletions
52
src/net/Qml.Net.Tests/BaseRuntimeManagerTests.cs
Normal file
52
src/net/Qml.Net.Tests/BaseRuntimeManagerTests.cs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Qml.Net.Runtimes;
|
||||
|
||||
namespace Qml.Net.Tests
|
||||
{
|
||||
public class BaseRuntimeManagerTests : BaseTests
|
||||
{
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
protected readonly string _runtimeUserDirectory;
|
||||
protected readonly string _runtimeExecutableDirectory;
|
||||
protected readonly string _runtimeCurrentDirectory;
|
||||
// ReSharper restore MemberCanBePrivate.Global
|
||||
private readonly string _tmpDirectory;
|
||||
private readonly Func<string> _oldRuntimeUserDirectory;
|
||||
private readonly Func<string> _oldRuntimeExecutableDirectory;
|
||||
private readonly Func<string> _oldRuntimeCurrentDirectory;
|
||||
|
||||
public BaseRuntimeManagerTests()
|
||||
{
|
||||
_tmpDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString().Replace("-", ""));
|
||||
Directory.CreateDirectory(_tmpDirectory);
|
||||
|
||||
_runtimeUserDirectory = Path.Combine(_tmpDirectory, "user");
|
||||
_runtimeExecutableDirectory = Path.Combine(_tmpDirectory, "executable");
|
||||
_runtimeCurrentDirectory = Path.Combine(_tmpDirectory, "current");
|
||||
|
||||
Directory.CreateDirectory(_runtimeUserDirectory);
|
||||
Directory.CreateDirectory(_runtimeExecutableDirectory);
|
||||
Directory.CreateDirectory(_runtimeCurrentDirectory);
|
||||
|
||||
_oldRuntimeUserDirectory = RuntimeManager.GetRuntimeUserDirectory;
|
||||
_oldRuntimeExecutableDirectory = RuntimeManager.GetRuntimeExecutableDirectory;
|
||||
_oldRuntimeCurrentDirectory = RuntimeManager.GetRuntimeCurrentDirectory;
|
||||
|
||||
RuntimeManager.GetRuntimeUserDirectory = () => _runtimeUserDirectory;
|
||||
RuntimeManager.GetRuntimeExecutableDirectory = () => _runtimeExecutableDirectory;
|
||||
RuntimeManager.GetRuntimeCurrentDirectory = () => _runtimeCurrentDirectory;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Directory.Delete(_tmpDirectory, true);
|
||||
|
||||
RuntimeManager.GetRuntimeUserDirectory = _oldRuntimeUserDirectory;
|
||||
RuntimeManager.GetRuntimeExecutableDirectory = _oldRuntimeExecutableDirectory;
|
||||
RuntimeManager.GetRuntimeCurrentDirectory = _oldRuntimeCurrentDirectory;
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
src/net/Qml.Net.Tests/RuntimeManagerDiscoveryTests.cs
Normal file
79
src/net/Qml.Net.Tests/RuntimeManagerDiscoveryTests.cs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Qml.Net.Runtimes;
|
||||
using Xunit;
|
||||
|
||||
namespace Qml.Net.Tests
|
||||
{
|
||||
public class RuntimeManagerDiscoveryTests : BaseRuntimeManagerTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(RuntimeManager.RuntimeSearchLocation.UserDirectory)]
|
||||
public void Can_find_qt_runtimes(RuntimeManager.RuntimeSearchLocation runtimeSearchLocation)
|
||||
{
|
||||
var directory = Path.Combine(RuntimeManager.GetPotentialRuntimesDirectories(runtimeSearchLocation).Single());
|
||||
|
||||
var found = RuntimeManager.FindQtRuntime(
|
||||
RuntimeManager.GetPotentialRuntimesDirectories(runtimeSearchLocation),
|
||||
"qt-version",
|
||||
RuntimeTarget.Windows64);
|
||||
|
||||
found.Should().BeNullOrEmpty();
|
||||
|
||||
File.WriteAllText(Path.Combine(directory, "version.txt"), "qt-version-win-x64");
|
||||
|
||||
found = RuntimeManager.FindQtRuntime(
|
||||
RuntimeManager.GetPotentialRuntimesDirectories(runtimeSearchLocation),
|
||||
"qt-version",
|
||||
RuntimeTarget.Windows64);
|
||||
|
||||
found.Should().Be(directory);
|
||||
|
||||
File.Delete(Path.Combine(directory, "version.txt"));
|
||||
|
||||
var nestedRuntimeDirectory = Path.Combine(directory, "qt-version-win-x64");
|
||||
Directory.CreateDirectory(nestedRuntimeDirectory);
|
||||
|
||||
File.WriteAllText(Path.Combine(nestedRuntimeDirectory, "version.txt"), "qt-version-win-x64");
|
||||
|
||||
found = RuntimeManager.FindQtRuntime(
|
||||
RuntimeManager.GetPotentialRuntimesDirectories(runtimeSearchLocation),
|
||||
"qt-version",
|
||||
RuntimeTarget.Windows64);
|
||||
|
||||
found.Should().Be(nestedRuntimeDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_find_runtimes_in_proper_order()
|
||||
{
|
||||
File.WriteAllText(Path.Combine(_runtimeCurrentDirectory, "version.txt"), "qt-version-win-x64");
|
||||
|
||||
var found = RuntimeManager.FindQtRuntime(
|
||||
RuntimeManager.GetPotentialRuntimesDirectories(),
|
||||
"qt-version",
|
||||
RuntimeTarget.Windows64);
|
||||
|
||||
found.Should().Be(_runtimeCurrentDirectory);
|
||||
|
||||
File.WriteAllText(Path.Combine(_runtimeUserDirectory, "version.txt"), "qt-version-win-x64");
|
||||
|
||||
found = RuntimeManager.FindQtRuntime(
|
||||
RuntimeManager.GetPotentialRuntimesDirectories(),
|
||||
"qt-version",
|
||||
RuntimeTarget.Windows64);
|
||||
|
||||
found.Should().Be(_runtimeUserDirectory);
|
||||
|
||||
File.WriteAllText(Path.Combine(_runtimeExecutableDirectory, "version.txt"), "qt-version-win-x64");
|
||||
|
||||
found = RuntimeManager.FindQtRuntime(
|
||||
RuntimeManager.GetPotentialRuntimesDirectories(),
|
||||
"qt-version",
|
||||
RuntimeTarget.Windows64);
|
||||
|
||||
found.Should().Be(_runtimeExecutableDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -66,6 +66,12 @@ namespace Qml.Net.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test()
|
||||
{
|
||||
var potential = RuntimeManager.GetPotentialRuntimesDirectories();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_tempDirectory))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace Qml.Net.Runtimes
|
||||
{
|
||||
internal class Chmod
|
||||
internal static class Chmod
|
||||
{
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern int chmod(string pathname, int mode);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Qml.Net.Runtimes
|
|||
{
|
||||
LinuxX64,
|
||||
OSX64,
|
||||
Windows64
|
||||
Windows64,
|
||||
Unsupported
|
||||
}
|
||||
}
|
||||
161
src/net/Qml.Net/Runtimes/RuntimeManager.Configure.cs
Normal file
161
src/net/Qml.Net/Runtimes/RuntimeManager.Configure.cs
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Qml.Net.Runtimes
|
||||
{
|
||||
public static partial class RuntimeManager
|
||||
{
|
||||
public static void ConfigureRuntimeDirectory(string directory)
|
||||
{
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(directory));
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
throw new Exception("The directory doesn't exist.");
|
||||
}
|
||||
|
||||
var versionFile = Path.Combine(directory, "version.txt");
|
||||
|
||||
if (!File.Exists(versionFile))
|
||||
{
|
||||
throw new Exception("The version.txt file doesn't exist in the directory.");
|
||||
}
|
||||
|
||||
var version = File.ReadAllText(versionFile).TrimEnd(Environment.NewLine.ToCharArray());
|
||||
var expectedVersion = $"{QmlNetConfig.QtBuildVersion}-{RuntimeTargetToString(GetCurrentRuntimeTarget())}";
|
||||
|
||||
if (version != expectedVersion)
|
||||
{
|
||||
throw new Exception($"The version of the runtime directory was {versionFile}, but expected {expectedVersion}");
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
var pluginsDirectory = Path.Combine(directory, "qt", "plugins");
|
||||
if (!Directory.Exists(pluginsDirectory))
|
||||
{
|
||||
throw new Exception($"Plugins directory didn't exist: {pluginsDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QT_PLUGIN_PATH", pluginsDirectory);
|
||||
|
||||
var qmlDirectory = Path.Combine(directory, "qt", "qml");
|
||||
if (!Directory.Exists(qmlDirectory))
|
||||
{
|
||||
throw new Exception($"QML directory didn't exist: {qmlDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QML2_IMPORT_PATH", qmlDirectory);
|
||||
|
||||
var libDirectory = Path.Combine(directory, "qt", "lib");
|
||||
if (!Directory.Exists(libDirectory))
|
||||
{
|
||||
throw new Exception($"The lib directory didn't exist: {libDirectory}");
|
||||
}
|
||||
|
||||
var preloadPath = Path.Combine(libDirectory, "preload.txt");
|
||||
if (!File.Exists(preloadPath))
|
||||
{
|
||||
throw new Exception($"The preload.txt file didn't exist: {preloadPath}");
|
||||
}
|
||||
|
||||
var libsToPreload = File.ReadAllLines(preloadPath).Where(x => !string.IsNullOrEmpty(x))
|
||||
.Select(x => Path.Combine(libDirectory, x))
|
||||
.ToList();
|
||||
var platformLoader = NetNativeLibLoader.Loader.PlatformLoaderBase.SelectPlatformLoader();
|
||||
foreach (var libToPreload in libsToPreload)
|
||||
{
|
||||
var libHandler = platformLoader.LoadLibrary(libToPreload);
|
||||
if (libHandler == IntPtr.Zero)
|
||||
{
|
||||
throw new Exception($"Unabled to preload library: {libToPreload}");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
var pluginsDirectory = Path.Combine(directory, "qt", "plugins");
|
||||
if (!Directory.Exists(pluginsDirectory))
|
||||
{
|
||||
throw new Exception($"Plugins directory didn't exist: {pluginsDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QT_PLUGIN_PATH", pluginsDirectory);
|
||||
|
||||
var qmlDirectory = Path.Combine(directory, "qt", "qml");
|
||||
if (!Directory.Exists(qmlDirectory))
|
||||
{
|
||||
throw new Exception($"QML directory didn't exist: {qmlDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QML2_IMPORT_PATH", qmlDirectory);
|
||||
|
||||
var libDirectory = Path.Combine(directory, "qt", "lib");
|
||||
if (!Directory.Exists(libDirectory))
|
||||
{
|
||||
throw new Exception($"The lib directory didn't exist: {libDirectory}");
|
||||
}
|
||||
|
||||
var preloadPath = Path.Combine(libDirectory, "preload.txt");
|
||||
if (!File.Exists(preloadPath))
|
||||
{
|
||||
throw new Exception($"The preload.txt file didn't exist: {preloadPath}");
|
||||
}
|
||||
|
||||
var libsToPreload = File.ReadAllLines(preloadPath).Where(x => !string.IsNullOrEmpty(x))
|
||||
.Select(x => Path.Combine(libDirectory, x))
|
||||
.ToList();
|
||||
var platformLoader = NetNativeLibLoader.Loader.PlatformLoaderBase.SelectPlatformLoader();
|
||||
foreach (var libToPreload in libsToPreload)
|
||||
{
|
||||
var libHandler = platformLoader.LoadLibrary(libToPreload);
|
||||
if (libHandler == IntPtr.Zero)
|
||||
{
|
||||
throw new Exception($"Unabled to preload library: {libToPreload}");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
var pluginsDirectory = Path.Combine(directory, "qt", "plugins");
|
||||
if (!Directory.Exists(pluginsDirectory))
|
||||
{
|
||||
throw new Exception($"Plugins directory didn't exist: {pluginsDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QT_PLUGIN_PATH", pluginsDirectory);
|
||||
|
||||
var qmlDirectory = Path.Combine(directory, "qt", "qml");
|
||||
if (!Directory.Exists(qmlDirectory))
|
||||
{
|
||||
throw new Exception($"QML directory didn't exist: {qmlDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QML2_IMPORT_PATH", qmlDirectory);
|
||||
|
||||
var binDirectory = Path.Combine(directory, "qt", "bin");
|
||||
if (!Directory.Exists(binDirectory))
|
||||
{
|
||||
throw new Exception($"The bin directory didn't exist: {binDirectory}");
|
||||
}
|
||||
|
||||
Environment.SetEnvironmentVariable("PATH", $"{binDirectory};{Environment.GetEnvironmentVariable("PATH")}");
|
||||
|
||||
var preloadPath = Path.Combine(binDirectory, "preload.txt");
|
||||
if (!File.Exists(preloadPath))
|
||||
{
|
||||
throw new Exception($"The preload.txt file didn't exist: {preloadPath}");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Exception("Unknown platform, can't configure runtime directory");
|
||||
}
|
||||
}
|
||||
}
|
||||
112
src/net/Qml.Net/Runtimes/RuntimeManager.Discovery.cs
Normal file
112
src/net/Qml.Net/Runtimes/RuntimeManager.Discovery.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Qml.Net.Runtimes
|
||||
{
|
||||
public static partial class RuntimeManager
|
||||
{
|
||||
[Flags]
|
||||
public enum RuntimeSearchLocation
|
||||
{
|
||||
UserDirectory = 1,
|
||||
ExecutableDirectory = 1 << 1,
|
||||
CurrentDirectory = 1 << 2,
|
||||
All = UserDirectory | ExecutableDirectory | CurrentDirectory
|
||||
}
|
||||
|
||||
internal static Func<string> GetRuntimeUserDirectory = () =>
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
return Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".qmlnet-qt-runtimes");
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return Path.Combine(Environment.GetEnvironmentVariable("%HOMEDRIVE%%HOMEPATH%"), ".qmlnet-qt-runtimes");
|
||||
}
|
||||
|
||||
throw new Exception("Unknown platform, can't get user runtimes directory");
|
||||
};
|
||||
|
||||
internal static Func<string> GetRuntimeExecutableDirectory = () => Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
|
||||
|
||||
internal static Func<string> GetRuntimeCurrentDirectory = () => Path.Combine(Directory.GetCurrentDirectory(), "qmlnet-qt-runtimes");
|
||||
|
||||
public static string[] GetPotentialRuntimesDirectories(RuntimeSearchLocation runtimes = RuntimeSearchLocation.All)
|
||||
{
|
||||
var result = new List<string>();
|
||||
|
||||
// Order matters, most important location first.
|
||||
if (runtimes.HasFlag(RuntimeSearchLocation.ExecutableDirectory))
|
||||
{
|
||||
result.Add(Path.Combine(GetRuntimeExecutableDirectory()));
|
||||
}
|
||||
|
||||
if (runtimes.HasFlag(RuntimeSearchLocation.UserDirectory))
|
||||
{
|
||||
result.Add(GetRuntimeUserDirectory());
|
||||
}
|
||||
|
||||
if (runtimes.HasFlag(RuntimeSearchLocation.CurrentDirectory))
|
||||
{
|
||||
result.Add(GetRuntimeCurrentDirectory());
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public static string FindQtRuntime(string[] runtimeDirectories, string qtVersion, RuntimeTarget target)
|
||||
{
|
||||
if (runtimeDirectories.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var expectedVersion = $"{qtVersion}-{RuntimeTargetToString(target)}";
|
||||
|
||||
foreach (var potentialRuntimeDirectory in runtimeDirectories)
|
||||
{
|
||||
if (!Directory.Exists(potentialRuntimeDirectory))
|
||||
{
|
||||
// Obviously nothing here...
|
||||
continue;
|
||||
}
|
||||
|
||||
// Maybe this directory contains a Qt runtime?
|
||||
var versionPath = Path.Combine(potentialRuntimeDirectory, "version.txt");
|
||||
|
||||
if (File.Exists(versionPath))
|
||||
{
|
||||
var version = File.ReadAllText(versionPath).Trim(Environment.NewLine.ToCharArray());
|
||||
if (version == expectedVersion)
|
||||
{
|
||||
// Found it!
|
||||
return potentialRuntimeDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe there are nested directories of runtimes?
|
||||
var nestedDirectory = Path.Combine(potentialRuntimeDirectory, expectedVersion);
|
||||
if (Directory.Exists(nestedDirectory))
|
||||
{
|
||||
versionPath = Path.Combine(nestedDirectory, "version.txt");
|
||||
if (File.Exists(versionPath))
|
||||
{
|
||||
var version = File.ReadAllText(versionPath).Trim(Environment.NewLine.ToCharArray());
|
||||
if (version == expectedVersion)
|
||||
{
|
||||
// Found it!
|
||||
return nestedDirectory;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
|
@ -7,7 +9,7 @@ using System.Threading;
|
|||
|
||||
namespace Qml.Net.Runtimes
|
||||
{
|
||||
public static class RuntimeManager
|
||||
public static partial class RuntimeManager
|
||||
{
|
||||
public delegate string BuildRuntimeUrlDelegate(string qtVersion, RuntimeTarget target);
|
||||
|
||||
|
|
@ -26,6 +28,8 @@ namespace Qml.Net.Runtimes
|
|||
return "linux-x64";
|
||||
case RuntimeTarget.OSX64:
|
||||
return "osx-x64";
|
||||
case RuntimeTarget.Unsupported:
|
||||
throw new Exception("Unsupported target");
|
||||
default:
|
||||
throw new Exception($"Unknown target {target}");
|
||||
}
|
||||
|
|
@ -33,13 +37,16 @@ namespace Qml.Net.Runtimes
|
|||
|
||||
public delegate void ExtractTarGZStreamDelegate(Stream stream, string destinationDirectory);
|
||||
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
// ReSharper disable once FieldCanBeMadeReadOnly.Global
|
||||
public static ExtractTarGZStreamDelegate ExtractTarGZStream = Tar.ExtractTarFromGzipStream;
|
||||
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static RuntimeTarget GetCurrentRuntimeTarget()
|
||||
{
|
||||
if (IntPtr.Size != 8)
|
||||
{
|
||||
throw new Exception("Only 64bit supported");
|
||||
return RuntimeTarget.Unsupported;
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
|
|
@ -57,7 +64,7 @@ namespace Qml.Net.Runtimes
|
|||
return RuntimeTarget.OSX64;
|
||||
}
|
||||
|
||||
throw new Exception("Unknown OS platform");
|
||||
return RuntimeTarget.Unsupported;
|
||||
}
|
||||
|
||||
public static void DownloadRuntimeToDirectory(
|
||||
|
|
@ -94,7 +101,7 @@ namespace Qml.Net.Runtimes
|
|||
});
|
||||
}
|
||||
|
||||
public static void GetUrlStream(string url, Action<Stream> action)
|
||||
private static void GetUrlStream(string url, Action<Stream> action)
|
||||
{
|
||||
var syncContext = SynchronizationContext.Current;
|
||||
try
|
||||
|
|
@ -112,147 +119,40 @@ namespace Qml.Net.Runtimes
|
|||
}
|
||||
}
|
||||
|
||||
public static void ConfigureRuntimeDirectory(string directory)
|
||||
public static string FindSuitableQtRuntime(RuntimeSearchLocation runtimeSearchLocation = RuntimeSearchLocation.All)
|
||||
{
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
var potentials = GetPotentialRuntimesDirectories(runtimeSearchLocation);
|
||||
return FindQtRuntime(potentials, QmlNetConfig.QtBuildVersion, GetCurrentRuntimeTarget());
|
||||
}
|
||||
|
||||
public static void DiscoverOrDownloadSuitableQtRuntime(RuntimeSearchLocation runtimeSearchLocation = RuntimeSearchLocation.All)
|
||||
{
|
||||
var suitableRuntime = FindSuitableQtRuntime(runtimeSearchLocation);
|
||||
if (!string.IsNullOrEmpty(suitableRuntime))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(directory));
|
||||
// Found one!
|
||||
ConfigureRuntimeDirectory(suitableRuntime);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directory))
|
||||
var currentTarget = GetCurrentRuntimeTarget();
|
||||
var version = $"{QmlNetConfig.QtBuildVersion}-{RuntimeTargetToString(currentTarget)}";
|
||||
|
||||
// Let's try to download and install the Qt runtime into the users directory.
|
||||
var destinationDirectory = Path.Combine(GetPotentialRuntimesDirectories(RuntimeSearchLocation.UserDirectory).Single(), version);
|
||||
var destinationTmpDirectory = $"{destinationDirectory}-{Guid.NewGuid().ToString().Replace("-", "")}";
|
||||
|
||||
Directory.CreateDirectory(destinationTmpDirectory);
|
||||
DownloadRuntimeToDirectory(QmlNetConfig.QtBuildVersion, currentTarget, destinationTmpDirectory);
|
||||
|
||||
if (Directory.Exists(destinationDirectory))
|
||||
{
|
||||
throw new Exception("The directory doesn't exist.");
|
||||
Directory.Delete(destinationDirectory, true);
|
||||
}
|
||||
|
||||
var versionFile = Path.Combine(directory, "version.txt");
|
||||
Directory.Move(destinationTmpDirectory, destinationDirectory);
|
||||
|
||||
if (!File.Exists(versionFile))
|
||||
{
|
||||
throw new Exception("The version.txt file doesn't exist in the directory.");
|
||||
}
|
||||
|
||||
var version = File.ReadAllText(versionFile).TrimEnd(Environment.NewLine.ToCharArray());
|
||||
var expectedVersion = $"{QmlNetConfig.QtBuildVersion}-{RuntimeTargetToString(GetCurrentRuntimeTarget())}";
|
||||
|
||||
if (version != expectedVersion)
|
||||
{
|
||||
throw new Exception($"The version of the runtime directory was {versionFile}, but expected {expectedVersion}");
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
var pluginsDirectory = Path.Combine(directory, "qt", "plugins");
|
||||
if (!Directory.Exists(pluginsDirectory))
|
||||
{
|
||||
throw new Exception($"Plugins directory didn't exist: {pluginsDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QT_PLUGIN_PATH", pluginsDirectory);
|
||||
|
||||
var qmlDirectory = Path.Combine(directory, "qt", "qml");
|
||||
if (!Directory.Exists(qmlDirectory))
|
||||
{
|
||||
throw new Exception($"QML directory didn't exist: {qmlDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QML2_IMPORT_PATH", qmlDirectory);
|
||||
|
||||
var libDirectory = Path.Combine(directory, "qt", "lib");
|
||||
if (!Directory.Exists(libDirectory))
|
||||
{
|
||||
throw new Exception($"The lib directory didn't exist: {libDirectory}");
|
||||
}
|
||||
|
||||
var preloadPath = Path.Combine(libDirectory, "preload.txt");
|
||||
if (!File.Exists(preloadPath))
|
||||
{
|
||||
throw new Exception($"The preload.txt file didn't exist: {preloadPath}");
|
||||
}
|
||||
|
||||
var libsToPreload = File.ReadAllLines(preloadPath).Where(x => !string.IsNullOrEmpty(x))
|
||||
.Select(x => Path.Combine(libDirectory, x))
|
||||
.ToList();
|
||||
var platformLoader = NetNativeLibLoader.Loader.PlatformLoaderBase.SelectPlatformLoader();
|
||||
foreach (var libToPreload in libsToPreload)
|
||||
{
|
||||
var libHandler = platformLoader.LoadLibrary(libToPreload);
|
||||
if (libHandler == IntPtr.Zero)
|
||||
{
|
||||
throw new Exception($"Unabled to preload library: {libToPreload}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
var pluginsDirectory = Path.Combine(directory, "qt", "plugins");
|
||||
if (!Directory.Exists(pluginsDirectory))
|
||||
{
|
||||
throw new Exception($"Plugins directory didn't exist: {pluginsDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QT_PLUGIN_PATH", pluginsDirectory);
|
||||
|
||||
var qmlDirectory = Path.Combine(directory, "qt", "qml");
|
||||
if (!Directory.Exists(qmlDirectory))
|
||||
{
|
||||
throw new Exception($"QML directory didn't exist: {qmlDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QML2_IMPORT_PATH", qmlDirectory);
|
||||
|
||||
var libDirectory = Path.Combine(directory, "qt", "lib");
|
||||
if (!Directory.Exists(libDirectory))
|
||||
{
|
||||
throw new Exception($"The lib directory didn't exist: {libDirectory}");
|
||||
}
|
||||
|
||||
var preloadPath = Path.Combine(libDirectory, "preload.txt");
|
||||
if (!File.Exists(preloadPath))
|
||||
{
|
||||
throw new Exception($"The preload.txt file didn't exist: {preloadPath}");
|
||||
}
|
||||
|
||||
var libsToPreload = File.ReadAllLines(preloadPath).Where(x => !string.IsNullOrEmpty(x))
|
||||
.Select(x => Path.Combine(libDirectory, x))
|
||||
.ToList();
|
||||
var platformLoader = NetNativeLibLoader.Loader.PlatformLoaderBase.SelectPlatformLoader();
|
||||
foreach (var libToPreload in libsToPreload)
|
||||
{
|
||||
var libHandler = platformLoader.LoadLibrary(libToPreload);
|
||||
if (libHandler == IntPtr.Zero)
|
||||
{
|
||||
throw new Exception($"Unabled to preload library: {libToPreload}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
var pluginsDirectory = Path.Combine(directory, "qt", "plugins");
|
||||
if (!Directory.Exists(pluginsDirectory))
|
||||
{
|
||||
throw new Exception($"Plugins directory didn't exist: {pluginsDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QT_PLUGIN_PATH", pluginsDirectory);
|
||||
|
||||
var qmlDirectory = Path.Combine(directory, "qt", "qml");
|
||||
if (!Directory.Exists(qmlDirectory))
|
||||
{
|
||||
throw new Exception($"QML directory didn't exist: {qmlDirectory}");
|
||||
}
|
||||
Environment.SetEnvironmentVariable("QML2_IMPORT_PATH", qmlDirectory);
|
||||
|
||||
var binDirectory = Path.Combine(directory, "qt", "bin");
|
||||
if (!Directory.Exists(binDirectory))
|
||||
{
|
||||
throw new Exception($"The bin directory didn't exist: {binDirectory}");
|
||||
}
|
||||
|
||||
Environment.SetEnvironmentVariable("PATH", $"{binDirectory};{Environment.GetEnvironmentVariable("PATH")}");
|
||||
|
||||
var preloadPath = Path.Combine(binDirectory, "preload.txt");
|
||||
if (!File.Exists(preloadPath))
|
||||
{
|
||||
throw new Exception($"The preload.txt file didn't exist: {preloadPath}");
|
||||
}
|
||||
}
|
||||
ConfigureRuntimeDirectory(destinationDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace Qml.Net.Runtimes
|
||||
{
|
||||
internal class Symlink
|
||||
internal static class Symlink
|
||||
{
|
||||
[DllImport("libc")]
|
||||
private static extern int symlink(string path1, string path2);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using Newtonsoft.Json.Schema;
|
|||
|
||||
namespace Qml.Net.Runtimes
|
||||
{
|
||||
internal class Tar
|
||||
internal static class Tar
|
||||
{
|
||||
public enum EntryType : byte
|
||||
{
|
||||
|
|
@ -31,7 +31,7 @@ namespace Qml.Net.Runtimes
|
|||
// ReSharper restore UnusedMember.Global
|
||||
}
|
||||
|
||||
public static Header ReadHeader(Stream stream)
|
||||
private static Header ReadHeader(Stream stream)
|
||||
{
|
||||
var buffer = new byte[512];
|
||||
var bytesRead = stream.Read(buffer, 0, buffer.Length);
|
||||
|
|
@ -70,7 +70,7 @@ namespace Qml.Net.Runtimes
|
|||
return header;
|
||||
}
|
||||
|
||||
public class Header
|
||||
private class Header
|
||||
{
|
||||
public EntryType EntryType { get; set; }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue