121 lines
5.3 KiB
C#
121 lines
5.3 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace MonoMod.Utils {
|
|
[MonoMod__OldName__("MonoMod.Helpers.PlatformHelper")]
|
|
public static class PlatformHelper {
|
|
|
|
static PlatformHelper() {
|
|
Current = Platform.Unknown;
|
|
|
|
#if NETSTANDARD
|
|
// RuntimeInformation.IsOSPlatform is lying: https://github.com/dotnet/corefx/issues/3032
|
|
// Determine the platform based on the path.
|
|
string windir = Environment.GetEnvironmentVariable("windir");
|
|
if (!string.IsNullOrEmpty(windir) && windir.Contains(@"\") && Directory.Exists(windir)) {
|
|
Current = Platform.Windows;
|
|
|
|
} else if (File.Exists("/proc/sys/kernel/ostype")) {
|
|
string osType = File.ReadAllText("/proc/sys/kernel/ostype");
|
|
if (osType.StartsWith("Linux", StringComparison.OrdinalIgnoreCase)) {
|
|
Current = Platform.Linux;
|
|
}
|
|
|
|
} else if (File.Exists("/System/Library/CoreServices/SystemVersion.plist")) {
|
|
Current = Platform.MacOS;
|
|
}
|
|
|
|
#else
|
|
// For old Mono, get from a private property to accurately get the platform.
|
|
// static extern PlatformID Platform
|
|
PropertyInfo p_Platform = typeof(Environment).GetProperty("Platform", BindingFlags.NonPublic | BindingFlags.Static);
|
|
string platID;
|
|
if (p_Platform != null) {
|
|
platID = p_Platform.GetValue(null, new object[0]).ToString();
|
|
} else {
|
|
// For .NET and newer Mono, use the usual value.
|
|
platID = Environment.OSVersion.Platform.ToString();
|
|
}
|
|
platID = platID.ToLowerInvariant();
|
|
|
|
if (platID.Contains("win")) {
|
|
Current = Platform.Windows;
|
|
} else if (platID.Contains("mac") || platID.Contains("osx")) {
|
|
Current = Platform.MacOS;
|
|
} else if (platID.Contains("lin") || platID.Contains("unix")) {
|
|
Current = Platform.Linux;
|
|
}
|
|
#endif
|
|
|
|
if (Directory.Exists("/data") && File.Exists("/system/build.prop")) {
|
|
Current = Platform.Android;
|
|
} else if (Directory.Exists("/Applications") && Directory.Exists("/System")) {
|
|
Current = Platform.iOS;
|
|
}
|
|
|
|
// Is64BitOperatingSystem has been added in .NET 4.0
|
|
MethodInfo m_get_Is64BitOperatingSystem = typeof(Environment).GetProperty("Is64BitOperatingSystem")?.GetGetMethod();
|
|
if (m_get_Is64BitOperatingSystem != null)
|
|
Current |= (((bool) m_get_Is64BitOperatingSystem.Invoke(null, new object[0])) ? Platform.Bits64 : Platform.Bits32);
|
|
else
|
|
Current |= (IntPtr.Size >= 8 ? Platform.Bits64 : Platform.Bits32);
|
|
|
|
#if NETSTANDARD
|
|
// Detect ARM based on RuntimeInformation.
|
|
if (RuntimeInformation.ProcessArchitecture.HasFlag(Architecture.Arm) ||
|
|
RuntimeInformation.OSArchitecture.HasFlag(Architecture.Arm))
|
|
Current |= Platform.ARM;
|
|
#else
|
|
if (Is(Platform.Unix) && Type.GetType("Mono.Runtime") != null) {
|
|
/* I'd love to use RuntimeInformation, but it returns X64 up until...
|
|
* https://github.com/mono/mono/commit/396559769d0e4ca72837e44bcf837b7c91596414
|
|
* ... and that commit still hasn't reached Mono 5.16 on Debian, dated
|
|
* tarball Mon Nov 26 17:21:35 UTC 2018
|
|
* There's also the possibility to [DllImport("libc.so.6")]
|
|
* -ade
|
|
*/
|
|
try {
|
|
string arch;
|
|
using (Process uname = Process.Start(new ProcessStartInfo("uname", "-m") {
|
|
UseShellExecute = false,
|
|
RedirectStandardOutput = true
|
|
})) {
|
|
arch = uname.StandardOutput.ReadLine().Trim();
|
|
}
|
|
|
|
if (arch.StartsWith("aarch") || arch.StartsWith("arm"))
|
|
Current |= Platform.ARM;
|
|
} catch (Exception) {
|
|
// Starting a process can fail for various reasons. One of them being...
|
|
/* System.TypeInitializationException: The type initializer for 'MonoMod.Utils.PlatformHelper' threw an exception. ---> System.MissingMethodException: Method 'MonoIO.CreatePipe' not found.
|
|
* at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) <0x414ceb20 + 0x0061f> in <filename unknown>:0
|
|
*/
|
|
}
|
|
|
|
} else {
|
|
// Detect ARM based on PE info or uname.
|
|
typeof(object).Module.GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine);
|
|
if (machine == (ImageFileMachine) 0x01C4 /* ARM, .NET 4.5 */)
|
|
Current |= Platform.ARM;
|
|
}
|
|
#endif
|
|
|
|
LibrarySuffix =
|
|
Is(Platform.MacOS) ? "dylib" :
|
|
Is(Platform.Unix) ? "so" :
|
|
"dll";
|
|
|
|
}
|
|
|
|
public static Platform Current { get; private set; }
|
|
public static string LibrarySuffix { get; private set; }
|
|
|
|
public static bool Is(Platform platform)
|
|
=> (Current & platform) == platform;
|
|
|
|
}
|
|
}
|