diff --git a/NativeLand/LibraryFile.cs b/NativeLand/LibraryFile.cs deleted file mode 100644 index 640b91c..0000000 --- a/NativeLand/LibraryFile.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -// NativeLand Copyright (C) 2023-2024 Aptivi -// -// This file is part of NativeLand -// -// NativeLand is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// NativeLand is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -namespace NativeLand -{ - /// - /// A class to store the information about native library file. - /// - public class LibraryFile - { - /// - /// Makes a new instance of this class - /// - /// Filename to use when extracting the library. - /// Library binary. - public LibraryFile(string fileName, byte[] resource) - { - FileName = fileName; - Resource = resource; - } - - /// - /// Filename to use when extracting the library. - /// - public string FileName { get; set; } - - /// - /// Library binary. - /// - public byte[] Resource { get; set; } - - /// - /// Specifies whether this file is a shared library, which can be loaded explicitly with - /// LoadLibraryEx on Windows and dlopen on Linux and MacOs. - /// - /// Default is True, but explicit loading is disabled by default with - /// . - /// - /// Set this to False if this file is not a library, but a supporting file which - /// shouldn't be loaded explicitly when is True. - /// - public bool CanLoadExplicitly { get; set; } = true; - } -} \ No newline at end of file diff --git a/NativeLand/LibraryItem.cs b/NativeLand/LibraryItem.cs index 47b17ea..43e10fc 100644 --- a/NativeLand/LibraryItem.cs +++ b/NativeLand/LibraryItem.cs @@ -18,7 +18,6 @@ // using NativeLand.Tools; -using System; using System.Runtime.InteropServices; namespace NativeLand @@ -28,23 +27,10 @@ namespace NativeLand /// public class LibraryItem { - /// - /// Makes a new instance of this class - /// - /// Binary platform. - /// Binary bitness. - /// A collection of files for this bitness and platform. - public LibraryItem(Platform platform, Architecture bitness, params LibraryFile[] files) - { - Platform = platform; - Bitness = bitness; - Files = files; - } - /// /// Library files. /// - public LibraryFile[] Files { get; set; } + public string[] Files { get; set; } /// /// Platform for which this binary is used. @@ -57,13 +43,16 @@ public LibraryItem(Platform platform, Architecture bitness, params LibraryFile[] public Architecture Bitness { get; set; } /// - /// Unpacks the library and directly loads it if on Windows. + /// Makes a new instance of this class /// - /// Target directory to which library is extracted. - /// Load library explicitly. - public virtual void LoadItem(string targetDirectory, bool loadLibrary) + /// Binary platform. + /// Binary bitness. + /// A collection of absolute paths for files for this bitness and platform. + public LibraryItem(Platform platform, Architecture bitness, params string[] paths) { - throw new InvalidOperationException("This item was never added to the LibraryManager. Create a LibraryManager, add this item and then call LibraryManager.LoadNativeLibrary()."); + Platform = platform; + Bitness = bitness; + Files = paths; } } } diff --git a/NativeLand/LibraryItemInternal.cs b/NativeLand/LibraryItemInternal.cs deleted file mode 100644 index 7d46211..0000000 --- a/NativeLand/LibraryItemInternal.cs +++ /dev/null @@ -1,140 +0,0 @@ -// -// NativeLand Copyright (C) 2023-2024 Aptivi -// -// This file is part of NativeLand -// -// NativeLand is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// NativeLand is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Security.Cryptography; -using Microsoft.Extensions.Logging; -using NativeLand.Tools; - -namespace NativeLand -{ - internal class LibraryItemInternal : LibraryItem - { - private readonly ILogger _logger; - - internal LibraryItemInternal(LibraryItem item, ILogger logger = null) - : base(item.Platform, item.Bitness, item.Files) - { - _logger = logger; - } - - public override void LoadItem(string targetDirectory, bool loadLibrary) - { - foreach (var file in Files) - { - string path = Path.Combine(targetDirectory, file.FileName); - - _logger?.LogInformation($"Unpacking native library {file.FileName} to {path}"); - - UnpackFile(path, file.Resource); - - if (!loadLibrary || !file.CanLoadExplicitly) - { - continue; - } - - if (Platform == Platform.Windows) - { - LoadWindowsLibrary(path); - } - else if (Platform == Platform.Linux || Platform == Platform.MacOS) - { - LoadNixLibrary(path); - } - } - } - - private void UnpackFile(string path, byte[] bytes) - { - if (File.Exists(path)) - { - _logger?.LogInformation($"File {path} already exists, computing hashes."); - using var md5 = MD5.Create(); - using var stream = File.OpenRead(path); - string fileHash = BitConverter.ToString(md5.ComputeHash(stream)); - string curHash = BitConverter.ToString(md5.ComputeHash(bytes)); - - if (string.Equals(fileHash, curHash)) - { - _logger?.LogInformation($"Hashes are equal, no need to unpack."); - return; - } - } - - File.WriteAllBytes(path, bytes); - } - - internal void LoadNixLibrary(string path) - { - _logger?.LogInformation($"Calling dlopen for {path}"); - try - { - var result = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); - _logger?.LogInformation(result == IntPtr.Zero ? "FAILED!" : "Success"); - } - catch (Exception ex) - { - _logger?.LogWarning($"libdl.so may not be found. Trying with libdl.so.2... {ex.Message}"); - var result = dlopen_new(path, RTLD_LAZY | RTLD_GLOBAL); - _logger?.LogInformation(result == IntPtr.Zero ? "FAILED!" : "Success"); - } - } - - internal void LoadWindowsLibrary(string path) - { - _logger?.LogInformation($"Calling LoadLibraryEx for {path}..."); - var result = LoadLibraryEx(path, IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_SYSTEM32 | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_USER_DIRS); - _logger?.LogInformation(result == IntPtr.Zero ? "FAILED!" : "Success"); - } - - #region dlopen - private const int RTLD_LAZY = 0x00001; // Only resolve symbols as needed - private const int RTLD_GLOBAL = 0x00100; // Make symbols available to libraries loaded later - - [DllImport("dl")] - private static extern IntPtr dlopen(string file, int mode); - - [DllImport("libdl.so.2", EntryPoint = "dlopen")] - private static extern IntPtr dlopen_new(string file, int mode); - #endregion - - #region LoadLibraryEx - [Flags] - private enum LoadLibraryFlags : uint - { - DONT_RESOLVE_DLL_REFERENCES = 0x00000001, - LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, - LOAD_LIBRARY_AS_DATAFILE = 0x00000002, - LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, - LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, - LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200, - LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000, - LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100, - LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800, - LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400, - LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 - } - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags); - #endregion - } -} diff --git a/NativeLand/LibraryManager.cs b/NativeLand/LibraryManager.cs index 1cb9b4b..ed93799 100644 --- a/NativeLand/LibraryManager.cs +++ b/NativeLand/LibraryManager.cs @@ -24,6 +24,7 @@ using Microsoft.Extensions.Logging; using NativeLand.Exceptions; using NativeLand.Tools; +using SpecProbe.Platform; namespace NativeLand { @@ -32,86 +33,10 @@ namespace NativeLand /// public class LibraryManager { - private readonly object _resourceLocker = new object(); - private readonly LibraryItemInternal[] _items; + private readonly object _resourceLocker = new(); + private readonly LibraryItem[] _items; private readonly ILogger _logger; - private bool _libLoaded = false; - - /// - /// Creates a new library manager which extracts to environment current directory by default. - /// - /// Library binaries for different platforms. - public LibraryManager(params LibraryItem[] items) - : this(Environment.CurrentDirectory, false, null, items) - { - } - - /// - /// Creates a new library manager which extracts to environment current directory by default. - /// - /// Logger factory. - /// Library binaries for different platforms. - public LibraryManager(ILoggerFactory loggerFactory, params LibraryItem[] items) - : this(Environment.CurrentDirectory, false, loggerFactory, items) - { - } - - /// - /// Creates a new library manager which extracts to a custom directory. - /// - /// IMPORTANT! Be sure this directory is discoverable by system library loader. Otherwise, your library won't be loaded. - /// - /// Target directory to extract the libraries. - /// Logger factory. - /// Library binaries for different platforms. - public LibraryManager(string targetDirectory, ILoggerFactory loggerFactory, params LibraryItem[] items) - : this(targetDirectory, true, loggerFactory, items) - { - } - - private LibraryManager(string targetDirectory, bool customDirectory, ILoggerFactory loggerFactory, params LibraryItem[] items) - { - TargetDirectory = targetDirectory; - var itemLogger = loggerFactory?.CreateLogger(); - - _logger = loggerFactory?.CreateLogger(); - _items = items.Select(x => new LibraryItemInternal(x, itemLogger)).ToArray(); - - if (customDirectory) - { - _logger?.LogWarning("Custom directory for native libraries is specified. Be sure it is discoverable by system library loader."); - } - } - - /// - /// Target directory to which native libraries will be extracted. Defaults to directory - /// in which targetAssembly, passed to constructor, resides. - /// - public string TargetDirectory { get; } - - /// - /// Defines whether shared libraries will be loaded explicitly. LoadLibraryEx is - /// used on Windows and dlopen is used on Linux and MacOs to load libraries - /// explicitly. - /// - /// WARNING! Explicit library loading on MacOs IS USELESS, and your P/Invoke call will fail unless - /// library path is discoverable by system library loader. - /// - public bool LoadLibraryExplicit { get; set; } = false; - - /// - /// Extract and load native library based on current platform and process bitness. - /// Throws an exception if current platform is not supported. - /// - /// - /// Use LoadLibrary API call on Windows to explicitly load library into the process. - /// - [Obsolete("This method is obsolete. Use LoadLibraryExplicit property.")] - public void LoadNativeLibrary(bool loadLibrary) - { - LoadNativeLibrary(); - } /// /// Extract and load native library based on current platform and process bitness. @@ -120,25 +45,16 @@ public void LoadNativeLibrary(bool loadLibrary) public void LoadNativeLibrary() { if (_libLoaded) - { return; - } lock (_resourceLocker) { if (_libLoaded) - { return; - } var item = FindItem(); - - if (item.Platform == Platform.MacOS && LoadLibraryExplicit) - { - _logger?.LogWarning("Current platform is MacOS and LoadLibraryExplicit is specified. Explicit library loading on MacOs IS USELESS, and your P/Invoke call will fail unless library path is discoverable by system library loader."); - } - item.LoadItem(TargetDirectory, LoadLibraryExplicit); + LoadLibraries(item); _libLoaded = true; } @@ -160,30 +76,117 @@ public LibraryItem FindItem() return item; } - /// - /// Gets the platform type. - /// - /// Thrown when platform is not supported. - public static Platform GetPlatform() - { - string windir = Environment.GetEnvironmentVariable("windir"); - if ((!string.IsNullOrEmpty(windir) && windir.Contains(@"\") && Directory.Exists(windir)) || - Environment.OSVersion.Platform == PlatformID.Win32NT) - return Platform.Windows; - else if (File.Exists(@"/proc/sys/kernel/ostype")) - { - string osType = File.ReadAllText(@"/proc/sys/kernel/ostype"); - if (osType.StartsWith("Linux", StringComparison.OrdinalIgnoreCase)) - return Platform.Linux; - else - throw new UnsupportedPlatformException($"Unsupported OS: {osType}"); + /// + /// Gets the platform type. + /// + /// Thrown when platform is not supported. + public static Platform GetPlatform() => + PlatformHelper.IsOnWindows() ? Platform.Windows : + PlatformHelper.IsOnMacOS() ? Platform.MacOS : + PlatformHelper.IsOnUnix() ? Platform.Linux : + throw new UnsupportedPlatformException("Unsupported platform."); + + internal void LoadLibraries(LibraryItem item) + { + foreach (var file in item.Files) + { + if (!File.Exists(file)) + throw new FileNotFoundException($"Can't find library file {file}"); + if (item.Platform == Platform.Windows) + LoadWindowsLibrary(file); + else if (item.Platform == Platform.Linux || item.Platform == Platform.MacOS) + LoadNixLibrary(file); + else + throw new UnsupportedPlatformException($"Can't load library on platform {item.Platform} [{(int)item.Platform}]"); } - else if (File.Exists(@"/System/Library/CoreServices/SystemVersion.plist")) - return Platform.MacOS; - else if (Environment.OSVersion.Platform == PlatformID.Unix) - return Platform.Linux; - else - throw new UnsupportedPlatformException("Unsupported OS!"); - } - } + } + + internal void LoadNixLibrary(string path) + { + _logger?.LogInformation($"Calling dlopen for {path}"); + try + { + var result = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); + _logger?.LogInformation(result == IntPtr.Zero ? "FAILED!" : "Success"); + } + catch (Exception ex) + { + _logger?.LogWarning($"libdl.so may not be found. Trying with libdl.so.2... {ex.Message}"); + var result = dlopen_new(path, RTLD_LAZY | RTLD_GLOBAL); + _logger?.LogInformation(result == IntPtr.Zero ? "FAILED!" : "Success"); + } + } + + internal void LoadWindowsLibrary(string path) + { + _logger?.LogInformation($"Calling LoadLibraryEx for {path}..."); + string folder = Path.GetDirectoryName(path); + var cookie = AddDllDirectory(folder); + var result = LoadLibraryEx(path, IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_SYSTEM32 | LoadLibraryFlags.LOAD_LIBRARY_SEARCH_USER_DIRS); + _logger?.LogInformation(result == IntPtr.Zero ? "FAILED!" : "Success"); + } + + #region dlopen + private const int RTLD_LAZY = 0x00001; // Only resolve symbols as needed + private const int RTLD_GLOBAL = 0x00100; // Make symbols available to libraries loaded later + + [DllImport("dl")] + private static extern IntPtr dlopen(string file, int mode); + + [DllImport("libdl.so.2", EntryPoint = "dlopen")] + private static extern IntPtr dlopen_new(string file, int mode); + #endregion + + #region LoadLibraryEx + [StructLayout(LayoutKind.Sequential)] + private struct DllDirectoryCookie + { + private nint value; + } + + [Flags] + private enum LoadLibraryFlags : uint + { + DONT_RESOLVE_DLL_REFERENCES = 0x00000001, + LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, + LOAD_LIBRARY_AS_DATAFILE = 0x00000002, + LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, + LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, + LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200, + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000, + LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100, + LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800, + LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400, + LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 + } + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern DllDirectoryCookie AddDllDirectory(string path); + #endregion + + /// + /// Creates a new library manager which extracts to environment current directory by default. + /// + /// Library binaries for different platforms. + public LibraryManager(params LibraryItem[] items) + : this(null, items) + { + } + + /// + /// Creates a new library manager which extracts to environment current directory by default. + /// + /// Logger factory. + /// Library binaries for different platforms. + public LibraryManager(ILoggerFactory loggerFactory, params LibraryItem[] items) + { + var itemLogger = loggerFactory?.CreateLogger(); + + _logger = loggerFactory?.CreateLogger(); + _items = items; + } + } } diff --git a/NativeLand/NativeLand.csproj b/NativeLand/NativeLand.csproj index 09b45cd..3021d79 100644 --- a/NativeLand/NativeLand.csproj +++ b/NativeLand/NativeLand.csproj @@ -36,6 +36,7 @@ + diff --git a/NativeLand/Tools/PathHelper.cs b/NativeLand/Tools/PathHelper.cs index 90e21ab..84f474b 100644 --- a/NativeLand/Tools/PathHelper.cs +++ b/NativeLand/Tools/PathHelper.cs @@ -39,13 +39,9 @@ public static string GetCurrentDirectory(this Assembly targetAssembly) string curDir; var ass = targetAssembly.Location; if (string.IsNullOrEmpty(ass)) - { curDir = Environment.CurrentDirectory; - } else - { curDir = Path.GetDirectoryName(ass); - } return curDir; } @@ -61,4 +57,4 @@ public static string CombineWithCurrentDirectory(this Assembly targetAssembly, s return !string.IsNullOrEmpty(curDir) ? Path.Combine(curDir, fileName) : fileName; } } -} \ No newline at end of file +} diff --git a/NativeLand/Tools/ResourceAccessor.cs b/NativeLand/Tools/ResourceAccessor.cs deleted file mode 100644 index 273e18a..0000000 --- a/NativeLand/Tools/ResourceAccessor.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// NativeLand Copyright (C) 2023-2024 Aptivi -// -// This file is part of NativeLand -// -// NativeLand is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// NativeLand is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using System; -using System.IO; -using System.Reflection; - -namespace NativeLand.Tools -{ - /// - /// A helper class to load resources from an assembly. - /// - public class ResourceAccessor - { - private readonly Assembly _assembly; - private readonly string _assemblyName; - - /// - /// Creates a resource accessor for the specified assembly. - /// - public ResourceAccessor(Assembly assembly) - { - _assembly = assembly; - _assemblyName = _assembly.GetName().Name; - } - - /// - /// Gets a resource with specified name as an array of bytes. - /// - /// Resource name with folders separated by dots. - /// - /// When resource is not found. - /// - public byte[] Binary(string name) - { - using (var stream = new MemoryStream()) - { - var resource = _assembly.GetManifestResourceStream(GetName(name)); - if (resource == null) - { - throw new InvalidOperationException("Resource not available."); - } - - resource.CopyTo(stream); - - return stream.ToArray(); - } - } - - private string GetName(string name) => - name.StartsWith(_assemblyName) ? name : $"{_assemblyName}.{name}"; - } -} \ No newline at end of file diff --git a/TestProcess/Program.cs b/TestProcess/Program.cs index c834727..f9cffe4 100644 --- a/TestProcess/Program.cs +++ b/TestProcess/Program.cs @@ -19,7 +19,6 @@ using System; using System.IO; -using System.Reflection; using System.Runtime.InteropServices; using Microsoft.Extensions.Logging; using NativeLand; @@ -31,27 +30,13 @@ namespace TestProcess { internal class Program { - private static ILoggerFactory _factory; - internal static int Main() { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Console() .CreateLogger(); - var factory = new LoggerFactory(new[] {new SerilogLoggerProvider() }); - - _factory = factory; - try - { - File.Delete("libTestLib.dylib"); - File.Delete("libTestLib.so"); - File.Delete("TestLib.dll"); - } - catch (Exception e) - { - Log.ForContext().Warning(e, $"Failed to cleanup libraries before running a test: {e.Message}"); - } + var factory = new LoggerFactory([new SerilogLoggerProvider()]); try { @@ -68,17 +53,15 @@ internal static int Main() private static int CanLoadLibraryFromCurrentDirAndCallFunction() { - var accessor = new ResourceAccessor(Assembly.GetExecutingAssembly()); var libManager = new LibraryManager( - _factory, new LibraryItem(Platform.MacOS, Architecture.X64, - new LibraryFile("libTestLib.dylib", accessor.Binary("libTestLib.dylib"))), + Path.GetFullPath("libTestLib.dylib")), new LibraryItem(Platform.Windows, Architecture.X64, - new LibraryFile("TestLib.dll", accessor.Binary("TestLib.dll"))), + Path.GetFullPath("TestLib.dll")), new LibraryItem(Platform.Linux, Architecture.X64, - new LibraryFile("libTestLib.so", accessor.Binary("libTestLib.so"))), + Path.GetFullPath("libTestLib.so")), new LibraryItem(Platform.Linux, Architecture.Arm64, - new LibraryFile("libTestLib.so", accessor.Binary("libTestLib_Arm64.so")))); + Path.GetFullPath("libTestLib_Arm64.so"))); libManager.LoadNativeLibrary(); @@ -93,22 +76,20 @@ private static int CanLoadLibraryFromTempDirAndCallFunction() { string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); Directory.CreateDirectory(tempDir); + File.Copy(Path.GetFullPath("libTestLib.dylib"), tempDir + "/libTestLib.dylib"); + File.Copy(Path.GetFullPath("TestLib.dll"), tempDir + "/TestLib.dll"); + File.Copy(Path.GetFullPath("libTestLib.so"), tempDir + "/libTestLib.so"); + File.Copy(Path.GetFullPath("libTestLib_Arm64.so"), tempDir + "/libTestLib_Arm64.so"); - var accessor = new ResourceAccessor(Assembly.GetExecutingAssembly()); var libManager = new LibraryManager( - tempDir, - _factory, new LibraryItem(Platform.MacOS, Architecture.X64, - new LibraryFile("libTestLib.dylib", accessor.Binary("libTestLib.dylib"))), + $"{tempDir}/libTestLib.dylib"), new LibraryItem(Platform.Windows, Architecture.X64, - new LibraryFile("TestLib.dll", accessor.Binary("TestLib.dll"))), + $"{tempDir}/TestLib.dll"), new LibraryItem(Platform.Linux, Architecture.X64, - new LibraryFile("libTestLib.so", accessor.Binary("libTestLib.so"))), + $"{tempDir}/libTestLib.so"), new LibraryItem(Platform.Linux, Architecture.Arm64, - new LibraryFile("libTestLib.so", accessor.Binary("libTestLib_Arm64.so")))) - { - LoadLibraryExplicit = true - }; + $"{tempDir}/libTestLib_Arm64.so")); var item = libManager.FindItem(); libManager.LoadNativeLibrary(); diff --git a/TestProcess/TestProcess.csproj b/TestProcess/TestProcess.csproj index e9b2900..d313a30 100644 --- a/TestProcess/TestProcess.csproj +++ b/TestProcess/TestProcess.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net8.0;net48 @@ -13,14 +13,22 @@ - - - - + - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest +