2 // Project.cs: Project class
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
6 // Ankit Jain (jankit@novell.com)
8 // (C) 2005 Marek Sieradzki
9 // Copyright 2011 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Collections.Specialized;
36 using System.Reflection;
39 using System.Xml.Schema;
40 using Microsoft.Build.Framework;
41 using Mono.XBuild.Framework;
42 using Mono.XBuild.CommandLine;
44 namespace Microsoft.Build.BuildEngine {
45 public class Project {
48 Dictionary <string, List <string>> conditionedProperties;
49 string[] defaultTargets;
51 BuildItemGroup evaluatedItems;
52 BuildItemGroup evaluatedItemsIgnoringCondition;
53 Dictionary <string, BuildItemGroup> evaluatedItemsByName;
54 Dictionary <string, BuildItemGroup> evaluatedItemsByNameIgnoringCondition;
55 BuildPropertyGroup evaluatedProperties;
56 string firstTargetName;
58 BuildPropertyGroup globalProperties;
59 GroupingCollection groupingCollection;
62 BuildItemGroupCollection itemGroups;
63 ImportCollection imports;
64 List<string> initialTargets;
65 Dictionary <string, BuildItemGroup> last_item_group_containing;
66 bool needToReevaluate;
68 BuildPropertyGroupCollection propertyGroups;
70 TaskDatabase taskDatabase;
71 TargetCollection targets;
72 DateTime timeOfLastDirty;
73 UsingTaskCollection usingTasks;
74 XmlDocument xmlDocument;
76 bool initialTargetsBuilt;
78 BuildSettings current_settings;
81 // This is used to keep track of "current" file,
82 // which is then used to set the reserved properties
83 // $(MSBuildThisFile*)
84 Stack<string> this_file_property_stack;
85 ProjectLoadSettings project_load_settings;
88 static string extensions_path;
89 static XmlNamespaceManager manager;
90 static string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
93 : this (Engine.GlobalEngine)
97 public Project (Engine engine) : this (engine, null)
101 public Project (Engine engine, string toolsVersion)
103 parentEngine = engine;
104 ToolsVersion = toolsVersion;
106 buildEnabled = ParentEngine.BuildEnabled;
107 xmlDocument = new XmlDocument ();
108 xmlDocument.PreserveWhitespace = false;
109 xmlDocument.AppendChild (xmlDocument.CreateElement ("Project", XmlNamespace));
110 xmlDocument.DocumentElement.SetAttribute ("xmlns", ns);
112 fullFileName = String.Empty;
113 timeOfLastDirty = DateTime.Now;
114 current_settings = BuildSettings.None;
115 project_load_settings = ProjectLoadSettings.None;
119 initialTargets = new List<string> ();
120 defaultTargets = new string [0];
121 batches = new Stack<Batch> ();
122 this_file_property_stack = new Stack<string> ();
124 globalProperties = new BuildPropertyGroup (null, this, null, false);
125 foreach (BuildProperty bp in parentEngine.GlobalProperties)
126 GlobalProperties.AddProperty (bp.Clone (true));
132 [MonoTODO ("Not tested")]
133 public void AddNewImport (string importLocation,
134 string importCondition)
136 if (importLocation == null)
137 throw new ArgumentNullException ("importLocation");
139 XmlElement importElement = xmlDocument.CreateElement ("Import", XmlNamespace);
140 xmlDocument.DocumentElement.AppendChild (importElement);
141 importElement.SetAttribute ("Project", importLocation);
142 if (!String.IsNullOrEmpty (importCondition))
143 importElement.SetAttribute ("Condition", importCondition);
145 AddImport (importElement, null, false);
146 MarkProjectAsDirty ();
150 public BuildItem AddNewItem (string itemName,
153 return AddNewItem (itemName, itemInclude, false);
156 [MonoTODO ("Adds item not in the same place as MS")]
157 public BuildItem AddNewItem (string itemName,
159 bool treatItemIncludeAsLiteral)
163 if (itemGroups.Count == 0)
164 big = AddNewItemGroup ();
166 if (last_item_group_containing.ContainsKey (itemName)) {
167 big = last_item_group_containing [itemName];
170 BuildItemGroup [] groups = new BuildItemGroup [itemGroups.Count];
171 itemGroups.CopyTo (groups, 0);
176 BuildItem item = big.AddNewItem (itemName, itemInclude, treatItemIncludeAsLiteral);
178 MarkProjectAsDirty ();
184 [MonoTODO ("Not tested")]
185 public BuildItemGroup AddNewItemGroup ()
187 XmlElement element = xmlDocument.CreateElement ("ItemGroup", XmlNamespace);
188 xmlDocument.DocumentElement.AppendChild (element);
190 BuildItemGroup big = new BuildItemGroup (element, this, null, false);
191 itemGroups.Add (big);
192 MarkProjectAsDirty ();
198 [MonoTODO ("Ignores insertAtEndOfProject")]
199 public BuildPropertyGroup AddNewPropertyGroup (bool insertAtEndOfProject)
201 XmlElement element = xmlDocument.CreateElement ("PropertyGroup", XmlNamespace);
202 xmlDocument.DocumentElement.AppendChild (element);
204 BuildPropertyGroup bpg = new BuildPropertyGroup (element, this, null, false);
205 propertyGroups.Add (bpg);
206 MarkProjectAsDirty ();
212 [MonoTODO ("Not tested, isn't added to TaskDatabase (no reevaluation)")]
213 public void AddNewUsingTaskFromAssemblyFile (string taskName,
216 if (taskName == null)
217 throw new ArgumentNullException ("taskName");
218 if (assemblyFile == null)
219 throw new ArgumentNullException ("assemblyFile");
221 XmlElement element = xmlDocument.CreateElement ("UsingTask", XmlNamespace);
222 xmlDocument.DocumentElement.AppendChild (element);
223 element.SetAttribute ("TaskName", taskName);
224 element.SetAttribute ("AssemblyFile", assemblyFile);
226 UsingTask ut = new UsingTask (element, this, null);
228 MarkProjectAsDirty ();
231 [MonoTODO ("Not tested, isn't added to TaskDatabase (no reevaluation)")]
232 public void AddNewUsingTaskFromAssemblyName (string taskName,
235 if (taskName == null)
236 throw new ArgumentNullException ("taskName");
237 if (assemblyName == null)
238 throw new ArgumentNullException ("assemblyName");
240 XmlElement element = xmlDocument.CreateElement ("UsingTask", XmlNamespace);
241 xmlDocument.DocumentElement.AppendChild (element);
242 element.SetAttribute ("TaskName", taskName);
243 element.SetAttribute ("AssemblyName", assemblyName);
245 UsingTask ut = new UsingTask (element, this, null);
247 MarkProjectAsDirty ();
250 [MonoTODO ("Not tested")]
253 return Build (new string [0]);
256 [MonoTODO ("Not tested")]
257 public bool Build (string targetName)
259 if (targetName == null)
260 return Build ((string[]) null);
262 return Build (new string [1] { targetName });
265 [MonoTODO ("Not tested")]
266 public bool Build (string [] targetNames)
268 return Build (targetNames, null);
271 [MonoTODO ("Not tested")]
272 public bool Build (string [] targetNames,
273 IDictionary targetOutputs)
275 return Build (targetNames, targetOutputs, BuildSettings.None);
278 [MonoTODO ("Not tested")]
279 public bool Build (string [] targetNames,
280 IDictionary targetOutputs,
281 BuildSettings buildFlags)
285 ParentEngine.StartProjectBuild (this, targetNames);
287 // Invoking this to emit a warning in case of unsupported
289 GetToolsVersionToUse (true);
291 string current_directory = Environment.CurrentDirectory;
293 current_settings = buildFlags;
294 if (!String.IsNullOrEmpty (fullFileName))
295 Directory.SetCurrentDirectory (Path.GetDirectoryName (fullFileName));
297 result = BuildInternal (targetNames, targetOutputs, buildFlags);
298 } catch (InvalidProjectFileException ie) {
299 ParentEngine.LogErrorWithFilename (fullFileName, ie.Message);
300 ParentEngine.LogMessage (MessageImportance.Low, String.Format ("{0}: {1}", fullFileName, ie.ToString ()));
301 } catch (Exception e) {
302 ParentEngine.LogErrorWithFilename (fullFileName, e.Message);
303 ParentEngine.LogMessage (MessageImportance.Low, String.Format ("{0}: {1}", fullFileName, e.ToString ()));
306 ParentEngine.EndProjectBuild (this, result);
307 current_settings = BuildSettings.None;
308 Directory.SetCurrentDirectory (current_directory);
315 bool BuildInternal (string [] targetNames,
316 IDictionary targetOutputs,
317 BuildSettings buildFlags)
320 if (buildFlags == BuildSettings.None) {
321 needToReevaluate = false;
326 ProcessBeforeAndAfterTargets ();
329 if (targetNames == null || targetNames.Length == 0) {
330 if (defaultTargets != null && defaultTargets.Length != 0) {
331 targetNames = defaultTargets;
332 } else if (firstTargetName != null) {
333 targetNames = new string [1] { firstTargetName};
335 if (targets == null || targets.Count == 0) {
336 LogError (fullFileName, "No target found in the project");
344 if (!initialTargetsBuilt) {
345 foreach (string target in initialTargets) {
346 if (!BuildTarget (target.Trim (), targetOutputs))
349 initialTargetsBuilt = true;
352 foreach (string target in targetNames) {
354 throw new ArgumentNullException ("Target name cannot be null");
356 if (!BuildTarget (target.Trim (), targetOutputs))
363 bool BuildTarget (string target_name, IDictionary targetOutputs)
365 if (target_name == null)
366 throw new ArgumentException ("targetNames cannot contain null strings");
368 if (!targets.Exists (target_name)) {
369 LogError (fullFileName, "Target named '{0}' not found in the project.", target_name);
373 string key = GetKeyForTarget (target_name);
374 if (!targets [target_name].Build (key))
378 if (ParentEngine.BuiltTargetsOutputByName.TryGetValue (key, out outputs)) {
379 if (targetOutputs != null)
380 targetOutputs.Add (target_name, outputs);
385 internal string GetKeyForTarget (string target_name)
387 return GetKeyForTarget (target_name, true);
390 internal string GetKeyForTarget (string target_name, bool include_global_properties)
392 // target name is case insensitive
393 return fullFileName + ":" + target_name.ToLowerInvariant () +
394 (include_global_properties ? (":" + GlobalPropertiesToString (GlobalProperties))
398 string GlobalPropertiesToString (BuildPropertyGroup bgp)
400 StringBuilder sb = new StringBuilder ();
401 foreach (BuildProperty bp in bgp)
402 sb.AppendFormat (" {0}:{1}", bp.Name, bp.FinalValue);
403 return sb.ToString ();
407 void ProcessBeforeAndAfterTargets ()
409 var beforeTable = Targets.AsIEnumerable ()
410 .SelectMany (target => GetTargetNamesFromString (target.BeforeTargets),
411 (target, before_target) => new {before_target, name = target.Name})
412 .ToLookup (x => x.before_target, x => x.name)
413 .ToDictionary (x => x.Key, x => x.Distinct ().ToList ());
415 foreach (var pair in beforeTable) {
416 if (targets.Exists (pair.Key))
417 targets [pair.Key].BeforeThisTargets = pair.Value;
419 LogWarning (FullFileName, "Target '{0}', not found in the project", pair.Key);
422 var afterTable = Targets.AsIEnumerable ()
423 .SelectMany (target => GetTargetNamesFromString (target.AfterTargets),
424 (target, after_target) => new {after_target, name = target.Name})
425 .ToLookup (x => x.after_target, x => x.name)
426 .ToDictionary (x => x.Key, x => x.Distinct ().ToList ());
428 foreach (var pair in afterTable) {
429 if (targets.Exists (pair.Key))
430 targets [pair.Key].AfterThisTargets = pair.Value;
432 LogWarning (FullFileName, "Target '{0}', not found in the project", pair.Key);
436 string[] GetTargetNamesFromString (string targets)
438 Expression expr = new Expression ();
439 expr.Parse (targets, ParseOptions.AllowItemsNoMetadataAndSplit);
440 return (string []) expr.ConvertTo (this, typeof (string []));
445 public string [] GetConditionedPropertyValues (string propertyName)
447 if (conditionedProperties.ContainsKey (propertyName))
448 return conditionedProperties [propertyName].ToArray ();
450 return new string [0];
453 public BuildItemGroup GetEvaluatedItemsByName (string itemName)
455 if (needToReevaluate) {
456 needToReevaluate = false;
460 if (evaluatedItemsByName.ContainsKey (itemName))
461 return evaluatedItemsByName [itemName];
463 return new BuildItemGroup (this);
466 public BuildItemGroup GetEvaluatedItemsByNameIgnoringCondition (string itemName)
468 if (needToReevaluate) {
469 needToReevaluate = false;
473 if (evaluatedItemsByNameIgnoringCondition.ContainsKey (itemName))
474 return evaluatedItemsByNameIgnoringCondition [itemName];
476 return new BuildItemGroup (this);
479 public string GetEvaluatedProperty (string propertyName)
481 if (needToReevaluate) {
482 needToReevaluate = false;
486 if (propertyName == null)
487 throw new ArgumentNullException ("propertyName");
489 BuildProperty bp = evaluatedProperties [propertyName];
491 return bp == null ? null : (string) bp;
494 [MonoTODO ("We should remember that node and not use XPath to get it")]
495 public string GetProjectExtensions (string id)
497 if (id == null || id == String.Empty)
500 XmlNode node = xmlDocument.SelectSingleNode (String.Format ("/tns:Project/tns:ProjectExtensions/tns:{0}", id), XmlNamespaceManager);
505 return node.InnerXml;
509 public void Load (string projectFileName)
511 Load (projectFileName, ProjectLoadSettings.None);
514 public void Load (string projectFileName, ProjectLoadSettings settings)
516 project_load_settings = settings;
517 if (String.IsNullOrEmpty (projectFileName))
518 throw new ArgumentNullException ("projectFileName");
520 if (!File.Exists (projectFileName))
521 throw new ArgumentException (String.Format ("Project file {0} not found", projectFileName),
524 this.fullFileName = Utilities.FromMSBuildPath (Path.GetFullPath (projectFileName));
525 PushThisFileProperty (fullFileName);
527 string filename = fullFileName;
528 if (String.Compare (Path.GetExtension (fullFileName), ".sln", true) == 0) {
529 Project tmp_project = ParentEngine.CreateNewProject ();
530 tmp_project.FullFileName = filename;
531 SolutionParser sln_parser = new SolutionParser ();
532 sln_parser.ParseSolution (fullFileName, tmp_project, delegate (int errorNumber, string message) {
533 LogWarning (filename, message);
535 filename = fullFileName + ".proj";
537 tmp_project.Save (filename);
538 ParentEngine.RemoveLoadedProject (tmp_project);
539 DoLoad (new StreamReader (filename));
541 if (Environment.GetEnvironmentVariable ("XBUILD_EMIT_SOLUTION") == null)
542 File.Delete (filename);
545 DoLoad (new StreamReader (filename));
549 [MonoTODO ("Not tested")]
550 public void Load (TextReader textReader)
552 Load (textReader, ProjectLoadSettings.None);
555 public void Load (TextReader textReader, ProjectLoadSettings projectLoadSettings)
557 project_load_settings = projectLoadSettings;
558 if (!string.IsNullOrEmpty (fullFileName))
559 PushThisFileProperty (fullFileName);
563 public void LoadXml (string projectXml)
565 LoadXml (projectXml, ProjectLoadSettings.None);
568 public void LoadXml (string projectXml, ProjectLoadSettings projectLoadSettings)
570 project_load_settings = projectLoadSettings;
571 if (!string.IsNullOrEmpty (fullFileName))
572 PushThisFileProperty (fullFileName);
573 DoLoad (new StringReader (projectXml));
574 MarkProjectAsDirty ();
578 public void MarkProjectAsDirty ()
581 timeOfLastDirty = DateTime.Now;
584 [MonoTODO ("Not tested")]
585 public void RemoveAllItemGroups ()
587 int length = ItemGroups.Count;
588 BuildItemGroup [] groups = new BuildItemGroup [length];
589 ItemGroups.CopyTo (groups, 0);
591 for (int i = 0; i < length; i++)
592 RemoveItemGroup (groups [i]);
594 MarkProjectAsDirty ();
598 [MonoTODO ("Not tested")]
599 public void RemoveAllPropertyGroups ()
601 int length = PropertyGroups.Count;
602 BuildPropertyGroup [] groups = new BuildPropertyGroup [length];
603 PropertyGroups.CopyTo (groups, 0);
605 for (int i = 0; i < length; i++)
606 RemovePropertyGroup (groups [i]);
608 MarkProjectAsDirty ();
613 public void RemoveItem (BuildItem itemToRemove)
615 if (itemToRemove == null)
616 throw new ArgumentNullException ("itemToRemove");
618 if (!itemToRemove.FromXml && !itemToRemove.HasParentItem)
619 throw new InvalidOperationException ("The object passed in is not part of the project.");
621 BuildItemGroup big = itemToRemove.ParentItemGroup;
623 if (big.Count == 1) {
624 // ParentItemGroup for items from xml and that have parent is the same
625 groupingCollection.Remove (big);
627 if (big.ParentProject != this)
628 throw new InvalidOperationException ("The object passed in is not part of the project.");
630 if (itemToRemove.FromXml)
631 big.RemoveItem (itemToRemove);
633 big.RemoveItem (itemToRemove.ParentItem);
636 MarkProjectAsDirty ();
640 [MonoTODO ("Not tested")]
641 public void RemoveItemGroup (BuildItemGroup itemGroupToRemove)
643 if (itemGroupToRemove == null)
644 throw new ArgumentNullException ("itemGroupToRemove");
646 groupingCollection.Remove (itemGroupToRemove);
647 MarkProjectAsDirty ();
651 // NOTE: does not modify imported projects
652 public void RemoveItemGroupsWithMatchingCondition (string matchingCondition)
654 throw new NotImplementedException ();
658 public void RemoveItemsByName (string itemName)
660 if (itemName == null)
661 throw new ArgumentNullException ("itemName");
663 throw new NotImplementedException ();
666 [MonoTODO ("Not tested")]
667 public void RemovePropertyGroup (BuildPropertyGroup propertyGroupToRemove)
669 if (propertyGroupToRemove == null)
670 throw new ArgumentNullException ("propertyGroupToRemove");
672 groupingCollection.Remove (propertyGroupToRemove);
673 MarkProjectAsDirty ();
677 // NOTE: does not modify imported projects
678 public void RemovePropertyGroupsWithMatchingCondition (string matchCondition)
680 throw new NotImplementedException ();
684 public void ResetBuildStatus ()
686 // hack to allow built targets to be removed
692 public void Save (string projectFileName)
694 Save (projectFileName, Encoding.Default);
698 [MonoTODO ("Ignores encoding")]
699 public void Save (string projectFileName, Encoding encoding)
701 xmlDocument.Save (projectFileName);
705 public void Save (TextWriter outTextWriter)
707 xmlDocument.Save (outTextWriter);
711 public void SetImportedProperty (string propertyName,
712 string propertyValue,
714 Project importProject)
716 SetImportedProperty (propertyName, propertyValue, condition, importProject,
717 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
720 public void SetImportedProperty (string propertyName,
721 string propertyValue,
723 Project importedProject,
724 PropertyPosition position)
726 SetImportedProperty (propertyName, propertyValue, condition, importedProject,
727 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
731 public void SetImportedProperty (string propertyName,
732 string propertyValue,
734 Project importedProject,
735 PropertyPosition position,
736 bool treatPropertyValueAsLiteral)
738 throw new NotImplementedException ();
741 public void SetProjectExtensions (string id, string xmlText)
744 throw new ArgumentNullException ("id");
746 throw new ArgumentNullException ("xmlText");
748 XmlNode projectExtensions, node;
750 projectExtensions = xmlDocument.SelectSingleNode ("/tns:Project/tns:ProjectExtensions", XmlNamespaceManager);
752 if (projectExtensions == null) {
753 projectExtensions = xmlDocument.CreateElement ("ProjectExtensions", XmlNamespace);
754 xmlDocument.DocumentElement.AppendChild (projectExtensions);
756 node = xmlDocument.CreateElement (id, XmlNamespace);
757 node.InnerXml = xmlText;
758 projectExtensions.AppendChild (node);
760 node = xmlDocument.SelectSingleNode (String.Format ("/tns:Project/tns:ProjectExtensions/tns:{0}", id), XmlNamespaceManager);
763 node = xmlDocument.CreateElement (id, XmlNamespace);
764 projectExtensions.AppendChild (node);
767 node.InnerXml = xmlText;
771 MarkProjectAsDirty ();
774 public void SetProperty (string propertyName,
775 string propertyValue)
777 SetProperty (propertyName, propertyValue, "true",
778 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
781 public void SetProperty (string propertyName,
782 string propertyValue,
785 SetProperty (propertyName, propertyValue, condition,
786 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
789 public void SetProperty (string propertyName,
790 string propertyValue,
792 PropertyPosition position)
794 SetProperty (propertyName, propertyValue, condition,
795 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
799 public void SetProperty (string propertyName,
800 string propertyValue,
802 PropertyPosition position,
803 bool treatPropertyValueAsLiteral)
805 throw new NotImplementedException ();
808 internal void Unload ()
813 internal void CheckUnloaded ()
816 throw new InvalidOperationException ("This project object has been unloaded from the MSBuild engine and is no longer valid.");
819 internal void NeedToReevaluate ()
821 needToReevaluate = true;
824 // Does the actual loading.
825 void DoLoad (TextReader textReader)
828 ParentEngine.RemoveLoadedProject (this);
830 xmlDocument.Load (textReader);
832 if (xmlDocument.DocumentElement.Name == "VisualStudioProject")
833 throw new InvalidProjectFileException (String.Format (
834 "Project file '{0}' is a VS2003 project, which is not " +
835 "supported by xbuild. You need to convert it to msbuild " +
836 "format to build with xbuild.", fullFileName));
838 if (SchemaFile != null) {
839 xmlDocument.Schemas.Add (XmlSchema.Read (
840 new StreamReader (SchemaFile), ValidationCallBack));
841 xmlDocument.Validate (ValidationCallBack);
844 if (xmlDocument.DocumentElement.Name != "Project") {
845 throw new InvalidProjectFileException (String.Format (
846 "The element <{0}> is unrecognized, or not supported in this context.", xmlDocument.DocumentElement.Name));
849 if (xmlDocument.DocumentElement.GetAttribute ("xmlns") != ns) {
850 throw new InvalidProjectFileException (
851 @"The default XML namespace of the project must be the MSBuild XML namespace." +
852 " If the project is authored in the MSBuild 2003 format, please add " +
853 "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" to the <Project> element. " +
854 "If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format. ");
857 ParentEngine.AddLoadedProject (this);
858 } catch (Exception e) {
859 throw new InvalidProjectFileException (String.Format ("{0}: {1}",
860 fullFileName, e.Message), e);
862 if (textReader != null)
874 groupingCollection = new GroupingCollection (this);
875 imports = new ImportCollection (groupingCollection);
876 usingTasks = new UsingTaskCollection (this);
877 itemGroups = new BuildItemGroupCollection (groupingCollection);
878 propertyGroups = new BuildPropertyGroupCollection (groupingCollection);
879 targets = new TargetCollection (this);
880 last_item_group_containing = new Dictionary <string, BuildItemGroup> ();
882 string effective_tools_version = GetToolsVersionToUse (false);
883 taskDatabase = new TaskDatabase ();
884 taskDatabase.CopyTasks (ParentEngine.GetDefaultTasks (effective_tools_version));
886 initialTargets = new List<string> ();
887 defaultTargets = new string [0];
888 PrepareForEvaluate (effective_tools_version);
889 ProcessElements (xmlDocument.DocumentElement, null);
895 void ProcessProjectAttributes (XmlAttributeCollection attributes)
897 foreach (XmlAttribute attr in attributes) {
899 case "InitialTargets":
900 initialTargets.AddRange (attr.Value.Split (
901 new char [] {';', ' '},
902 StringSplitOptions.RemoveEmptyEntries));
904 case "DefaultTargets":
905 // first non-empty DefaultTargets found is used
906 if (defaultTargets == null || defaultTargets.Length == 0)
907 defaultTargets = attr.Value.Split (new char [] {';', ' '},
908 StringSplitOptions.RemoveEmptyEntries);
909 EvaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectDefaultTargets",
910 DefaultTargets, PropertyType.Reserved));
916 internal void ProcessElements (XmlElement rootElement, ImportedProject ip)
918 ProcessProjectAttributes (rootElement.Attributes);
919 foreach (XmlNode xn in rootElement.ChildNodes) {
920 if (xn is XmlElement) {
921 XmlElement xe = (XmlElement) xn;
923 case "ProjectExtensions":
924 AddProjectExtensions (xe);
935 AddUsingTask (xe, ip);
938 AddImport (xe, ip, true);
941 AddImportGroup (xe, ip, true);
944 AddItemGroup (xe, ip);
946 case "PropertyGroup":
947 AddPropertyGroup (xe, ip);
953 throw new InvalidProjectFileException (String.Format ("Invalid element '{0}' in project file '{1}'.", xe.Name, ip.FullFileName));
959 void PrepareForEvaluate (string effective_tools_version)
961 evaluatedItems = new BuildItemGroup (null, this, null, true);
962 evaluatedItemsIgnoringCondition = new BuildItemGroup (null, this, null, true);
963 evaluatedItemsByName = new Dictionary <string, BuildItemGroup> (StringComparer.OrdinalIgnoreCase);
964 evaluatedItemsByNameIgnoringCondition = new Dictionary <string, BuildItemGroup> (StringComparer.OrdinalIgnoreCase);
965 if (building && current_settings == BuildSettings.None)
966 RemoveBuiltTargets ();
968 InitializeProperties (effective_tools_version);
973 groupingCollection.Evaluate ();
975 //FIXME: UsingTasks aren't really evaluated. (shouldn't use expressions or anything)
976 foreach (UsingTask usingTask in UsingTasks)
977 usingTask.Evaluate ();
980 // Removes entries of all earlier built targets for this project
981 void RemoveBuiltTargets ()
983 ParentEngine.ClearBuiltTargetsForProject (this);
986 void InitializeProperties (string effective_tools_version)
990 evaluatedProperties = new BuildPropertyGroup (null, null, null, true);
991 conditionedProperties = new Dictionary<string, List<string>> ();
993 foreach (BuildProperty gp in GlobalProperties) {
994 bp = new BuildProperty (gp.Name, gp.Value, PropertyType.Global);
995 evaluatedProperties.AddProperty (bp);
998 foreach (BuildProperty gp in GlobalProperties)
999 ParentEngine.GlobalProperties.AddProperty (gp);
1001 // add properties that we dont have from parent engine's
1002 // global properties
1003 foreach (BuildProperty gp in ParentEngine.GlobalProperties) {
1004 if (evaluatedProperties [gp.Name] == null) {
1005 bp = new BuildProperty (gp.Name, gp.Value, PropertyType.Global);
1006 evaluatedProperties.AddProperty (bp);
1010 foreach (DictionaryEntry de in Environment.GetEnvironmentVariables ()) {
1011 bp = new BuildProperty ((string) de.Key, (string) de.Value, PropertyType.Environment);
1012 evaluatedProperties.AddProperty (bp);
1015 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectFile", Path.GetFileName (fullFileName),
1016 PropertyType.Reserved));
1017 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectFullPath", fullFileName, PropertyType.Reserved));
1018 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectName",
1019 Path.GetFileNameWithoutExtension (fullFileName),
1020 PropertyType.Reserved));
1021 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectExtension",
1022 Path.GetExtension (fullFileName),
1023 PropertyType.Reserved));
1025 string toolsPath = parentEngine.Toolsets [effective_tools_version].ToolsPath;
1026 if (toolsPath == null)
1027 throw new Exception (String.Format ("Invalid tools version '{0}', no tools path set for this.", effective_tools_version));
1028 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildBinPath", toolsPath, PropertyType.Reserved));
1029 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildToolsPath", toolsPath, PropertyType.Reserved));
1030 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildToolsRoot", Path.GetDirectoryName (toolsPath), PropertyType.Reserved));
1031 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildToolsVersion", effective_tools_version, PropertyType.Reserved));
1032 SetExtensionsPathProperties (DefaultExtensionsPath);
1033 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectDefaultTargets", DefaultTargets, PropertyType.Reserved));
1034 evaluatedProperties.AddProperty (new BuildProperty ("OS", OS, PropertyType.Environment));
1036 // see http://msdn.microsoft.com/en-us/library/vstudio/hh162058(v=vs.120).aspx
1037 if (effective_tools_version == "12.0") {
1038 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildToolsPath32", toolsPath, PropertyType.Reserved));
1039 string frameworkToolsPath = parentEngine.Toolsets [effective_tools_version].FrameworkToolsPath;
1040 if (frameworkToolsPath == null)
1041 throw new Exception (String.Format ("Invalid tools version '{0}', no framework tools path set for this.", effective_tools_version));
1042 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildFrameworkToolsPath", frameworkToolsPath, PropertyType.Reserved));
1043 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildFrameworkToolsPath32", frameworkToolsPath, PropertyType.Reserved));
1046 // FIXME: make some internal method that will work like GetDirectoryName but output String.Empty on null/String.Empty
1048 if (FullFileName == String.Empty)
1049 projectDir = Environment.CurrentDirectory;
1051 projectDir = Path.GetDirectoryName (FullFileName);
1053 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectDirectory", projectDir, PropertyType.Reserved));
1055 if (this_file_property_stack.Count > 0)
1056 // Just re-inited the properties, but according to the stack,
1057 // we should have a MSBuild*This* property set
1058 SetMSBuildThisFileProperties (this_file_property_stack.Peek ());
1061 internal void SetExtensionsPathProperties (string extn_path)
1063 if (!String.IsNullOrEmpty (extn_path)) {
1064 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildExtensionsPath", extn_path, PropertyType.Reserved));
1065 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildExtensionsPath32", extn_path, PropertyType.Reserved));
1066 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildExtensionsPath64", extn_path, PropertyType.Reserved));
1071 // ToolsVersion property
1072 // ToolsVersion attribute on the project
1073 // parentEngine's DefaultToolsVersion
1074 string GetToolsVersionToUse (bool emitWarning)
1076 if (!String.IsNullOrEmpty (ToolsVersion))
1077 return ToolsVersion;
1079 if (!HasToolsVersionAttribute)
1080 return parentEngine.DefaultToolsVersion;
1082 if (parentEngine.Toolsets [DefaultToolsVersion] == null) {
1084 LogWarning (FullFileName, "Project has unknown ToolsVersion '{0}'. Using the default tools version '{1}' instead.",
1085 DefaultToolsVersion, parentEngine.DefaultToolsVersion);
1086 return parentEngine.DefaultToolsVersion;
1089 return DefaultToolsVersion;
1092 void AddProjectExtensions (XmlElement xmlElement)
1096 void AddMessage (XmlElement xmlElement)
1100 void AddTarget (XmlElement xmlElement, ImportedProject importedProject)
1102 Target target = new Target (xmlElement, this, importedProject);
1103 targets.AddTarget (target);
1105 if (firstTargetName == null)
1106 firstTargetName = target.Name;
1109 void AddUsingTask (XmlElement xmlElement, ImportedProject importedProject)
1111 UsingTask usingTask;
1113 usingTask = new UsingTask (xmlElement, this, importedProject);
1114 UsingTasks.Add (usingTask);
1117 void AddImport (XmlElement xmlElement, ImportedProject importingProject, bool evaluate_properties)
1119 // eval all the properties etc till the import
1120 if (evaluate_properties) {
1121 groupingCollection.Evaluate (EvaluationType.Property);
1122 groupingCollection.Evaluate (EvaluationType.Choose);
1125 PushThisFileProperty (importingProject != null ? importingProject.FullFileName : FullFileName);
1127 string project_attribute = xmlElement.GetAttribute ("Project");
1128 if (String.IsNullOrEmpty (project_attribute))
1129 throw new InvalidProjectFileException ("The required attribute \"Project\" is missing from element <Import>.");
1131 Import.ForEachExtensionPathTillFound (xmlElement, this, importingProject,
1132 (importPath, from_source_msg) => AddSingleImport (xmlElement, importPath, importingProject, from_source_msg));
1134 PopThisFileProperty ();
1138 void AddImportGroup (XmlElement xmlElement, ImportedProject importedProject, bool evaluate_properties)
1140 // eval all the properties etc till the import group
1141 if (evaluate_properties) {
1142 groupingCollection.Evaluate (EvaluationType.Property);
1143 groupingCollection.Evaluate (EvaluationType.Choose);
1145 string condition_attribute = xmlElement.GetAttribute ("Condition");
1146 if (!ConditionParser.ParseAndEvaluate (condition_attribute, this))
1148 foreach (XmlNode xn in xmlElement.ChildNodes) {
1149 if (xn is XmlElement) {
1150 XmlElement xe = (XmlElement) xn;
1153 AddImport (xe, importedProject, evaluate_properties);
1156 throw new InvalidProjectFileException(String.Format("Invalid element '{0}' inside ImportGroup in project file '{1}'.", xe.Name, importedProject.FullFileName));
1162 bool AddSingleImport (XmlElement xmlElement, string projectPath, ImportedProject importingProject, string from_source_msg)
1164 Import import = new Import (xmlElement, projectPath, this, importingProject);
1165 if (!ConditionParser.ParseAndEvaluate (import.Condition, this)) {
1166 ParentEngine.LogMessage (MessageImportance.Low,
1167 "Not importing project '{0}' as the condition '{1}' is false",
1168 import.ProjectPath, import.Condition);
1172 Import existingImport;
1173 if (Imports.TryGetImport (import, out existingImport)) {
1174 if (importingProject == null)
1175 LogWarning (fullFileName,
1176 "Cannot import project '{0}' again. It was already imported by " +
1178 projectPath, existingImport.ContainedInProjectFileName);
1180 LogWarning (importingProject != null ? importingProject.FullFileName : fullFileName,
1181 "A circular reference was found involving the import of '{0}'. " +
1182 "It was earlier imported by '{1}'. Only " +
1183 "the first import of this file will be used, ignoring others.",
1184 import.EvaluatedProjectPath, existingImport.ContainedInProjectFileName);
1189 if (String.Compare (fullFileName, import.EvaluatedProjectPath) == 0) {
1190 LogWarning (importingProject != null ? importingProject.FullFileName : fullFileName,
1191 "The main project file was imported here, which creates a circular " +
1192 "reference. Ignoring this import.");
1197 if (project_load_settings != ProjectLoadSettings.IgnoreMissingImports &&
1198 !import.CheckEvaluatedProjectPathExists ())
1201 Imports.Add (import);
1202 string importingFile = importingProject != null ? importingProject.FullFileName : FullFileName;
1203 ParentEngine.LogMessage (MessageImportance.Low,
1204 "{0}: Importing project {1} {2}",
1205 importingFile, import.EvaluatedProjectPath, from_source_msg);
1207 import.Evaluate (project_load_settings == ProjectLoadSettings.IgnoreMissingImports);
1211 void AddItemGroup (XmlElement xmlElement, ImportedProject importedProject)
1213 BuildItemGroup big = new BuildItemGroup (xmlElement, this, importedProject, false);
1214 ItemGroups.Add (big);
1217 void AddPropertyGroup (XmlElement xmlElement, ImportedProject importedProject)
1219 BuildPropertyGroup bpg = new BuildPropertyGroup (xmlElement, this, importedProject, false);
1220 PropertyGroups.Add (bpg);
1223 void AddChoose (XmlElement xmlElement, ImportedProject importedProject)
1225 BuildChoose bc = new BuildChoose (xmlElement, this, importedProject);
1226 groupingCollection.Add (bc);
1229 static void ValidationCallBack (object sender, ValidationEventArgs e)
1231 Console.WriteLine ("Validation Error: {0}", e.Message);
1234 public bool BuildEnabled {
1236 return buildEnabled;
1239 buildEnabled = value;
1244 public Encoding Encoding {
1245 get { return encoding; }
1248 public string DefaultTargets {
1250 return String.Join ("; ", defaultTargets);
1253 xmlDocument.DocumentElement.SetAttribute ("DefaultTargets", value);
1255 defaultTargets = value.Split (new char [] {';', ' '},
1256 StringSplitOptions.RemoveEmptyEntries);
1260 public BuildItemGroup EvaluatedItems {
1262 if (needToReevaluate) {
1263 needToReevaluate = false;
1266 return evaluatedItems;
1270 public BuildItemGroup EvaluatedItemsIgnoringCondition {
1272 if (needToReevaluate) {
1273 needToReevaluate = false;
1276 return evaluatedItemsIgnoringCondition;
1280 internal IDictionary <string, BuildItemGroup> EvaluatedItemsByName {
1282 // FIXME: do we need to do this here?
1283 if (needToReevaluate) {
1284 needToReevaluate = false;
1287 return evaluatedItemsByName;
1291 internal IEnumerable EvaluatedItemsByNameAsDictionaryEntries {
1293 if (EvaluatedItemsByName.Count == 0)
1296 foreach (KeyValuePair<string, BuildItemGroup> pair in EvaluatedItemsByName) {
1297 foreach (BuildItem bi in pair.Value)
1298 yield return new DictionaryEntry (pair.Key, bi.ConvertToITaskItem (null, ExpressionOptions.ExpandItemRefs));
1303 internal IDictionary <string, BuildItemGroup> EvaluatedItemsByNameIgnoringCondition {
1305 // FIXME: do we need to do this here?
1306 if (needToReevaluate) {
1307 needToReevaluate = false;
1310 return evaluatedItemsByNameIgnoringCondition;
1314 // For batching implementation
1315 Dictionary<string, BuildItemGroup> perBatchItemsByName;
1316 Dictionary<string, BuildItemGroup> commonItemsByName;
1319 public Dictionary<string, BuildItemGroup> perBatchItemsByName;
1320 public Dictionary<string, BuildItemGroup> commonItemsByName;
1322 public Batch (Dictionary<string, BuildItemGroup> perBatchItemsByName, Dictionary<string, BuildItemGroup> commonItemsByName)
1324 this.perBatchItemsByName = perBatchItemsByName;
1325 this.commonItemsByName = commonItemsByName;
1329 Stack<Batch> Batches {
1330 get { return batches; }
1333 internal void PushBatch (Dictionary<string, BuildItemGroup> perBatchItemsByName, Dictionary<string, BuildItemGroup> commonItemsByName)
1335 batches.Push (new Batch (perBatchItemsByName, commonItemsByName));
1336 SetBatchedItems (perBatchItemsByName, commonItemsByName);
1339 internal void PopBatch ()
1342 if (batches.Count > 0) {
1343 Batch b = batches.Peek ();
1344 SetBatchedItems (b.perBatchItemsByName, b.commonItemsByName);
1346 SetBatchedItems (null, null);
1350 void SetBatchedItems (Dictionary<string, BuildItemGroup> perBatchItemsByName, Dictionary<string, BuildItemGroup> commonItemsByName)
1352 this.perBatchItemsByName = perBatchItemsByName;
1353 this.commonItemsByName = commonItemsByName;
1357 internal bool TryGetEvaluatedItemByNameBatched (string itemName, out BuildItemGroup group)
1359 if (perBatchItemsByName != null && perBatchItemsByName.TryGetValue (itemName, out group))
1362 if (commonItemsByName != null && commonItemsByName.TryGetValue (itemName, out group))
1366 return EvaluatedItemsByName.TryGetValue (itemName, out group);
1369 internal string GetMetadataBatched (string itemName, string metadataName)
1371 BuildItemGroup group = null;
1372 if (itemName == null) {
1373 //unqualified, all items in a batch(bucket) have the
1374 //same metadata values
1375 group = GetFirst<BuildItemGroup> (perBatchItemsByName.Values);
1377 group = GetFirst<BuildItemGroup> (commonItemsByName.Values);
1380 TryGetEvaluatedItemByNameBatched (itemName, out group);
1383 if (group != null) {
1384 foreach (BuildItem item in group) {
1385 if (item.HasMetadata (metadataName))
1386 return item.GetEvaluatedMetadata (metadataName);
1389 return String.Empty;
1392 internal IEnumerable<BuildItemGroup> GetAllItemGroups ()
1394 if (perBatchItemsByName == null && commonItemsByName == null)
1395 foreach (BuildItemGroup group in EvaluatedItemsByName.Values)
1398 if (perBatchItemsByName != null)
1399 foreach (BuildItemGroup group in perBatchItemsByName.Values)
1402 if (commonItemsByName != null)
1403 foreach (BuildItemGroup group in commonItemsByName.Values)
1407 T GetFirst<T> (ICollection<T> list)
1412 foreach (T t in list)
1418 // Used for MSBuild*This* set of properties
1419 internal void PushThisFileProperty (string full_filename)
1421 string last_file = this_file_property_stack.Count == 0 ? String.Empty : this_file_property_stack.Peek ();
1422 this_file_property_stack.Push (full_filename);
1423 if (last_file != full_filename)
1424 // first time, or different from previous one
1425 SetMSBuildThisFileProperties (full_filename);
1428 internal void PopThisFileProperty ()
1430 string last_file = this_file_property_stack.Pop ();
1431 if (this_file_property_stack.Count > 0 && last_file != this_file_property_stack.Peek ())
1432 SetMSBuildThisFileProperties (this_file_property_stack.Peek ());
1435 void SetMSBuildThisFileProperties (string full_filename)
1437 if (String.IsNullOrEmpty (full_filename))
1440 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFile", Path.GetFileName (full_filename), PropertyType.Reserved));
1441 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileFullPath", full_filename, PropertyType.Reserved));
1442 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileName", Path.GetFileNameWithoutExtension (full_filename), PropertyType.Reserved));
1443 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileExtension", Path.GetExtension (full_filename), PropertyType.Reserved));
1445 string project_dir = Path.GetDirectoryName (full_filename) + Path.DirectorySeparatorChar;
1446 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileDirectory", project_dir, PropertyType.Reserved));
1447 evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileDirectoryNoRoot",
1448 project_dir.Substring (Path.GetPathRoot (project_dir).Length),
1449 PropertyType.Reserved));
1453 internal void LogWarning (string filename, string message, params object[] messageArgs)
1455 BuildWarningEventArgs bwea = new BuildWarningEventArgs (
1456 null, null, filename, 0, 0, 0, 0, String.Format (message, messageArgs),
1458 ParentEngine.EventSource.FireWarningRaised (this, bwea);
1461 internal void LogError (string filename, string message,
1462 params object[] messageArgs)
1464 BuildErrorEventArgs beea = new BuildErrorEventArgs (
1465 null, null, filename, 0, 0, 0, 0, String.Format (message, messageArgs),
1467 ParentEngine.EventSource.FireErrorRaised (this, beea);
1470 internal static string DefaultExtensionsPath {
1472 if (extensions_path == null) {
1473 // NOTE: code from mcs/tools/gacutil/driver.cs
1474 PropertyInfo gac = typeof (System.Environment).GetProperty (
1475 "GacPath", BindingFlags.Static | BindingFlags.NonPublic);
1478 MethodInfo get_gac = gac.GetGetMethod (true);
1479 string gac_path = (string) get_gac.Invoke (null, null);
1480 extensions_path = Path.GetFullPath (Path.Combine (
1481 gac_path, Path.Combine ("..", "xbuild")));
1484 return extensions_path;
1488 public BuildPropertyGroup EvaluatedProperties {
1490 if (needToReevaluate) {
1491 needToReevaluate = false;
1494 return evaluatedProperties;
1498 internal IEnumerable EvaluatedPropertiesAsDictionaryEntries {
1500 foreach (BuildProperty bp in EvaluatedProperties)
1501 yield return new DictionaryEntry (bp.Name, bp.Value);
1505 public string FullFileName {
1506 get { return fullFileName; }
1507 set { fullFileName = value; }
1510 public BuildPropertyGroup GlobalProperties {
1511 get { return globalProperties; }
1514 throw new ArgumentNullException ("value");
1517 throw new InvalidOperationException ("GlobalProperties can not be set to persisted property group.");
1519 globalProperties = value;
1523 public bool IsDirty {
1524 get { return isDirty; }
1527 public bool IsValidated {
1528 get { return isValidated; }
1529 set { isValidated = value; }
1532 public BuildItemGroupCollection ItemGroups {
1533 get { return itemGroups; }
1536 public ImportCollection Imports {
1537 get { return imports; }
1540 public string InitialTargets {
1542 return String.Join ("; ", initialTargets.ToArray ());
1545 initialTargets.Clear ();
1546 xmlDocument.DocumentElement.SetAttribute ("InitialTargets", value);
1548 initialTargets.AddRange (value.Split (
1549 new char [] {';', ' '}, StringSplitOptions.RemoveEmptyEntries));
1553 public Engine ParentEngine {
1554 get { return parentEngine; }
1557 public BuildPropertyGroupCollection PropertyGroups {
1558 get { return propertyGroups; }
1561 public string SchemaFile {
1562 get { return schemaFile; }
1563 set { schemaFile = value; }
1566 public TargetCollection Targets {
1567 get { return targets; }
1570 public DateTime TimeOfLastDirty {
1571 get { return timeOfLastDirty; }
1574 public UsingTaskCollection UsingTasks {
1575 get { return usingTasks; }
1580 get { return xmlDocument.InnerXml; }
1583 // corresponds to the xml attribute
1584 public string DefaultToolsVersion {
1586 if (xmlDocument != null)
1587 return xmlDocument.DocumentElement.GetAttribute ("ToolsVersion");
1591 if (xmlDocument != null)
1592 xmlDocument.DocumentElement.SetAttribute ("ToolsVersion", value);
1596 public bool HasToolsVersionAttribute {
1598 return xmlDocument != null && xmlDocument.DocumentElement.HasAttribute ("ToolsVersion");
1602 public string ToolsVersion {
1606 internal Dictionary <string, BuildItemGroup> LastItemGroupContaining {
1607 get { return last_item_group_containing; }
1610 internal ProjectLoadSettings ProjectLoadSettings {
1611 get { return project_load_settings; }
1612 set { project_load_settings = value; }
1615 internal static XmlNamespaceManager XmlNamespaceManager {
1617 if (manager == null) {
1618 manager = new XmlNamespaceManager (new NameTable ());
1619 manager.AddNamespace ("tns", ns);
1626 internal TaskDatabase TaskDatabase {
1627 get { return taskDatabase; }
1630 internal XmlDocument XmlDocument {
1631 get { return xmlDocument; }
1634 internal static string XmlNamespace {
1640 PlatformID pid = Environment.OSVersion.Platform;
1648 return "Windows_NT";