xref: /aosp_15_r20/external/grpc-grpc/src/csharp/Grpc.Tools/CommonPlatformDetection.cs (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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