Skip to content

Commit

Permalink
Better OS detection for native libs (#50)
Browse files Browse the repository at this point in the history
* Allow detection of Android OS on .NetStandard builds and use uname -m on those platforms if possible

* Use Marshal.SizeOf instead of Unsafe.SizeOf

* Fix conditional compilation flags messing up NetFX logic. Try and detect OSX on netframework (Mono?).

* Bump nuget version

* even more thorough checking on .NetFramework since apparently many non-windows functions never worked correctly
  • Loading branch information
lostromb authored May 26, 2024
1 parent e42b40f commit 6c2328d
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 23 deletions.
2 changes: 1 addition & 1 deletion CSharp/Concentus/Concentus.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\Concentus.snk</AssemblyOriginatorKeyFile>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>2.2.1</Version>
<Version>2.2.2</Version>
<Authors>Logan Stromberg</Authors>
<Description>This package is a portable C# implementation of the Opus audio compression codec (see https://opus-codec.org/ for more details). This package contains the Opus encoder, decoder, multistream codecs, repacketizer, as well as a port of the libspeexdsp resampler. It does NOT contain code to parse .ogg or .opus container files or to manage RTP packet streams. For better performance depending on your platform, see also the Concentus.Native package.</Description>
<Copyright>© Xiph.Org Foundation, Skype Limited, CSIRO, Microsoft Corp.</Copyright>
Expand Down
78 changes: 56 additions & 22 deletions CSharp/Concentus/Native/NativePlatformUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,42 +67,75 @@ internal static OSAndArchitecture GetCurrentPlatformInternal(TextWriter logger)
#endif // NETCOREAPP

// We can sometimes fail to parse new runtime IDs (like if they add "debian" as a runtime ID in the future), so fall back if needed
#if NET452_OR_GREATER
if (os == PlatformOperatingSystem.Unknown)
{
// Figure out our OS
#if NET452_OR_GREATER
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
try
{
os = PlatformOperatingSystem.Windows;
// Figure out our OS
switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32NT:
case PlatformID.Win32S:
case PlatformID.Win32Windows:
case PlatformID.WinCE:
os = PlatformOperatingSystem.Windows;
break;
case PlatformID.Unix:
case PlatformID.MacOSX:
if (File.Exists(@"/proc/sys/kernel/ostype") &&
File.ReadAllText(@"/proc/sys/kernel/ostype").StartsWith("Linux", StringComparison.OrdinalIgnoreCase))
{
os = PlatformOperatingSystem.Linux;
}
else if (File.Exists(@"/System/Library/CoreServices/SystemVersion.plist"))
{
os = PlatformOperatingSystem.MacOS;
}
else
{
os = PlatformOperatingSystem.Unix;
}
break;
}
}
else if (Environment.OSVersion.Platform == PlatformID.Unix)
catch (Exception e)
{
os = PlatformOperatingSystem.Unix;
logger?.WriteLine(e.ToString());
}
}
#else
if (os == PlatformOperatingSystem.Unknown)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
os = PlatformOperatingSystem.Windows;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
#if !NETSTANDARD1_1
else if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ANDROID_STORAGE")))
{
os = PlatformOperatingSystem.Linux;
os = PlatformOperatingSystem.Android;
}
#endif // !NETSTANDARD1_1
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
os = PlatformOperatingSystem.MacOS;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
os = PlatformOperatingSystem.Linux;
}
#if NET6_0_OR_GREATER
else if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
{
os = PlatformOperatingSystem.FreeBSD;
}
#endif // !NET452_OR_GREATER
#endif // NET6_0_OR_GREATER
}
#endif // !NET452_OR_GREATER

