In class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine:
[mono.git] / mcs / class / Microsoft.Build.Tasks / Microsoft.Build.Tasks / MSBuild.cs
1 //
2 // MSBuild.cs: Task that can run .*proj files
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 #if NET_2_0
29
30 using System;
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.IO;
34 using Microsoft.Build.Framework;
35 using Microsoft.Build.Utilities;
36
37 namespace Microsoft.Build.Tasks {
38
39         [MonoTODO]
40         public class MSBuild : TaskExtension {
41         
42                 ITaskItem []    projects;
43                 string []       properties;
44                 bool            rebaseOutputs;
45                 bool            runEachTargetSeparately;
46                 bool            stopOnFirstFailure;
47                 bool            buildInParallel;
48                 ITaskItem []    targetOutputs;
49                 string []       targets;
50         
51                 public MSBuild ()
52                 {
53                 }
54
55                 public override bool Execute ()
56                 {
57                         if (projects.Length == 0)
58                                 return true;
59
60                         string filename;
61                         bool result = true;
62                         stopOnFirstFailure = false;
63                         List <ITaskItem > outputItems = new List <ITaskItem> ();
64                         string currentDirectory = Environment.CurrentDirectory;
65                         Hashtable outputs;
66                 
67                         Dictionary<string, string> global_properties = SplitPropertiesToDictionary ();
68                         Dictionary<string, ITaskItem> projectsByFileName = new Dictionary<string, ITaskItem> ();
69
70                         foreach (ITaskItem project in projects) {
71                                 filename = project.GetMetadata ("FullPath");
72                                 if (!File.Exists (filename)) {
73                                         Log.LogError ("Could not find the project file '{0}'", filename);
74                                         if (stopOnFirstFailure)
75                                                 break;
76
77                                         continue;
78                                 }
79
80                                 Directory.SetCurrentDirectory (Path.GetDirectoryName (filename));
81                                 outputs = new Hashtable ();
82
83                                 result = BuildEngine.BuildProjectFile (filename, targets, global_properties, outputs);
84
85                                 if (result) {
86                                         // Metadata from the first item for the project file is copied
87                                         ITaskItem first_item;
88                                         if (!projectsByFileName.TryGetValue (filename, out first_item))
89                                                 projectsByFileName [filename] = first_item = project;
90
91                                         foreach (DictionaryEntry de in outputs) {
92                                                 ITaskItem [] array = (ITaskItem []) de.Value;
93                                                 foreach (ITaskItem item in array) {
94                                                         // copy the metadata from original @project to here
95                                                         // CopyMetadataTo does _not_ overwrite
96                                                         first_item.CopyMetadataTo (item);
97
98                                                         outputItems.Add (item);
99
100                                                         //FIXME: Correctly rebase output paths to be relative to the
101                                                         //       calling project
102                                                         //if (rebaseOutputs)
103                                                         //      File.Copy (item.ItemSpec, Path.Combine (currentDirectory, item.ItemSpec), true);
104                                                 }
105                                         }
106                                 } else {
107                                         if (stopOnFirstFailure)
108                                                 break;
109                                 }
110
111                                 Directory.SetCurrentDirectory (currentDirectory);
112                         }
113
114                         if (result)
115                                 targetOutputs = outputItems.ToArray ();
116
117                         Directory.SetCurrentDirectory (currentDirectory);
118                         return result;
119                 }
120
121                 [Required]
122                 public ITaskItem [] Projects {
123                         get { return projects; }
124                         set { projects = value; }
125                 }
126
127                 [MonoTODO]
128                 public string [] Properties {
129                         get { return properties; }
130                         set { properties = value; }
131                 }
132
133                 public bool RebaseOutputs {
134                         get { return rebaseOutputs; }
135                         set { rebaseOutputs = value; }
136                 }
137
138                 [MonoTODO]
139                 public bool RunEachTargetSeparately {
140                         get { return runEachTargetSeparately; }
141                         set { runEachTargetSeparately = value; }
142                 }
143
144                 public bool StopOnFirstFailure {
145                         get { return stopOnFirstFailure; }
146                         set { stopOnFirstFailure = value; }
147                 }
148
149                 [Output]
150                 public ITaskItem [] TargetOutputs {
151                         get { return targetOutputs; }
152                 }
153
154                 public string [] Targets {
155                         get { return targets; }
156                         set { targets = value; }
157                 }
158
159                 public bool BuildInParallel {
160                         get { return buildInParallel; }
161                         set { buildInParallel = value; }
162                 }
163
164                 Dictionary<string, string> SplitPropertiesToDictionary ()
165                 {
166                         if (properties == null)
167                                 return null;
168
169                         Dictionary<string, string> global_properties = new Dictionary<string, string> ();
170                         foreach (string kvpair in properties) {
171                                 if (String.IsNullOrEmpty (kvpair))
172                                         continue;
173
174                                 string [] parts = kvpair.Trim ().Split (new char [] {'='}, 2);
175                                 if (parts.Length != 2) {
176                                         Log.LogWarning ("Invalid key/value pairs ({0}) in Properties, ignoring.", kvpair);
177                                         continue;
178                                 }
179
180                                 global_properties.Add (parts [0], parts [1]);
181                         }
182
183                         return global_properties;
184                 }
185
186         }
187 }
188
189 #endif