Skip to content

Commit

Permalink
Merge pull request #1918 from libgit2/tfm-change
Browse files Browse the repository at this point in the history
Change TFM to netcoreapp3.1
  • Loading branch information
bording committed Nov 9, 2021
2 parents 66dae0f + 9a9a297 commit ab87189
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 78 deletions.
8 changes: 5 additions & 3 deletions LibGit2Sharp.Tests/GlobalSettingsFixture.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using LibGit2Sharp.Core;
using LibGit2Sharp.Tests.TestHelpers;
Expand Down Expand Up @@ -64,12 +65,13 @@ public void LoadFromSpecifiedPath(string architecture)
var testDir = Path.GetDirectoryName(typeof(GlobalSettingsFixture).Assembly.Location);
var testAppExe = Path.Combine(testDir, $"NativeLibraryLoadTestApp.{architecture}.exe");
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
var platformDir = Path.Combine(tempDir, "plat");
var platformDir = Path.Combine(tempDir, "plat", architecture);
var libraryPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lib", "win32", architecture);

try
{
Directory.CreateDirectory(Path.Combine(platformDir, architecture));
File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, architecture, nativeDllFileName), Path.Combine(platformDir, architecture, nativeDllFileName));
Directory.CreateDirectory(platformDir);
File.Copy(Path.Combine(libraryPath, nativeDllFileName), Path.Combine(platformDir, nativeDllFileName));

var (output, exitCode) = ProcessHelper.RunProcess(testAppExe, arguments: $@"{NativeDllName.Name} ""{platformDir}""", workingDirectory: tempDir);

Expand Down
79 changes: 17 additions & 62 deletions LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
// Restrict the set of directories where the native library is loaded from to safe directories.
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.ApplicationDirectory | DllImportSearchPath.SafeDirectories)]

#pragma warning disable IDE1006 // Naming Styles

// ReSharper disable InconsistentNaming
namespace LibGit2Sharp.Core
{
internal static class NativeMethods
Expand All @@ -22,15 +19,13 @@ internal static class NativeMethods
// An object tied to the lifecycle of the NativeMethods static class.
// This will handle initialization and shutdown of the underlying
// native library.
#pragma warning disable 0414
private static NativeShutdownObject shutdownObject;
#pragma warning restore 0414

static NativeMethods()
{
if (Platform.IsRunningOnNetFramework() || Platform.IsRunningOnNetCore())
{
// Use .NET Core 3.0+ NativeLibrary when available.
// Use NativeLibrary when available.
if (!TryUseNativeLibrary())
{
// NativeLibrary is not available, fall back.
Expand All @@ -40,6 +35,7 @@ static NativeMethods()
// If this call succeeds further DllImports will find the library loaded and not attempt to load it again.
// If it fails the next DllImport will load the library from safe directories.
string nativeLibraryPath = GetGlobalSettingsNativeLibraryPath();

if (nativeLibraryPath != null)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
Expand All @@ -61,89 +57,46 @@ static NativeMethods()
private static string GetGlobalSettingsNativeLibraryPath()
{
string nativeLibraryDir = GlobalSettings.GetAndLockNativeLibraryPath();

if (nativeLibraryDir == null)
{
return null;
}
return Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension());
}

private delegate bool TryLoadLibraryByNameDelegate(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle);
private delegate bool TryLoadLibraryByPathDelegate(string libraryPath, out IntPtr handle);

static TryLoadLibraryByNameDelegate _tryLoadLibraryByName;
static TryLoadLibraryByPathDelegate _tryLoadLibraryByPath;

static bool TryLoadLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
{
if (_tryLoadLibraryByName == null)
{
throw new NotSupportedException();
}
return _tryLoadLibraryByName(libraryName, assembly, searchPath, out handle);
}

static bool TryLoadLibrary(string libraryPath, out IntPtr handle)
{
if (_tryLoadLibraryByPath == null)
{
throw new NotSupportedException();
}
return _tryLoadLibraryByPath(libraryPath, out handle);
return Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension());
}

#if NETSTANDARD
private static bool TryUseNativeLibrary() => false;
#else
private static bool TryUseNativeLibrary()
{
// NativeLibrary is available in .NET Core 3.0+.
// We use reflection to use NativeLibrary so this library can target 'netstandard2.0'.

Type dllImportResolverType = Type.GetType("System.Runtime.InteropServices.DllImportResolver, System.Runtime.InteropServices", throwOnError: false);
Type nativeLibraryType = Type.GetType("System.Runtime.InteropServices.NativeLibrary, System.Runtime.InteropServices", throwOnError: false);
var tryLoadLibraryByName = (TryLoadLibraryByNameDelegate)nativeLibraryType?.GetMethod("TryLoad",
new Type[] { typeof(string), typeof(Assembly), typeof(DllImportSearchPath?), typeof(IntPtr).MakeByRefType() })?.CreateDelegate(typeof(TryLoadLibraryByNameDelegate));
var tryLoadLibraryByPath = (TryLoadLibraryByPathDelegate)nativeLibraryType?.GetMethod("TryLoad",
new Type[] { typeof(string), typeof(IntPtr).MakeByRefType() })?.CreateDelegate(typeof(TryLoadLibraryByPathDelegate));
MethodInfo setDllImportResolver = nativeLibraryType?.GetMethod("SetDllImportResolver", new Type[] { typeof(Assembly), dllImportResolverType });

if (dllImportResolverType == null ||
nativeLibraryType == null ||
tryLoadLibraryByName == null ||
tryLoadLibraryByPath == null ||
setDllImportResolver == null)
{
return false;
}

_tryLoadLibraryByPath = tryLoadLibraryByPath;
_tryLoadLibraryByName = tryLoadLibraryByName;

// NativeMethods.SetDllImportResolver(typeof(NativeMethods).Assembly, ResolveDll);
object resolveDelegate = typeof(NativeMethods).GetMethod(nameof(ResolveDll), BindingFlags.NonPublic | BindingFlags.Static).CreateDelegate(dllImportResolverType);
setDllImportResolver.Invoke(null, new object[] { typeof(NativeMethods).Assembly, resolveDelegate });
NativeLibrary.SetDllImportResolver(typeof(NativeMethods).Assembly, ResolveDll);

return true;
}

private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
IntPtr handle = IntPtr.Zero;

if (libraryName == libgit2)
{
// Use GlobalSettings.NativeLibraryPath when set.
string nativeLibraryPath = GetGlobalSettingsNativeLibraryPath();
if (nativeLibraryPath != null &&
TryLoadLibrary(nativeLibraryPath, out handle))

if (nativeLibraryPath != null && NativeLibrary.TryLoad(nativeLibraryPath, out handle))
{
return handle;
}

// Use Default DllImport resolution.
if (TryLoadLibrary(libraryName, assembly, searchPath, out handle))
if (NativeLibrary.TryLoad(libraryName, assembly, searchPath, out handle))
{
return handle;
}

// We cary a number of .so files for Linux which are linked against various
// We carry a number of .so files for Linux which are linked against various
// libc/OpenSSL libraries. Try them out.
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Expand All @@ -158,16 +111,19 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor
foreach (var runtimeFolder in Directory.GetDirectories(runtimesDirectory, $"*-{processorArchitecture}"))
{
string libPath = Path.Combine(runtimeFolder, "native", $"lib{libraryName}.so");
if (TryLoadLibrary(libPath, out handle))

if (NativeLibrary.TryLoad(libPath, out handle))
{
return handle;
}
}
}
}
}

