1*cc02d7e2SAndroid Build Coastguard Worker #region Copyright notice and license 2*cc02d7e2SAndroid Build Coastguard Worker 3*cc02d7e2SAndroid Build Coastguard Worker // Copyright 2021 The gRPC Authors 4*cc02d7e2SAndroid Build Coastguard Worker // 5*cc02d7e2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 6*cc02d7e2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 7*cc02d7e2SAndroid Build Coastguard Worker // You may obtain a copy of the License at 8*cc02d7e2SAndroid Build Coastguard Worker // 9*cc02d7e2SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0 10*cc02d7e2SAndroid Build Coastguard Worker // 11*cc02d7e2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 12*cc02d7e2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 13*cc02d7e2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*cc02d7e2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 15*cc02d7e2SAndroid Build Coastguard Worker // limitations under the License. 16*cc02d7e2SAndroid Build Coastguard Worker 17*cc02d7e2SAndroid Build Coastguard Worker #endregion 18*cc02d7e2SAndroid Build Coastguard Worker 19*cc02d7e2SAndroid Build Coastguard Worker using System; 20*cc02d7e2SAndroid Build Coastguard Worker using System.Runtime.CompilerServices; 21*cc02d7e2SAndroid Build Coastguard Worker using System.Runtime.InteropServices; 22*cc02d7e2SAndroid Build Coastguard Worker 23*cc02d7e2SAndroid Build Coastguard Worker namespace Grpc.Core.Internal 24*cc02d7e2SAndroid Build Coastguard Worker { 25*cc02d7e2SAndroid Build Coastguard Worker /// <summary> 26*cc02d7e2SAndroid Build Coastguard Worker /// This source file is shared by both Grpc.Core and Grpc.Tools to avoid duplication 27*cc02d7e2SAndroid Build Coastguard Worker /// of platform detection code. 28*cc02d7e2SAndroid Build Coastguard Worker /// </summary> 29*cc02d7e2SAndroid Build Coastguard Worker internal static class CommonPlatformDetection 30*cc02d7e2SAndroid Build Coastguard Worker { 31*cc02d7e2SAndroid Build Coastguard Worker public enum OSKind { Unknown, Windows, Linux, MacOSX }; 32*cc02d7e2SAndroid Build Coastguard Worker public enum CpuArchitecture { Unknown, X86, X64, Arm64 }; 33*cc02d7e2SAndroid Build Coastguard Worker GetOSKind()34*cc02d7e2SAndroid Build Coastguard Worker public static OSKind GetOSKind() 35*cc02d7e2SAndroid Build Coastguard Worker { 36*cc02d7e2SAndroid Build Coastguard Worker #if NETSTANDARD || NETCORE 37*cc02d7e2SAndroid Build Coastguard Worker if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 38*cc02d7e2SAndroid Build Coastguard Worker { 39*cc02d7e2SAndroid Build Coastguard Worker return OSKind.Windows; 40*cc02d7e2SAndroid Build Coastguard Worker } 41*cc02d7e2SAndroid Build Coastguard Worker else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 42*cc02d7e2SAndroid Build Coastguard Worker { 43*cc02d7e2SAndroid Build Coastguard Worker return OSKind.Linux; 44*cc02d7e2SAndroid Build Coastguard Worker } 45*cc02d7e2SAndroid Build Coastguard Worker else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) 46*cc02d7e2SAndroid Build Coastguard Worker { 47*cc02d7e2SAndroid Build Coastguard Worker return OSKind.MacOSX; 48*cc02d7e2SAndroid Build Coastguard Worker } 49*cc02d7e2SAndroid Build Coastguard Worker else 50*cc02d7e2SAndroid Build Coastguard Worker { 51*cc02d7e2SAndroid Build Coastguard Worker return OSKind.Unknown; 52*cc02d7e2SAndroid Build Coastguard Worker } 53*cc02d7e2SAndroid Build Coastguard Worker #else 54*cc02d7e2SAndroid Build Coastguard Worker var platform = Environment.OSVersion.Platform; 55*cc02d7e2SAndroid Build Coastguard Worker if (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows) 56*cc02d7e2SAndroid Build Coastguard Worker { 57*cc02d7e2SAndroid Build Coastguard Worker return OSKind.Windows; 58*cc02d7e2SAndroid Build Coastguard Worker } 59*cc02d7e2SAndroid Build Coastguard Worker else if (platform == PlatformID.Unix && GetUname() == "Darwin") 60*cc02d7e2SAndroid Build Coastguard Worker { 61*cc02d7e2SAndroid Build Coastguard Worker // PlatformID.MacOSX is never returned, commonly used trick is to identify Mac is by using uname. 62*cc02d7e2SAndroid Build Coastguard Worker return OSKind.MacOSX; 63*cc02d7e2SAndroid Build Coastguard Worker } 64*cc02d7e2SAndroid Build Coastguard Worker else if (platform == PlatformID.Unix) 65*cc02d7e2SAndroid Build Coastguard Worker { 66*cc02d7e2SAndroid Build Coastguard Worker // on legacy .NET Framework, our detection options are limited, so we treat 67*cc02d7e2SAndroid Build Coastguard Worker // all other unix systems as Linux. 68*cc02d7e2SAndroid Build Coastguard Worker return OSKind.Linux; 69*cc02d7e2SAndroid Build Coastguard Worker } 70*cc02d7e2SAndroid Build Coastguard Worker else 71*cc02d7e2SAndroid Build Coastguard Worker { 72*cc02d7e2SAndroid Build Coastguard Worker return OSKind.Unknown; 73*cc02d7e2SAndroid Build Coastguard Worker } 74*cc02d7e2SAndroid Build Coastguard Worker #endif 75*cc02d7e2SAndroid Build Coastguard Worker } 76*cc02d7e2SAndroid Build Coastguard Worker GetProcessArchitecture()77*cc02d7e2SAndroid Build Coastguard Worker public static CpuArchitecture GetProcessArchitecture() 78*cc02d7e2SAndroid Build Coastguard Worker { 79*cc02d7e2SAndroid Build Coastguard Worker #if NETSTANDARD || NETCORE 80*cc02d7e2SAndroid Build Coastguard Worker switch (RuntimeInformation.ProcessArchitecture) 81*cc02d7e2SAndroid Build Coastguard Worker { 82*cc02d7e2SAndroid Build Coastguard Worker case Architecture.X86: 83*cc02d7e2SAndroid Build Coastguard Worker return CpuArchitecture.X86; 84*cc02d7e2SAndroid Build Coastguard Worker case Architecture.X64: 85*cc02d7e2SAndroid Build Coastguard Worker return CpuArchitecture.X64; 86*cc02d7e2SAndroid Build Coastguard Worker case Architecture.Arm64: 87*cc02d7e2SAndroid Build Coastguard Worker return CpuArchitecture.Arm64; 88*cc02d7e2SAndroid Build Coastguard Worker // We do not support other architectures, 89*cc02d7e2SAndroid Build Coastguard Worker // so we simply return "unrecognized". 90*cc02d7e2SAndroid Build Coastguard Worker default: 91*cc02d7e2SAndroid Build Coastguard Worker return CpuArchitecture.Unknown; 92*cc02d7e2SAndroid Build Coastguard Worker } 93*cc02d7e2SAndroid Build Coastguard Worker #else 94*cc02d7e2SAndroid Build Coastguard Worker // on legacy .NET Framework, RuntimeInformation is not available 95*cc02d7e2SAndroid Build Coastguard Worker // but our choice of supported architectures there 96*cc02d7e2SAndroid Build Coastguard Worker // is also very limited, so we simply take our best guess. 97*cc02d7e2SAndroid Build Coastguard Worker return Environment.Is64BitProcess ? CpuArchitecture.X64 : CpuArchitecture.X86; 98*cc02d7e2SAndroid Build Coastguard Worker #endif 99*cc02d7e2SAndroid Build Coastguard Worker } 100*cc02d7e2SAndroid Build Coastguard Worker 101*cc02d7e2SAndroid Build Coastguard Worker [DllImport("libc")] uname(IntPtr buf)102*cc02d7e2SAndroid Build Coastguard Worker static extern int uname(IntPtr buf); 103*cc02d7e2SAndroid Build Coastguard Worker 104*cc02d7e2SAndroid Build Coastguard Worker // This code is copied from Grpc.Core/PlatformApis.cs GetUname()105*cc02d7e2SAndroid Build Coastguard Worker static string GetUname() 106*cc02d7e2SAndroid Build Coastguard Worker { 107*cc02d7e2SAndroid Build Coastguard Worker var buffer = Marshal.AllocHGlobal(8192); 108*cc02d7e2SAndroid Build Coastguard Worker try 109*cc02d7e2SAndroid Build Coastguard Worker { 110*cc02d7e2SAndroid Build Coastguard Worker if (uname(buffer) == 0) 111*cc02d7e2SAndroid Build Coastguard Worker { 112*cc02d7e2SAndroid Build Coastguard Worker return Marshal.PtrToStringAnsi(buffer); 113*cc02d7e2SAndroid Build Coastguard Worker } 114*cc02d7e2SAndroid Build Coastguard Worker return string.Empty; 115*cc02d7e2SAndroid Build Coastguard Worker } 116*cc02d7e2SAndroid Build Coastguard Worker catch 117*cc02d7e2SAndroid Build Coastguard Worker { 118*cc02d7e2SAndroid Build Coastguard Worker return string.Empty; 119*cc02d7e2SAndroid Build Coastguard Worker } 120*cc02d7e2SAndroid Build Coastguard Worker finally 121*cc02d7e2SAndroid Build Coastguard Worker { 122*cc02d7e2SAndroid Build Coastguard Worker if (buffer != IntPtr.Zero) 123*cc02d7e2SAndroid Build Coastguard Worker { 124*cc02d7e2SAndroid Build Coastguard Worker Marshal.FreeHGlobal(buffer); 125*cc02d7e2SAndroid Build Coastguard Worker } 126*cc02d7e2SAndroid Build Coastguard Worker } 127*cc02d7e2SAndroid Build Coastguard Worker } 128*cc02d7e2SAndroid Build Coastguard Worker } 129*cc02d7e2SAndroid Build Coastguard Worker } 130