// Figure out our architecture
if (arch == PlatformArchitecture.Unknown)
if (os != PlatformOperatingSystem.Unknown && arch == PlatformArchitecture.Unknown)
{
// First try native kernel interop
arch = TryGetNativeArchitecture(os, logger);
Expand All @@ -112,14 +145,7 @@ internal static OSAndArchitecture GetCurrentPlatformInternal(TextWriter logger)
if (arch == PlatformArchitecture.Unknown)
{
#if NET452_OR_GREATER
if (Environment.Is64BitProcess)
{
arch = PlatformArchitecture.X64;
}
else
{
arch = PlatformArchitecture.I386;
}
arch = Environment.Is64BitProcess ? PlatformArchitecture.X64 : PlatformArchitecture.I386;
#else
switch (RuntimeInformation.ProcessArchitecture)
{
Expand Down Expand Up @@ -191,13 +217,14 @@ internal static NativeLibraryStatus PrepareNativeLibrary(string libraryName, Tex

if (platform.OS == PlatformOperatingSystem.Android)
{
// On android we're not allowed to dlopen shared system binaries directly.
// On android we're not allowed to dlopen shared system binaries directly because of Private API
// (see https://android-developers.googleblog.com/2016/06/android-changes-for-ndk-developers.html)
// So we have to probe and see if there's a native .so provided to us by this application's .apk
logger?.WriteLine($"Probing for {normalizedLibraryName} within local Android .apk");
NativeLibraryStatus androidApkLibStatus = ProbeLibrary(normalizedLibraryName, platform, logger);
if (androidApkLibStatus != NativeLibraryStatus.Available)
{
logger?.WriteLine("Native library \"{0}\" was not found in the local .apk", libraryName);
logger?.WriteLine("Native library \"{0}\" was not found in the local .apk.", libraryName);
return NativeLibraryStatus.Unavailable;
}

Expand Down Expand Up @@ -314,6 +341,8 @@ internal static string GetRuntimeIdString(this PlatformArchitecture architecture
return "s390x";
case PlatformArchitecture.Loongarch64:
return "loongarch64";
case PlatformArchitecture.Itanium64:
return "ia64";
default:
throw new PlatformNotSupportedException("No runtime ID defined for " + architecture.ToString());
}
Expand Down Expand Up @@ -583,6 +612,10 @@ internal static PlatformArchitecture TryParseArchitectureString(ReadOnlySpan<cha
{
return PlatformArchitecture.Loongarch64;
}
else if (arch.Equals("ia64".AsSpan(), StringComparison.OrdinalIgnoreCase))
{
return PlatformArchitecture.Itanium64;
}
else
{
return PlatformArchitecture.Unknown;
Expand All @@ -599,7 +632,7 @@ internal static PlatformArchitecture TryGetNativeArchitecture(PlatformOperatingS
{
case KernelInteropWindows.PROCESSOR_ARCHITECTURE_INTEL:
case KernelInteropWindows.PROCESSOR_ARCHITECTURE_AMD64:
return Unsafe.SizeOf<IntPtr>() == 4 ? PlatformArchitecture.I386 : PlatformArchitecture.X64;
return Marshal.SizeOf(new IntPtr()) == 4 ? PlatformArchitecture.I386 : PlatformArchitecture.X64;
case KernelInteropWindows.PROCESSOR_ARCHITECTURE_ARM:
return PlatformArchitecture.ArmV7;
case KernelInteropWindows.PROCESSOR_ARCHITECTURE_ARM64:
Expand All @@ -614,7 +647,8 @@ internal static PlatformArchitecture TryGetNativeArchitecture(PlatformOperatingS
else if (os == PlatformOperatingSystem.Linux ||
os == PlatformOperatingSystem.Unix ||
os == PlatformOperatingSystem.Linux_Musl ||
os == PlatformOperatingSystem.Linux_Bionic)
os == PlatformOperatingSystem.Linux_Bionic ||
os == PlatformOperatingSystem.Android)
{
PlatformArchitecture? possibleArch = KernelInteropLinux.TryGetArchForUnix(logger);
if (possibleArch.HasValue)
Expand Down

0 comments on commit 6c2328d

Please sign in to comment.