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

Remove unused code from UnmanagedLibrary #3799

Merged
merged 2 commits into from
Oct 28, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
268 changes: 15 additions & 253 deletions Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#define GUICS
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;

Expand All @@ -27,81 +26,6 @@ namespace Unix.Terminal;
/// </summary>
internal class UnmanagedLibrary
{
private const string UnityEngineApplicationClassName = "UnityEngine.Application, UnityEngine";
private const string XamarinAndroidObjectClassName = "Java.Lang.Object, Mono.Android";
private const string XamarinIOSObjectClassName = "Foundation.NSObject, Xamarin.iOS";
private static readonly bool IsWindows;
private static readonly bool IsLinux;
private static readonly bool Is64Bit;
#if GUICS
private static readonly bool IsMono;
#else
static bool IsMono, IsUnity, IsXamarinIOS, IsXamarinAndroid, IsXamarin;
#endif
private static bool IsNetCore;
public static bool IsMacOSPlatform { get; }

[DllImport ("libc")]
private static extern int uname (nint buf);

private static string GetUname ()
{
nint buffer = Marshal.AllocHGlobal (8192);

try
{
if (uname (buffer) == 0)
{
return Marshal.PtrToStringAnsi (buffer);
}

return string.Empty;
}
catch
{
return string.Empty;
}
finally
{
if (buffer != nint.Zero)
{
Marshal.FreeHGlobal (buffer);
}
}
}

[UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
static UnmanagedLibrary ()
{
PlatformID platform = Environment.OSVersion.Platform;

IsMacOSPlatform = platform == PlatformID.Unix && GetUname () == "Darwin";
IsLinux = platform == PlatformID.Unix && !IsMacOSPlatform;

IsWindows = platform == PlatformID.Win32NT
|| platform == PlatformID.Win32S
|| platform == PlatformID.Win32Windows;
Is64Bit = Marshal.SizeOf (typeof (nint)) == 8;
IsMono = Type.GetType ("Mono.Runtime") != null;

if (!IsMono)
{
IsNetCore = Type.GetType ("System.MathF") != null;
}
#if GUICS

//IsUnity = IsXamarinIOS = IsXamarinAndroid = IsXamarin = false;
#else
IsUnity = Type.GetType (UnityEngineApplicationClassName) != null;
IsXamarinIOS = Type.GetType (XamarinIOSObjectClassName) != null;
IsXamarinAndroid = Type.GetType (XamarinAndroidObjectClassName) != null;
IsXamarin = IsXamarinIOS || IsXamarinAndroid;
#endif
}

// flags for dlopen
private const int RTLD_LAZY = 1;
private const int RTLD_GLOBAL = 8;
public readonly string LibraryPath;
public nint NativeLibraryHandle { get; }

Expand All @@ -114,15 +38,25 @@ public UnmanagedLibrary (string [] libraryPathAlternatives, bool isFullPath)
{
if (isFullPath)
{
LibraryPath = FirstValidLibraryPath (libraryPathAlternatives);
NativeLibraryHandle = PlatformSpecificLoadLibrary (LibraryPath);
foreach (string path in libraryPathAlternatives)
{
if (File.Exists (path))
{
LibraryPath = path;
break;
}
}

if (LibraryPath is null)
throw new FileNotFoundException ($"Error loading native library. Not found in any of the possible locations: {string.Join (",", libraryPathAlternatives)}");

NativeLibraryHandle = NativeLibrary.Load (LibraryPath);
}
else
{
foreach (string lib in libraryPathAlternatives)
{
NativeLibraryHandle = PlatformSpecificLoadLibrary (lib);

NativeLibraryHandle = NativeLibrary.Load (lib);
if (NativeLibraryHandle != nint.Zero)
{
LibraryPath = lib;
Expand All @@ -143,55 +77,7 @@ public UnmanagedLibrary (string [] libraryPathAlternatives, bool isFullPath)
/// <returns></returns>
public nint LoadSymbol (string symbolName)
{
if (IsWindows)
{
// See http://stackoverflow.com/questions/10473310 for background on this.
if (Is64Bit)
{
return Windows.GetProcAddress (NativeLibraryHandle, symbolName);
}

// Yes, we could potentially predict the size... but it's a lot simpler to just try
// all the candidates. Most functions have a suffix of @0, @4 or @8 so we won't be trying
// many options - and if it takes a little bit longer to fail if we've really got the wrong
// library, that's not a big problem. This is only called once per function in the native library.
symbolName = "_" + symbolName + "@";

for (var stackSize = 0; stackSize < 128; stackSize += 4)
{
nint candidate = Windows.GetProcAddress (NativeLibraryHandle, symbolName + stackSize);

if (candidate != nint.Zero)
{
return candidate;
}
}

// Fail.
return nint.Zero;
}

if (IsLinux)
{
if (IsMono)
{
return Mono.dlsym (NativeLibraryHandle, symbolName);
}

if (IsNetCore)
{
return CoreCLR.dlsym (NativeLibraryHandle, symbolName);
}

return Linux.dlsym (NativeLibraryHandle, symbolName);
}

if (IsMacOSPlatform)
{
return MacOSX.dlsym (NativeLibraryHandle, symbolName);
}

throw new InvalidOperationException ("Unsupported platform.");
return NativeLibrary.GetExport(NativeLibraryHandle, symbolName);
}

public T GetNativeMethodDelegate<T> (string methodName)
Expand All @@ -206,128 +92,4 @@ public T GetNativeMethodDelegate<T> (string methodName)

return Marshal.GetDelegateForFunctionPointer<T> (ptr); // non-generic version is obsolete
}

/// <summary>Loads library in a platform specific way.</summary>
private static nint PlatformSpecificLoadLibrary (string libraryPath)
{
if (IsWindows)
{
return Windows.LoadLibrary (libraryPath);
}

if (IsLinux)
{
if (IsMono)
{
return Mono.dlopen (libraryPath, RTLD_GLOBAL + RTLD_LAZY);
}

if (IsNetCore)
{
try
{
return CoreCLR.dlopen (libraryPath, RTLD_GLOBAL + RTLD_LAZY);
}
catch (Exception)
{
IsNetCore = false;
}
}

return Linux.dlopen (libraryPath, RTLD_GLOBAL + RTLD_LAZY);
}

if (IsMacOSPlatform)
{
return MacOSX.dlopen (libraryPath, RTLD_GLOBAL + RTLD_LAZY);
}

throw new InvalidOperationException ("Unsupported platform.");
}

private static string FirstValidLibraryPath (string [] libraryPathAlternatives)
{
foreach (string path in libraryPathAlternatives)
{
if (File.Exists (path))
{
return path;
}
}

throw new FileNotFoundException (
string.Format (
"Error loading native library. Not found in any of the possible locations: {0}",
string.Join (",", libraryPathAlternatives)
)
);
}

private static class Windows
{
[DllImport ("kernel32.dll")]
internal static extern nint GetProcAddress (nint hModule, string procName);

[DllImport ("kernel32.dll")]
internal static extern nint LoadLibrary (string filename);
}

private static class Linux
{
[DllImport ("libdl.so")]
internal static extern nint dlopen (string filename, int flags);

[DllImport ("libdl.so")]
internal static extern nint dlsym (nint handle, string symbol);
}

private static class MacOSX
{
[DllImport ("libSystem.dylib")]
internal static extern nint dlopen (string filename, int flags);

[DllImport ("libSystem.dylib")]
internal static extern nint dlsym (nint handle, string symbol);
}

/// <summary>
/// On Linux systems, using dlopen and dlsym results in DllNotFoundException("libdl.so not found") if
/// libc6-dev is not installed. As a workaround, we load symbols for dlopen and dlsym from the current process as on
/// Linux Mono sure is linked against these symbols.
/// </summary>
private static class Mono
{
[DllImport ("__Internal")]
internal static extern nint dlopen (string filename, int flags);

[DllImport ("__Internal")]
internal static extern nint dlsym (nint handle, string symbol);
}

/// <summary>
/// Similarly as for Mono on Linux, we load symbols for dlopen and dlsym from the "libcoreclr.so", to avoid the
/// dependency on libc-dev Linux.
/// </summary>
private static class CoreCLR
{
// Custom resolver to support true single-file apps
// (those which run directly from bundle; in-memory).
// -1 on Unix means self-referencing binary (libcoreclr.so)
// 0 means fallback to CoreCLR's internal resolution
// Note: meaning of -1 stay the same even for non-single-file form factors.
static CoreCLR ()
{
NativeLibrary.SetDllImportResolver (
typeof (CoreCLR).Assembly,
(libraryName, assembly, searchPath) =>
libraryName == "libcoreclr.so" ? -1 : nint.Zero
);
}

[DllImport ("libcoreclr.so")]
internal static extern nint dlopen (string filename, int flags);

[DllImport ("libcoreclr.so")]
internal static extern nint dlsym (nint handle, string symbol);
}
}
6 changes: 3 additions & 3 deletions Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,9 @@ private static nint get_ptr (string key)

private static void LoadMethods ()
{
string [] libs = UnmanagedLibrary.IsMacOSPlatform
? new [] { "libncurses.dylib" }
: new [] { "libncursesw.so.6", "libncursesw.so.5" };
string [] libs = OperatingSystem.IsMacOS()
? ["libncurses.dylib"]
: ["libncursesw.so.6", "libncursesw.so.5"];
var attempts = 1;

while (true)
Expand Down
Loading