Simplified the loading of native libs in Qml.Net.

This effectively removes support from loading Qt from NuGet.
Finalized the ability to configure a Qt runtime directory on Linux.
This commit is contained in:
Paul Knopf 2019-04-12 23:47:07 -04:00
parent 3dad022866
commit 6889773427
2 changed files with 38 additions and 68 deletions

View file

@ -16,10 +16,6 @@ namespace Qml.Net.Internal
static Interop() static Interop()
{ {
string pluginsDirectory = null;
string qmlDirectory = null;
string libDirectory = null;
IPathResolver pathResolver = null; IPathResolver pathResolver = null;
IPlatformLoader loader = null; IPlatformLoader loader = null;
@ -47,42 +43,6 @@ namespace Qml.Net.Internal
{ {
pathResolver = new LinuxDllImportLibraryPathResolver(pathResolver); pathResolver = new LinuxDllImportLibraryPathResolver(pathResolver);
} }
var resolveResult = pathResolver.Resolve("QmlNet");
if (resolveResult.IsSuccess)
{
libDirectory = Path.GetDirectoryName(resolveResult.Path);
if (!string.IsNullOrEmpty(libDirectory))
{
// If this library has a plugins/qml directory below it, set it.
var potentialPlugisDirectory = Path.Combine(libDirectory, "plugins");
if (Directory.Exists(potentialPlugisDirectory))
{
pluginsDirectory = potentialPlugisDirectory;
}
var potentialQmlDirectory = Path.Combine(libDirectory, "qml");
if (Directory.Exists(potentialQmlDirectory))
{
qmlDirectory = potentialQmlDirectory;
}
}
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (!string.IsNullOrEmpty(libDirectory) && Directory.Exists(libDirectory))
{
// Even though we opened up the native dll correctly, we need to add
// the folder to the path. The reason is because QML plugins aren't
// in the same directory and have trouble finding dependencies
// that are within our lib folder.
Environment.SetEnvironmentVariable(
"PATH",
Environment.GetEnvironmentVariable("PATH") + $";{libDirectory}");
}
}
} }
var result = pathResolver.Resolve("QmlNet"); var result = pathResolver.Resolve("QmlNet");
@ -114,14 +74,10 @@ namespace Qml.Net.Internal
QtWebEngine = LoadInteropType<QtWebEngineInterop>(library, loader); QtWebEngine = LoadInteropType<QtWebEngineInterop>(library, loader);
QTest = LoadInteropType<QTestInterop>(library, loader); QTest = LoadInteropType<QTestInterop>(library, loader);
if (!string.IsNullOrEmpty(pluginsDirectory)) // RuntimeManager.ConfigureRuntimeDirectory may set these environment variables.
{ // However, they only really work when called with Qt.PutEnv.
Qt.PutEnv("QT_PLUGIN_PATH", pluginsDirectory); Qt.PutEnv("QT_PLUGIN_PATH", Environment.GetEnvironmentVariable("QT_PLUGIN_PATH"));
} Qt.PutEnv("QML2_IMPORT_PATH", Environment.GetEnvironmentVariable("QML2_IMPORT_PATH"));
if (!string.IsNullOrEmpty(qmlDirectory))
{
Qt.PutEnv("QML2_IMPORT_PATH", qmlDirectory);
}
var cb = DefaultCallbacks.Callbacks(); var cb = DefaultCallbacks.Callbacks();
Callbacks.RegisterCallbacks(ref cb); Callbacks.RegisterCallbacks(ref cb);
@ -167,7 +123,7 @@ namespace Qml.Net.Internal
public static QTestInterop QTest { get; } public static QTestInterop QTest { get; }
private static T LoadInteropType<T>(IntPtr library, NetNativeLibLoader.Loader.IPlatformLoader loader) private static T LoadInteropType<T>(IntPtr library, IPlatformLoader loader)
where T : new() where T : new()
{ {
var result = new T(); var result = new T();

View file

@ -1,5 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
@ -12,21 +13,23 @@ namespace Qml.Net.Runtimes
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once FieldCanBeMadeReadOnly.Global // ReSharper disable once FieldCanBeMadeReadOnly.Global
public static BuildRuntimeUrlDelegate BuildRuntimeUrl = (qtVersion, target) => public static BuildRuntimeUrlDelegate BuildRuntimeUrl = (qtVersion, target)
=> $"https://github.com/qmlnet/qt-runtimes/releases/download/releases/{qtVersion}-{RuntimeTargetToString(target)}-runtime.tar.gz";
private static string RuntimeTargetToString(RuntimeTarget target)
{ {
var url = $"https://github.com/qmlnet/qt-runtimes/releases/download/releases/{qtVersion}-{{target}}-runtime.tar.gz";
switch (target) switch (target)
{ {
case RuntimeTarget.Windows64: case RuntimeTarget.Windows64:
return url.Replace("{target}", "win-x64"); return "win-x64";
case RuntimeTarget.LinuxX64: case RuntimeTarget.LinuxX64:
return url.Replace("{target}", "linux-x64"); return "linux-x64";
case RuntimeTarget.OSX64: case RuntimeTarget.OSX64:
return url.Replace("{target}", "osx-x64"); return "osx-x64";
default: default:
throw new Exception($"Unknown target {target}"); throw new Exception($"Unknown target {target}");
} }
}; }
public delegate void ExtractTarGZStreamDelegate(Stream stream, string destinationDirectory); public delegate void ExtractTarGZStreamDelegate(Stream stream, string destinationDirectory);
@ -129,40 +132,51 @@ namespace Qml.Net.Runtimes
} }
var version = File.ReadAllText(versionFile).TrimEnd(Environment.NewLine.ToCharArray()); var version = File.ReadAllText(versionFile).TrimEnd(Environment.NewLine.ToCharArray());
var expectedVersion = $"{QmlNetConfig.QtBuildVersion}-{GetCurrentRuntimeTarget()}"; var expectedVersion = $"{QmlNetConfig.QtBuildVersion}-{RuntimeTargetToString(GetCurrentRuntimeTarget())}";
if (version != expectedVersion) if (version != expectedVersion)
{ {
throw new Exception($"The version of the runtime directory was {versionFile}, but expected {expectedVersion}"); throw new Exception($"The version of the runtime directory was {versionFile}, but expected {expectedVersion}");
} }
var pluginsDirectory = Path.Combine(directory, "plugins"); var pluginsDirectory = Path.Combine(directory, "qt", "plugins");
if (!Directory.Exists(pluginsDirectory)) if (!Directory.Exists(pluginsDirectory))
{ {
throw new Exception($"Plugins directory didn't exist: {pluginsDirectory}"); throw new Exception($"Plugins directory didn't exist: {pluginsDirectory}");
} }
Environment.SetEnvironmentVariable("QT_PLUGIN_PATH", pluginsDirectory); Environment.SetEnvironmentVariable("QT_PLUGIN_PATH", pluginsDirectory);
var qmlDirectory = Path.Combine(directory, "qml"); var qmlDirectory = Path.Combine(directory, "qt", "qml");
if (!Directory.Exists(qmlDirectory)) if (!Directory.Exists(qmlDirectory))
{ {
throw new Exception($"QML directory didn't exist: {qmlDirectory}"); throw new Exception($"QML directory didn't exist: {qmlDirectory}");
} }
Environment.SetEnvironmentVariable("QML2_IMPORT_PATH", qmlDirectory); Environment.SetEnvironmentVariable("QML2_IMPORT_PATH", qmlDirectory);
/*if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) var libDirectory = Path.Combine(directory, "qt", "lib");
if (!Directory.Exists(libDirectory))
{ {
if (!string.IsNullOrEmpty(libDirectory) && 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)
{ {
// Even though we opened up the native dll correctly, we need to add throw new Exception($"Unabled to preload library: {libToPreload}");
// the folder to the path. The reason is because QML plugins aren't
// in the same directory and have trouble finding dependencies
// that are within our lib folder.
Environment.SetEnvironmentVariable(
"PATH",
Environment.GetEnvironmentVariable("PATH") + $";{libDirectory}");
} }
}*/ }
} }
} }
} }