1 //
2 // ToolLocationHelper.cs:
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //
7 // (C) 2005 Marek Sieradzki
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 
28 using System;
29 using System.IO;
30 using System.Xml;
31 using System.Linq;
32 
33 namespace Microsoft.Build.Utilities
34 {
35 	#if MICROSOFT_BUILD_DLL
36 	internal
37 	#else
38 	public
39 	#endif
40 	static class ToolLocationHelper
41 	{
42 		static string lib_mono_dir;
43 		static string [] mono_dir;
44 		static bool runningOnDotNet;
45 
ToolLocationHelper()46 		static ToolLocationHelper ()
47 		{
48 			string assemblyLocation;
49 			DirectoryInfo t1, t2;
50 
51 			// /usr/local/lib/mono/1.0
52 			assemblyLocation = Path.GetDirectoryName (typeof (object).Assembly.Location);
53 			t1 = new DirectoryInfo (assemblyLocation);
54 
55 			// usr/local/lib/mono
56 			t2 = t1.Parent;
57 
58 			lib_mono_dir = t2.FullName;
59 
60 			var windowsPath = Environment.GetFolderPath (Environment.SpecialFolder.Windows);
61 			runningOnDotNet = !string.IsNullOrEmpty (windowsPath) && lib_mono_dir.StartsWith (windowsPath);
62 
63 			if (Environment.GetEnvironmentVariable ("TESTING_MONO") != null) {
64 				mono_dir = new string [] {                   // TargetDotNetFrameworkVersion:
65 					Path.Combine (lib_mono_dir, "net_1_0"),  // Version11
66 					Path.Combine (lib_mono_dir, "net_2_0"),  // Version20
67 					Path.Combine (lib_mono_dir, "net_2_0"),  // Version30
68 					Path.Combine (lib_mono_dir, "net_3_5"),  // Version35
69 					// mono's 4.0 is not an actual framework directory with all tools etc
70 					// it's simply reference assemblies. So like .NET we consider 4.5 to
71 					// be a complete replacement for 4.0.
72 					Path.Combine (lib_mono_dir, "net_4_x"),  // Version40
73 					Path.Combine (lib_mono_dir, "net_4_x"),  // Version45
74 					Path.Combine (lib_mono_dir, "net_4_x"),  // Version451
75 					Path.Combine (lib_mono_dir, "net_4_x"),  // Version46
76 					Path.Combine (lib_mono_dir, "net_4_x"),  // Version461
77 					Path.Combine (lib_mono_dir, "net_4_x"),  // Version462
78 				};
79 			} else if (runningOnDotNet) {
80 				mono_dir = new string [] {
81 					Path.Combine (lib_mono_dir, "v1.0.3705"),   // Version11
82 					Path.Combine (lib_mono_dir, "v2.0.50727"),  // Version20
83 					Path.Combine (lib_mono_dir, "v2.0.50727"),  // Version30
84 					Path.Combine (lib_mono_dir, "v3.5"),        // Version35
85 					Path.Combine (lib_mono_dir, "v4.0.30319"),  // Version40
86 					Path.Combine (lib_mono_dir, "v4.0.30319"),  // Version45
87 					Path.Combine (lib_mono_dir, "v4.0.30319"),  // Version451
88 					Path.Combine (lib_mono_dir, "v4.0.30319"),  // Version46
89 					Path.Combine (lib_mono_dir, "v4.0.30319"),  // Version461
90 					Path.Combine (lib_mono_dir, "v4.0.30319"),  // Version462
91 				};
92 			} else {
93 				mono_dir = new string [] {
94 					Path.Combine (lib_mono_dir, "1.0"),  // Version11
95 					Path.Combine (lib_mono_dir, "2.0"),  // Version20
96 					Path.Combine (lib_mono_dir, "2.0"),  // Version30
97 					Path.Combine (lib_mono_dir, "3.5"),  // Version35
98 					// see comment above regarding 4.0/4.5
99 					Path.Combine (lib_mono_dir, "4.5"),  // Version40
100 					Path.Combine (lib_mono_dir, "4.5"),  // Version45
101 					Path.Combine (lib_mono_dir, "4.5"),  // Version451
102 					Path.Combine (lib_mono_dir, "4.5"),  // Version46
103 					Path.Combine (lib_mono_dir, "4.5"),  // Version461
104 					Path.Combine (lib_mono_dir, "4.5"),  // Version462
105 				};
106 			}
107 
108 		}
109 
110 		[MonoTODO]
GetDotNetFrameworkRootRegistryKey(TargetDotNetFrameworkVersion version)111 		public static string GetDotNetFrameworkRootRegistryKey (TargetDotNetFrameworkVersion version)
112 		{
113 			throw new NotImplementedException ();
114 		}
115 
116 		[MonoTODO]
GetDotNetFrameworkSdkInstallKeyValue(TargetDotNetFrameworkVersion version)117 		public static string GetDotNetFrameworkSdkInstallKeyValue (TargetDotNetFrameworkVersion version)
118 		{
119 			throw new NotImplementedException ();
120 		}
121 
122 		[MonoTODO]
GetDotNetFrameworkVersionFolderPrefix(TargetDotNetFrameworkVersion version)123 		public static string GetDotNetFrameworkVersionFolderPrefix (TargetDotNetFrameworkVersion version)
124 		{
125 			throw new NotImplementedException ();
126 		}
127 
GetPathToDotNetFramework(TargetDotNetFrameworkVersion version)128 		public static string GetPathToDotNetFramework (TargetDotNetFrameworkVersion version)
129 		{
130 			return mono_dir [(int)version];
131 		}
132 
GetPathToDotNetFrameworkFile(string fileName, TargetDotNetFrameworkVersion version)133 		public static string GetPathToDotNetFrameworkFile (string fileName,
134 								  TargetDotNetFrameworkVersion version)
135 		{
136 			string dir = GetPathToDotNetFramework (version);
137 			string file = Path.Combine (dir, fileName);
138 			if (File.Exists (file))
139 				return file;
140 
141 			//Mono doesn't ship multiple versions of tools that are backwards/forwards compatible
142 			if (!runningOnDotNet) {
143 				//most of the 3.5 tools are in the 2.0 directory
144 				if (version == TargetDotNetFrameworkVersion.Version35)
145 					return GetPathToDotNetFrameworkFile (fileName, TargetDotNetFrameworkVersion.Version20);
146 				//unversioned tools are in the 4.5 directory
147 				if (version == TargetDotNetFrameworkVersion.Version20)
148 					return GetPathToDotNetFrameworkFile (fileName, (TargetDotNetFrameworkVersion)5);
149 			}
150 
151 			return null;
152 		}
153 
GetPathToDotNetFrameworkBinFile(string fileName)154 		public static string GetPathToDotNetFrameworkBinFile (string fileName)
155 		{
156 			string dir = Path.Combine(Directory.GetParent(Directory.GetParent(lib_mono_dir).FullName).FullName, "bin");
157 			string file = Path.Combine (dir, fileName);
158 			if (File.Exists (file))
159 				return file;
160 
161 			return null;
162 		}
163 
GetPathToDotNetFrameworkSdk(TargetDotNetFrameworkVersion version)164 		public static string GetPathToDotNetFrameworkSdk (TargetDotNetFrameworkVersion version)
165 		{
166 			return GetPathToDotNetFramework (version);
167 		}
168 
169 		[MonoTODO]
GetPathToDotNetFrameworkSdkFile(string fileName, TargetDotNetFrameworkVersion version)170 		public static string GetPathToDotNetFrameworkSdkFile (string fileName,
171 								      TargetDotNetFrameworkVersion version)
172 		{
173 			throw new NotImplementedException ();
174 		}
175 
GetPathToStandardLibraries(string targetFrameworkIdentifier, string targetFrameworkVersion, string targetFrameworkProfile)176 		public static string GetPathToStandardLibraries (string targetFrameworkIdentifier,
177 								 string targetFrameworkVersion,
178 								 string targetFrameworkProfile)
179 		{
180 			return GetPathToStandardLibraries (targetFrameworkIdentifier, targetFrameworkVersion, targetFrameworkProfile, null);
181 		}
182 
183 		[MonoTODO]
184 		#if XBUILD_12
185 		public
186 		#endif
GetPathToStandardLibraries(string targetFrameworkIdentifier, string targetFrameworkVersion, string targetFrameworkProfile, string platformTarget)187 		static string GetPathToStandardLibraries (string targetFrameworkIdentifier,
188 		                                          string targetFrameworkVersion,
189 		                                          string targetFrameworkProfile,
190 		                                          string platformTarget)
191 		{
192 			// FIXME: support platformTarget
193 			if (platformTarget != null)
194 				throw new NotImplementedException ("platformTarget support is not implemented");
195 
196 			var ext = Environment.GetEnvironmentVariable ("XBUILD_FRAMEWORK_FOLDERS_PATH");
197 			var ret = ext != null ? GetPathToStandardLibrariesWith (ext, targetFrameworkIdentifier, targetFrameworkVersion, targetFrameworkProfile) : null;
198 			return ret ?? GetPathToStandardLibrariesWith (Path.GetFullPath (Path.Combine (lib_mono_dir, "xbuild-frameworks")), targetFrameworkIdentifier, targetFrameworkVersion, targetFrameworkProfile);
199 		}
200 
GetPathToStandardLibrariesWith(string xbuildFxDir, string targetFrameworkIdentifier, string targetFrameworkVersion, string targetFrameworkProfile)201 		static string GetPathToStandardLibrariesWith (string xbuildFxDir,
202 							      string targetFrameworkIdentifier,
203 		                                              string targetFrameworkVersion,
204 		                                              string targetFrameworkProfile)
205 		{
206 			var path = Path.Combine (xbuildFxDir, targetFrameworkIdentifier);
207 			if (!string.IsNullOrEmpty (targetFrameworkVersion)) {
208 				path = Path.Combine (path, targetFrameworkVersion);
209 				if (!string.IsNullOrEmpty (targetFrameworkProfile))
210 					path = Path.Combine (path, "Profile", targetFrameworkProfile);
211 			}
212 			if (!Directory.Exists (path))
213 				return null;
214 			var flist = Path.Combine (path, "RedistList", "FrameworkList.xml");
215 			if (!File.Exists (flist))
216 				return null;
217 			var xml = XmlReader.Create (flist);
218 			xml.MoveToContent ();
219 			var targetFxDir = xml.GetAttribute ("TargetFrameworkDirectory");
220 			targetFxDir = targetFxDir != null ? Path.GetFullPath (Path.Combine (path, "dummy", targetFxDir.Replace ('\\', Path.DirectorySeparatorChar))) : null;
221 			if (Directory.Exists (targetFxDir))
222 				return targetFxDir;
223 			// I'm not sure if this is completely valid assumption...
224 			return path;
225 		}
226 
227 		[MonoTODO]
GetPathToSystemFile(string fileName)228 		public static string GetPathToSystemFile (string fileName)
229 		{
230 			throw new NotImplementedException ();
231 		}
232 
233 		[MonoTODO]
234 		public static string PathToSystem {
235 			get {
236 				throw new NotImplementedException ();
237 			}
238 		}
239 
240 #if XBUILD_12
241 		public static string CurrentToolsVersion {
242 			get {
243 				return XBuildConsts.Version;
244 			}
245 		}
246 
GetPathToBuildTools(string toolsVersion)247 		public static string GetPathToBuildTools (string toolsVersion)
248 		{
249 			string path;
250 			switch (toolsVersion) {
251 			case "12.0":
252 				path = "xbuild_12";
253 				break;
254 			case "14.0":
255 				path = "xbuild_14";
256 				break;
257 			default:
258 				return null;
259 			}
260 
261 			if (Environment.GetEnvironmentVariable ("TESTING_MONO") != null)
262 				return Path.Combine (lib_mono_dir, path);
263 
264 			if (runningOnDotNet) {
265 				//see http://msdn.microsoft.com/en-us/library/vstudio/bb397428(v=vs.120).aspx
266 				var programFiles = Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86);
267 				return Path.Combine (programFiles, "MSBuild", toolsVersion, "bin");
268 			}
269 
270 			return Path.Combine (lib_mono_dir, "xbuild", toolsVersion, "bin");
271 		}
272 #endif
273 	}
274 }
275