1 #region Copyright notice and license 2 3 // Copyright 2018 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #endregion 18 19 using System; 20 using System.IO; 21 using System.Runtime.CompilerServices; 22 using System.Runtime.InteropServices; 23 using System.Security; 24 25 namespace Grpc.Tools 26 { 27 // Metadata names (MSBuild item attributes) that we refer to often. 28 static class Metadata 29 { 30 // On output dependency lists. 31 public static string Source = "Source"; 32 // On Protobuf items. 33 public static string ProtoRoot = "ProtoRoot"; 34 public static string OutputDir = "OutputDir"; 35 public static string GrpcServices = "GrpcServices"; 36 public static string GrpcOutputDir = "GrpcOutputDir"; 37 }; 38 39 // A few flags used to control the behavior under various platforms. 40 internal static class Platform 41 { 42 public enum OsKind { Unknown, Windows, Linux, MacOsX }; 43 public static readonly OsKind Os; 44 45 public enum CpuKind { Unknown, X86, X64 }; 46 public static readonly CpuKind Cpu; 47 48 // This is not necessarily true, but good enough. BCL lacks a per-FS 49 // API to determine file case sensitivity. 50 public static bool IsFsCaseInsensitive => Os == OsKind.Windows; 51 public static bool IsWindows => Os == OsKind.Windows; 52 Platform()53 static Platform() 54 { 55 #if NETCORE 56 Os = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? OsKind.Windows 57 : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? OsKind.Linux 58 : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? OsKind.MacOsX 59 : OsKind.Unknown; 60 61 switch (RuntimeInformation.ProcessArchitecture) 62 { 63 case Architecture.X86: Cpu = CpuKind.X86; break; 64 case Architecture.X64: Cpu = CpuKind.X64; break; 65 // We do not have build tools for other architectures. 66 default: Cpu = CpuKind.Unknown; break; 67 } 68 #else 69 // Using the same best-effort detection logic as Grpc.Core/PlatformApis.cs 70 var platform = Environment.OSVersion.Platform; 71 if (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows) 72 { 73 Os = OsKind.Windows; 74 } 75 else if (platform == PlatformID.Unix && GetUname() == "Darwin") 76 { 77 Os = OsKind.MacOsX; 78 } 79 else 80 { 81 Os = OsKind.Linux; 82 } 83 84 // Hope we are not building on ARM under Xamarin! 85 Cpu = Environment.Is64BitProcess ? CpuKind.X64 : CpuKind.X86; 86 #endif 87 } 88 89 [DllImport("libc")] uname(IntPtr buf)90 static extern int uname(IntPtr buf); 91 92 // This code is copied from Grpc.Core/PlatformApis.cs GetUname()93 static string GetUname() 94 { 95 var buffer = Marshal.AllocHGlobal(8192); 96 try 97 { 98 if (uname(buffer) == 0) 99 { 100 return Marshal.PtrToStringAnsi(buffer); 101 } 102 return string.Empty; 103 } 104 catch 105 { 106 return string.Empty; 107 } 108 finally 109 { 110 if (buffer != IntPtr.Zero) 111 { 112 Marshal.FreeHGlobal(buffer); 113 } 114 } 115 } 116 }; 117 118 // Exception handling helpers. 119 static class Exceptions 120 { 121 // Returns true iff the exception indicates an error from an I/O call. See 122 // https://github.com/Microsoft/msbuild/blob/v15.4.8.50001/src/Shared/ExceptionHandling.cs#L101 123 static public bool IsIoRelated(Exception ex) => 124 ex is IOException || 125 (ex is ArgumentException && !(ex is ArgumentNullException)) || 126 ex is SecurityException || 127 ex is UnauthorizedAccessException || 128 ex is NotSupportedException; 129 }; 130 131 // String helpers. 132 static class Strings 133 { 134 // Compare string to argument using OrdinalIgnoreCase comparison. EqualNoCase(this string a, string b)135 public static bool EqualNoCase(this string a, string b) => 136 string.Equals(a, b, StringComparison.OrdinalIgnoreCase); 137 } 138 } 139