return handle;
}
#endif

public const int RTLD_NOW = 0x002;

Expand Down Expand Up @@ -2110,4 +2066,3 @@ IntPtr data
git_worktree_prune_options options);
}
}
// ReSharper restore InconsistentNaming
2 changes: 1 addition & 1 deletion LibGit2Sharp/Core/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal enum OperatingSystemType

internal static class Platform
{
public static string ProcessorArchitecture => IntPtr.Size == 8 ? "x64" : "x86";
public static string ProcessorArchitecture => RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant();

public static OperatingSystemType OperatingSystem
{
Expand Down
11 changes: 2 additions & 9 deletions LibGit2Sharp/GlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static GlobalSettings()
if (netFX)
{
// For .NET Framework apps the dependencies are deployed to lib/win32/{architecture} directory
nativeLibraryDefaultPath = Path.Combine(GetExecutingAssemblyDirectory(), "lib", "win32");
nativeLibraryDefaultPath = Path.Combine(GetExecutingAssemblyDirectory(), "lib", "win32", Platform.ProcessorArchitecture);
}
else
{
Expand Down Expand Up @@ -159,8 +159,6 @@ public static LogConfiguration LogConfiguration
/// <summary>
/// Sets a path for loading native binaries on .NET Framework or .NET Core.
/// When specified, native library will first be searched under the given path.
/// On .NET Framework a subdirectory corresponding to the architecture ("x86" or "x64") is appended,
/// otherwise the native library is expected to be found in the directory as specified.
///
/// If the library is not found it will be searched in standard search paths:
/// <see cref="DllImportSearchPath.AssemblyDirectory"/>,
Expand All @@ -170,10 +168,6 @@ public static LogConfiguration LogConfiguration
/// This must be set before any other calls to the library,
/// and is not available on other platforms than .NET Framework and .NET Core.
/// </para>
/// <para>
/// If not specified on .NET Framework it defaults to lib/win32 subdirectory
/// of the directory where this assembly is loaded from.
/// </para>
/// </summary>
public static string NativeLibraryPath
{
Expand Down Expand Up @@ -213,8 +207,7 @@ public static string NativeLibraryPath
internal static string GetAndLockNativeLibraryPath()
{
nativeLibraryPathLocked = true;
string result = nativeLibraryPath ?? nativeLibraryDefaultPath;
return Platform.IsRunningOnNetFramework() ? Path.Combine(result, Platform.ProcessorArchitecture) : result;
return nativeLibraryPath ?? nativeLibraryDefaultPath;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion LibGit2Sharp/LibGit2Sharp.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netcoreapp3.1</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Description>LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET</Description>
<Company>LibGit2Sharp contributors</Company>
Expand Down
4 changes: 2 additions & 2 deletions NativeLibraryLoadTestApp/TestApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class TestApp
private static extern IntPtr GetModuleHandle(string path);

[DllImport("kernel32")]
private static extern int GetModuleFileName(IntPtr handle, [Out]StringBuilder path, int size);
private static extern int GetModuleFileName(IntPtr handle, [Out] StringBuilder path, int size);

static int Main(string[] args)
{
Expand All @@ -23,7 +23,7 @@ static int Main(string[] args)

var moduleName = args[0];
var loadFromDirectory = args[1];
var expectedPath = Path.Combine(loadFromDirectory, (IntPtr.Size == 4) ? "x86" : "x64", moduleName + ".dll");
var expectedPath = Path.Combine(loadFromDirectory, moduleName + ".dll");

GlobalSettings.NativeLibraryPath = loadFromDirectory;
var isValid = Repository.IsValid(Path.GetTempPath());
Expand Down

0 comments on commit ab87189

Please sign in to comment.