From cb67be5a5a44fec5193257dc3548e8f469a90bd2 Mon Sep 17 00:00:00 2001 From: Paul Knopf Date: Sat, 13 Apr 2019 13:58:38 -0400 Subject: [PATCH] Support for auto discovery and download of runtimes. --- .../Qml.Net.Tests/BaseRuntimeManagerTests.cs | 52 ++++++ .../RuntimeManagerDiscoveryTests.cs | 79 ++++++++ src/net/Qml.Net.Tests/RuntimeManagerTests.cs | 6 + src/net/Qml.Net/Runtimes/Chmod.cs | 2 +- .../Qml.Net/Runtimes/RuntimeArchitecture.cs | 3 +- .../Runtimes/RuntimeManager.Configure.cs | 161 ++++++++++++++++ .../Runtimes/RuntimeManager.Discovery.cs | 112 +++++++++++ src/net/Qml.Net/Runtimes/RuntimeManager.cs | 174 ++++-------------- src/net/Qml.Net/Runtimes/Symlink.cs | 2 +- src/net/Qml.Net/Runtimes/Tar.cs | 6 +- 10 files changed, 454 insertions(+), 143 deletions(-) create mode 100644 src/net/Qml.Net.Tests/BaseRuntimeManagerTests.cs create mode 100644 src/net/Qml.Net.Tests/RuntimeManagerDiscoveryTests.cs create mode 100644 src/net/Qml.Net/Runtimes/RuntimeManager.Configure.cs create mode 100644 src/net/Qml.Net/Runtimes/RuntimeManager.Discovery.cs diff --git a/src/net/Qml.Net.Tests/BaseRuntimeManagerTests.cs b/src/net/Qml.Net.Tests/BaseRuntimeManagerTests.cs new file mode 100644 index 00000000..52b077b9 --- /dev/null +++ b/src/net/Qml.Net.Tests/BaseRuntimeManagerTests.cs @@ -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 _oldRuntimeUserDirectory; + private readonly Func _oldRuntimeExecutableDirectory; + private readonly Func _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(); + } + } +} \ No newline at end of file diff --git a/src/net/Qml.Net.Tests/RuntimeManagerDiscoveryTests.cs b/src/net/Qml.Net.Tests/RuntimeManagerDiscoveryTests.cs new file mode 100644 index 00000000..abd02f31 --- /dev/null +++ b/src/net/Qml.Net.Tests/RuntimeManagerDiscoveryTests.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/src/net/Qml.Net.Tests/RuntimeManagerTests.cs b/src/net/Qml.Net.Tests/RuntimeManagerTests.cs index aa9b2517..9019e881 100644 --- a/src/net/Qml.Net.Tests/RuntimeManagerTests.cs +++ b/src/net/Qml.Net.Tests/RuntimeManagerTests.cs @@ -66,6 +66,12 @@ namespace Qml.Net.Tests } } + [Fact] + public void Test() + { + var potential = RuntimeManager.GetPotentialRuntimesDirectories(); + } + public void Dispose() { if (Directory.Exists(_tempDirectory)) diff --git a/src/net/Qml.Net/Runtimes/Chmod.cs b/src/net/Qml.Net/Runtimes/Chmod.cs index c053321e..4972dfa3 100644 --- a/src/net/Qml.Net/Runtimes/Chmod.cs +++ b/src/net/Qml.Net/Runtimes/Chmod.cs @@ -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); diff --git a/src/net/Qml.Net/Runtimes/RuntimeArchitecture.cs b/src/net/Qml.Net/Runtimes/RuntimeArchitecture.cs index 7d9eec0a..74e1a252 100644 --- a/src/net/Qml.Net/Runtimes/RuntimeArchitecture.cs +++ b/src/net/Qml.Net/Runtimes/RuntimeArchitecture.cs @@ -4,6 +4,7 @@ namespace Qml.Net.Runtimes { LinuxX64, OSX64, - Windows64 + Windows64, + Unsupported } } \ No newline at end of file diff --git a/src/net/Qml.Net/Runtimes/RuntimeManager.Configure.cs b/src/net/Qml.Net/Runtimes/RuntimeManager.Configure.cs new file mode 100644 index 00000000..dd259b57 --- /dev/null +++ b/src/net/Qml.Net/Runtimes/RuntimeManager.Configure.cs @@ -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"); + } + } +} \ No newline at end of file diff --git a/src/net/Qml.Net/Runtimes/RuntimeManager.Discovery.cs b/src/net/Qml.Net/Runtimes/RuntimeManager.Discovery.cs new file mode 100644 index 00000000..c5f64724 --- /dev/null +++ b/src/net/Qml.Net/Runtimes/RuntimeManager.Discovery.cs @@ -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 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 GetRuntimeExecutableDirectory = () => Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); + + internal static Func GetRuntimeCurrentDirectory = () => Path.Combine(Directory.GetCurrentDirectory(), "qmlnet-qt-runtimes"); + + public static string[] GetPotentialRuntimesDirectories(RuntimeSearchLocation runtimes = RuntimeSearchLocation.All) + { + var result = new List(); + + // 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; + } + } +} \ No newline at end of file diff --git a/src/net/Qml.Net/Runtimes/RuntimeManager.cs b/src/net/Qml.Net/Runtimes/RuntimeManager.cs index cb7adbcb..0753b537 100644 --- a/src/net/Qml.Net/Runtimes/RuntimeManager.cs +++ b/src/net/Qml.Net/Runtimes/RuntimeManager.cs @@ -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 action) + private static void GetUrlStream(string url, Action 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); } } } \ No newline at end of file diff --git a/src/net/Qml.Net/Runtimes/Symlink.cs b/src/net/Qml.Net/Runtimes/Symlink.cs index 3d7eb661..ce0eee0d 100644 --- a/src/net/Qml.Net/Runtimes/Symlink.cs +++ b/src/net/Qml.Net/Runtimes/Symlink.cs @@ -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); diff --git a/src/net/Qml.Net/Runtimes/Tar.cs b/src/net/Qml.Net/Runtimes/Tar.cs index 71980199..98897b3c 100644 --- a/src/net/Qml.Net/Runtimes/Tar.cs +++ b/src/net/Qml.Net/Runtimes/Tar.cs @@ -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; }