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

Properly Detect & Handle Musl Systems #1657

Merged
merged 16 commits into from
May 20, 2021
2 changes: 1 addition & 1 deletion binding/Binding.Shared/LibraryLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ private static class Mac

private static class Linux
{
private const string SystemLibrary = "libdl.so";
private const string SystemLibrary = "dl";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattleibow apparently this throws DllNotFoundException on a somewhat clean Ubuntu 20.04 installation


private const int RTLD_LAZY = 1;
private const int RTLD_NOW = 2;
Expand Down
16 changes: 9 additions & 7 deletions binding/Binding.Shared/PlatformConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace HarfBuzzSharp
namespace SkiaSharp
#endif
{
internal static class PlatformConfiguration
public static class PlatformConfiguration
{
public static bool IsUnix { get; }

Expand Down Expand Up @@ -50,18 +50,20 @@ static PlatformConfiguration ()
Is64Bit = IntPtr.Size == 8;
}

public static bool? IsMuslOverride { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically there are other libc implementations, so I'd suggest to have something like

enum LibcFlavor
{
    Glibc,
    Musl
}

Copy link
Contributor Author

@mattleibow mattleibow Mar 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so I changed the whole way of selecting a variant/flavor.

There is now a property LinuxFlavor that can be used to control the whole thing instead of the specific IsMusl. This is useful in cases where there needs to be a specific version of Linux. For example if you need a custom build for say FreeBSD. You can set the flavor at app startup following any checks that you do and then the lookup will use that first.

If the property is null, then I just do the basic glibc/musl check - or rather I check for glibc and assume musl otherwise. If a specific flavor is set, then I do nothing and just use that. This is just a plain string that allows for extension later on, and also is just the name of the folder to use.

Example usage would be on a x64 machine:

  • LinuxFlavor == null with glibc => 'x64'
  • LinuxFlavor == null with non-glibc => 'musl-x64'
  • LinuxFlavor == freebsd => 'freebsd-x64'

Since this is totally customizable, you can even do specific checks for versions and set the flavor to opensuse.14 and then it will look in opensuse.14-arm64 if it were running on an ARM64 machine.


#if WINDOWS_UWP
public static bool IsMusl { get; }
#else
private static readonly Lazy<bool> isMuslLazy = new Lazy<bool>(IsMuslImplementation);
private static readonly Lazy<bool> isMuslLazy = new Lazy<bool> (IsMuslImplementation);

public static bool IsMusl => IsLinux && isMuslLazy.Value;
public static bool IsMusl => IsLinux && (IsMuslOverride ?? isMuslLazy.Value);

private static bool IsMuslImplementation()
private static bool IsMuslImplementation ()
{
try
{
gnu_get_libc_version();
gnu_get_libc_version ();
return false;
}
catch (TypeLoadException)
Expand All @@ -70,8 +72,8 @@ private static bool IsMuslImplementation()
}
}

[DllImport("libc", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr gnu_get_libc_version();
[DllImport ("c", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr gnu_get_libc_version ();
#endif
}
}