PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/Common/Tests/Utilities/VCCompiler.cs

https://gitlab.com/SplatoonModdingHub/PTVS
C# | 275 lines | 238 code | 20 blank | 17 comment | 23 complexity | fec4ba2f6b1ed4e21138fa0c65a7db0d MD5 | raw file
  1. // Visual Studio Shared Project
  2. // Copyright(c) Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the License); you may not use
  6. // this file except in compliance with the License. You may obtain a copy of the
  7. // License at http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
  10. // OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
  11. // IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  12. // MERCHANTABLITY OR NON-INFRINGEMENT.
  13. //
  14. // See the Apache Version 2.0 License for specific language governing
  15. // permissions and limitations under the License.
  16. using System;
  17. using System.IO;
  18. using System.Linq;
  19. using System.Reflection;
  20. using Microsoft.Win32;
  21. namespace TestUtilities {
  22. public class VCCompiler {
  23. public readonly string BinPath;
  24. public readonly string BinPaths;
  25. public readonly string LibPaths;
  26. public readonly string IncludePaths;
  27. public static VCCompiler VC9_X86 { get { return FindVC("9.0", ProcessorArchitecture.X86); } }
  28. public static VCCompiler VC10_X86 { get { return FindVC("10.0", ProcessorArchitecture.X86); } }
  29. public static VCCompiler VC11_X86 { get { return FindVC("11.0", ProcessorArchitecture.X86); } }
  30. public static VCCompiler VC12_X86 { get { return FindVC("12.0", ProcessorArchitecture.X86); } }
  31. public static VCCompiler VC14_X86 { get { return FindVC("14.0", ProcessorArchitecture.X86); } }
  32. public static VCCompiler VC9_X64 { get { return FindVC("9.0", ProcessorArchitecture.Amd64); } }
  33. public static VCCompiler VC10_X64 { get { return FindVC("10.0", ProcessorArchitecture.Amd64); } }
  34. public static VCCompiler VC11_X64 { get { return FindVC("11.0", ProcessorArchitecture.Amd64); } }
  35. public static VCCompiler VC12_X64 { get { return FindVC("12.0", ProcessorArchitecture.Amd64); } }
  36. public static VCCompiler VC14_X64 { get { return FindVC("14.0", ProcessorArchitecture.Amd64); } }
  37. private VCCompiler(string bin, string bins, string include, string lib) {
  38. BinPath = bin ?? string.Empty;
  39. BinPaths = bins ?? BinPath;
  40. LibPaths = lib ?? string.Empty;
  41. IncludePaths = include ?? string.Empty;
  42. }
  43. private static VCCompiler FindVC(string version, ProcessorArchitecture arch) {
  44. string vcDir = null, vsDir = null;
  45. using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
  46. using (var key1 = baseKey.OpenSubKey("SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"))
  47. using (var key2 = baseKey.OpenSubKey("SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7")) {
  48. if (key1 != null) {
  49. vcDir = key1.GetValue(version) as string;
  50. }
  51. if (key2 != null) {
  52. vsDir = key2.GetValue(version) as string;
  53. }
  54. }
  55. if (string.IsNullOrEmpty(vcDir)) {
  56. using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32))
  57. using (var key = baseKey.OpenSubKey("SOFTWARE\\Microsoft\\DevDiv\\VCForPython\\" + version)) {
  58. if (key != null) {
  59. vcDir = key.GetValue("InstallDir") as string;
  60. }
  61. }
  62. }
  63. if (string.IsNullOrEmpty(vcDir)) {
  64. using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
  65. using (var key = baseKey.OpenSubKey("SOFTWARE\\Microsoft\\DevDiv\\VCForPython\\" + version)) {
  66. if (key != null) {
  67. vcDir = key.GetValue("InstallDir") as string;
  68. }
  69. }
  70. }
  71. if (string.IsNullOrEmpty(vcDir)) {
  72. return null;
  73. }
  74. string bin = Path.Combine(vcDir, "bin"), bins = bin;
  75. if (arch == ProcessorArchitecture.Amd64) {
  76. bin = Path.Combine(bin, "x86_amd64");
  77. bins = bin + ";" + bins;
  78. }
  79. if (!string.IsNullOrEmpty(vsDir)) {
  80. bins += ";" + vsDir + ";" + vsDir + @"\Common7\IDE";
  81. }
  82. string include = Path.Combine(vcDir, "include");
  83. string lib = Path.Combine(vcDir, "lib");
  84. if (arch == ProcessorArchitecture.Amd64) {
  85. lib = Path.Combine(lib, "amd64");
  86. }
  87. AddWindowsSdk(version, arch, ref include, ref lib);
  88. return new VCCompiler(bin, bins, include, lib);
  89. }
  90. private static void AddWindowsSdk(
  91. string vcVersion,
  92. ProcessorArchitecture arch,
  93. ref string includePaths,
  94. ref string libPaths
  95. ) {
  96. var isX64 = (arch == ProcessorArchitecture.Amd64);
  97. if (vcVersion == "14.0") {
  98. // Windows 10 kit is required for this version
  99. AddWindows10KitPaths(isX64, ref includePaths, ref libPaths);
  100. return;
  101. }
  102. if (vcVersion == "11.0" || vcVersion == "12.0") {
  103. // If we find a Windows 8 kit, then return
  104. if (AddWindows8KitPaths(isX64, ref includePaths, ref libPaths)) {
  105. return;
  106. }
  107. }
  108. AddWindowsSdkPaths(isX64, ref includePaths, ref libPaths);
  109. }
  110. private static void AppendPath(ref string paths, string path) {
  111. if (string.IsNullOrEmpty(paths)) {
  112. paths = path;
  113. } else {
  114. paths += ";" + path;
  115. }
  116. }
  117. private static bool AddWindowsSdkPaths(
  118. bool isX64,
  119. ref string includePaths,
  120. ref string libPaths
  121. ) {
  122. foreach(var version in new[] { "v8.0A", "v7.0A", "v7.0" }) {
  123. var regValue = Registry.GetValue(
  124. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\" + version,
  125. "InstallationFolder",
  126. null
  127. );
  128. string[] locations = new[] {
  129. regValue != null ? regValue.ToString() : null,
  130. Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Microsoft SDKs", "Windows", version),
  131. Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Microsoft SDKs", "Windows", version)
  132. };
  133. foreach(var rootPath in locations) {
  134. if (!Directory.Exists(rootPath)) {
  135. continue;
  136. }
  137. var include = Path.Combine(rootPath, "Include");
  138. var lib = Path.Combine(rootPath, "Lib");
  139. if (isX64) {
  140. lib = Path.Combine(lib, "x64");
  141. }
  142. if (Directory.Exists(include) && Directory.Exists(lib)) {
  143. AppendPath(ref includePaths, include);
  144. AppendPath(ref libPaths, lib);
  145. return true;
  146. }
  147. }}
  148. return false;
  149. }
  150. private static bool AddWindows8KitPaths(
  151. bool isX64,
  152. ref string includePaths,
  153. ref string libPaths
  154. ) {
  155. foreach (var version in new[] { "KitsRoot81", "KitsRoot" }) {
  156. var regValue = Registry.GetValue(
  157. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots",
  158. version,
  159. null
  160. );
  161. if (regValue == null) {
  162. continue;
  163. }
  164. var rootPath = regValue.ToString();
  165. var includeShared = Path.Combine(rootPath, "Include", "shared");
  166. var includeum = Path.Combine(rootPath, "Include", "um");
  167. var lib8 = Path.Combine(rootPath, "Lib", "win8", "um", isX64 ? "x64" : "x86");
  168. var libv63 = Path.Combine(rootPath, "Lib", "winv6.3", "um", isX64 ? "x64" : "x86");
  169. if (!Directory.Exists(includeShared) || !Directory.Exists(includeum)) {
  170. continue;
  171. }
  172. if (Directory.Exists(lib8)) {
  173. AppendPath(ref libPaths, lib8);
  174. } else if (Directory.Exists(libv63)) {
  175. AppendPath(ref libPaths, libv63);
  176. } else {
  177. continue;
  178. }
  179. AppendPath(ref includePaths, includeShared);
  180. AppendPath(ref includePaths, includeum);
  181. return true;
  182. }
  183. return false;
  184. }
  185. private static bool AddWindows10KitPaths(
  186. bool isX64,
  187. ref string includePaths,
  188. ref string libPaths
  189. ) {
  190. string include8 = null;
  191. string lib8 = null;
  192. if (!AddWindows8KitPaths(isX64, ref include8, ref lib8)) {
  193. return false;
  194. }
  195. foreach (var version in new[] { "KitsRoot10" }) {
  196. var regValue = Registry.GetValue(
  197. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots",
  198. version,
  199. null
  200. );
  201. if (regValue == null) {
  202. continue;
  203. }
  204. var rootPath = regValue.ToString();
  205. var include = Path.Combine(rootPath, "Include");
  206. if (!Directory.Exists(include)) {
  207. continue;
  208. }
  209. // We want a subfolder that is a version number - get the latest
  210. var crtVersion = new DirectoryInfo(include).EnumerateDirectories()
  211. .Select(d => d.Name)
  212. .OrderByDescending(s => s)
  213. .FirstOrDefault();
  214. if (string.IsNullOrEmpty(crtVersion)) {
  215. continue;
  216. }
  217. include = Path.Combine(include, crtVersion, "ucrt");
  218. var lib = Path.Combine(rootPath, "Lib", crtVersion, "ucrt", isX64 ? "x64" : "x86");
  219. if (!Directory.Exists(include) || !Directory.Exists(lib)) {
  220. continue;
  221. }
  222. AppendPath(ref includePaths, include);
  223. AppendPath(ref includePaths, include8);
  224. AppendPath(ref libPaths, lib);
  225. AppendPath(ref libPaths, lib8);
  226. return true;
  227. }
  228. return false;
  229. }
  230. }
  231. }