Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change TFM to netcoreapp3.1 #1918

Merged
merged 6 commits into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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