2 using Microsoft.Build.Framework;
4 using System.Reflection;
6 using System.Collections.Generic;
8 using Mono.XBuild.Utilities;
12 namespace Microsoft.Build.Tasks
14 public class GetReferenceAssemblyPaths : TaskExtension
16 static string framework_base_path;
17 static string PathSeparatorAsString = Path.PathSeparator.ToString ();
18 const string MacOSXExternalXBuildDir = "/Library/Frameworks/Mono.framework/External/xbuild-frameworks";
20 public GetReferenceAssemblyPaths ()
24 public override bool Execute ()
26 FrameworkMoniker moniker = null;
27 if (!TryParseTargetFrameworkMoniker (TargetFrameworkMoniker, out moniker))
30 var framework = GetFrameworkDirectoriesForMoniker (moniker);
31 if (framework == null) {
32 Log.LogWarning ("Unable to find framework corresponding to the target framework moniker '{0}'. " +
33 "Framework assembly references will be resolved from the GAC, which might not be " +
34 "the intended behavior.", TargetFrameworkMoniker);
38 ReferenceAssemblyPaths = FullFrameworkReferenceAssemblyPaths = framework.Directories;
39 TargetFrameworkMonikerDisplayName = framework.DisplayName;
44 Framework GetFrameworkDirectoriesForMoniker (FrameworkMoniker moniker)
46 string dirs = String.Join (PathSeparatorAsString, new string [] {
47 Environment.GetEnvironmentVariable ("XBUILD_FRAMEWORK_FOLDERS_PATH") ?? String.Empty,
48 MSBuildUtils.RunningOnMac ? MacOSXExternalXBuildDir : String.Empty,
50 DefaultFrameworksBasePath });
52 string [] paths = dirs.Split (new char [] {Path.PathSeparator}, StringSplitOptions.RemoveEmptyEntries);
53 foreach (string path in paths) {
54 var framework = GetFrameworkDirectoriesForMoniker (moniker, path);
55 if (framework != null)
62 //@base_path must be absolute
63 Framework GetFrameworkDirectoriesForMoniker (FrameworkMoniker moniker, string base_path)
65 if (String.IsNullOrEmpty (base_path)) {
66 Log.LogMessage (MessageImportance.Low, "Invalid *empty* base path, ignoring. " + Environment.StackTrace);
70 Log.LogMessage (MessageImportance.Low, "Looking for framework '{0}' in root path '{1}'",
72 string framework_path = Path.Combine (base_path, Path.Combine (moniker.Identifier, moniker.Version));
73 if (!String.IsNullOrEmpty (moniker.Profile))
74 framework_path = Path.Combine (framework_path, moniker.Profile);
76 string redistlist_dir = Path.Combine (framework_path, "RedistList");
77 string framework_list = Path.Combine (redistlist_dir, "FrameworkList.xml");
78 if (!File.Exists (framework_list)) {
79 Log.LogMessage (MessageImportance.Low,
80 "Unable to find framework definition file '{0}' for Target Framework Moniker '{1}'",
81 framework_list, moniker);
85 Log.LogMessage (MessageImportance.Low, "Found framework definition list '{0}' for framework '{1}'",
86 framework_list, moniker);
87 XmlReader xr = XmlReader.Create (framework_list);
90 if (xr.LocalName != "FileList") {
91 Log.LogMessage (MessageImportance.Low, "Invalid frameworklist '{0}', expected a 'FileList' root element.",
96 var framework = new Framework ();
97 framework.DisplayName = xr.GetAttribute ("Name");
98 string framework_dir = xr.GetAttribute ("TargetFrameworkDirectory");
99 if (String.IsNullOrEmpty (framework_dir))
100 framework_dir = Path.Combine (redistlist_dir, "..");
102 framework_dir = Path.Combine (redistlist_dir, framework_dir);
104 var directories = new List<string> ();
105 directories.Add (MSBuildUtils.FromMSBuildPath (framework_dir));
107 string include = xr.GetAttribute ("IncludeFramework");
108 if (!String.IsNullOrEmpty (include)) {
109 var included_framework = GetFrameworkDirectoriesForMoniker (new FrameworkMoniker (moniker.Identifier, include, null));
111 if (included_framework != null && included_framework.Directories != null)
112 directories.AddRange (included_framework.Directories);
115 framework.Directories = directories.ToArray ();
118 } catch (XmlException xe) {
119 Log.LogWarning ("Error reading framework definition file '{0}': {1}", framework_list, xe.Message);
120 Log.LogMessage (MessageImportance.Low, "Error reading framework definition file '{0}': {1}", framework_list,
125 ((IDisposable)xr).Dispose ();
129 bool TryParseTargetFrameworkMoniker (string moniker_literal, out FrameworkMoniker moniker)
132 if (String.IsNullOrEmpty (moniker_literal))
133 throw new ArgumentException ("Empty moniker string");
135 string [] parts = moniker_literal.Split (new char [] {','}, StringSplitOptions.RemoveEmptyEntries);
137 if (parts.Length < 2 || parts.Length > 3) {
138 LogInvalidMonikerError (null, moniker_literal);
142 string identifier = parts [0];
143 string version = null;
144 string profile = null;
146 if (!parts [1].StartsWith ("Version=")) {
147 LogInvalidMonikerError ("Invalid framework name", moniker_literal);
151 version = parts [1].Substring (8);
152 if (String.IsNullOrEmpty (version)) {
153 LogInvalidMonikerError ("Invalid framework version", moniker_literal);
157 if (parts.Length > 2) {
158 if (!parts [2].StartsWith ("Profile=")) {
159 LogInvalidMonikerError ("Invalid framework version", moniker_literal);
163 profile = parts [2].Substring (8);
164 if (String.IsNullOrEmpty (profile)) {
165 LogInvalidMonikerError ("Invalid framework profile", moniker_literal);
170 moniker = new FrameworkMoniker (identifier, version, profile);
174 void LogInvalidMonikerError (string msg, string moniker_literal)
177 Log.LogError ("{0} in the Target Framework Moniker '{1}'. Expected format: 'Identifier,Version=<version>[,Profile=<profile>]'. " +
178 "It should have either 2 or 3 comma separated components.", msg, moniker_literal);
180 Log.LogError ("Invalid Target Framework Moniker '{0}'. Expected format: 'Identifier,Version=<version>[,Profile=<profile>]'. " +
181 "It should have either 2 or 3 comma separated components.", moniker_literal);
185 public string TargetFrameworkMoniker { get; set; }
187 public string RootPath { get; set; }
189 public bool BypassFrameworkInstallChecks { get; set; }
192 public string TargetFrameworkMonikerDisplayName { get; set; }
195 public string[] ReferenceAssemblyPaths { get; set; }
198 public string[] FullFrameworkReferenceAssemblyPaths { get; set; }
200 static string DefaultFrameworksBasePath {
202 if (framework_base_path == null) {
203 // NOTE: code from mcs/tools/gacutil/driver.cs
204 PropertyInfo gac = typeof (System.Environment).GetProperty (
205 "GacPath", BindingFlags.Static | BindingFlags.NonPublic);
208 MethodInfo get_gac = gac.GetGetMethod (true);
209 string gac_path = (string) get_gac.Invoke (null, null);
210 framework_base_path = Path.GetFullPath (Path.Combine (
211 gac_path, Path.Combine ("..", "xbuild-frameworks")));
214 return framework_base_path;
219 class FrameworkMoniker {
220 public readonly string Identifier;
221 public readonly string Version;
222 public readonly string Profile;
224 public FrameworkMoniker (string identifier, string version, string profile)
226 this.Identifier = identifier;
227 this.Version = version;
228 this.Profile = profile;
231 public override string ToString ()
233 if (String.IsNullOrEmpty (Profile))
234 return String.Format ("{0},Version={1}", Identifier, Version);
235 return String.Format ("{0},Version={1},Profile={2}", Identifier, Version, Profile);
240 public string Moniker;
241 public string[] Directories;
242 public string DisplayName;