Merge pull request #1275 from ranma42/fix-lib64
[mono.git] / mcs / class / Microsoft.Build / Microsoft.Build.Execution / BuildManager.cs
1 // BuildManager.cs
2 //
3 // Author:
4 //   Rolf Bjarne Kvinge (rolf@xamarin.com)
5 //   Atsushi Enomoto (atsushi@xamarin.com)
6 //
7 // Copyright (C) 2011,2013 Xamarin Inc.
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
29 using Microsoft.Build.Evaluation;
30 using System;
31 using System.Collections.Generic;
32 using System.Threading;
33 using Microsoft.Build.Internal;
34 using System.Linq;
35
36 namespace Microsoft.Build.Execution
37 {
38         public class BuildManager
39         {
40                 static BuildManager default_manager = new BuildManager ();
41
42                 public static BuildManager DefaultBuildManager {
43                         get { return default_manager; }
44                 }
45                 
46                 public BuildManager ()
47                 {
48                 }
49
50                 public BuildManager (string hostName)
51                 {
52                         throw new NotImplementedException ();
53                 }
54                 
55                 public void Dispose ()
56                 {
57                         WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
58                         BuildNodeManager.Stop ();
59                 }
60
61                 ~BuildManager ()
62                 {
63                         // maybe processes created by out-of-process nodes should be signaled.
64                 }
65
66                 readonly List<BuildSubmission> submissions = new List<BuildSubmission> ();
67                 
68                 BuildParameters ongoing_build_parameters;
69                 
70                 internal BuildParameters OngoingBuildParameters {
71                         get { return ongoing_build_parameters; }
72                 }
73
74                 public void BeginBuild (BuildParameters parameters)
75                 {
76                         if (ongoing_build_parameters != null)
77                                 throw new InvalidOperationException ("There is already ongoing build");
78                         ongoing_build_parameters = parameters.Clone ();
79                 }
80
81                 public BuildResult Build (BuildParameters parameters, BuildRequestData requestData)
82                 {
83                         BeginBuild (parameters);
84                         var ret = BuildRequest (requestData);
85                         EndBuild ();
86                         return ret;
87                 }
88
89                 public BuildResult BuildRequest (BuildRequestData requestData)
90                 {
91                         var sub = PendBuildRequest (requestData);
92                         sub.Execute ();
93                         return sub.BuildResult;
94                 }
95                 
96                 public void CancelAllSubmissions ()
97                 {
98                         foreach (var sub in submissions) {
99                                 try {
100                                         if (!sub.IsCompleted)
101                                                 sub.Cancel ();
102                                 } catch (InvalidOperationException) {
103                                         // some submissions could be already done during this iteration. Ignore that.
104                                 }
105                         }
106                         submissions.Clear ();
107                 }
108
109                 public void EndBuild ()
110                 {
111                         if (ongoing_build_parameters == null)
112                                 throw new InvalidOperationException ("Build has not started");
113                         if (submissions.Count > 0)
114                                 WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
115                         BuildNodeManager.Stop ();
116                         ongoing_build_parameters = null;
117                 }
118                 
119                 Dictionary<Project,ProjectInstance> instances = new Dictionary<Project, ProjectInstance> ();
120
121                 public ProjectInstance GetProjectInstanceForBuild (Project project)
122                 {
123                         if (project == null)
124                                 throw new ArgumentNullException ("project");
125                         if (project.FullPath == null)
126                                 throw new ArgumentNullException ("project", "FullPath parameter in the project cannot be null.");
127                         if (project.FullPath == string.Empty)
128                                 throw new ArgumentException ("FullPath parameter in the project cannot be empty.", "project");
129                         // other than that, any invalid path character is accepted...
130                         
131                         return GetProjectInstanceForBuildInternal (project);
132                 }
133                         
134                 internal ProjectInstance GetProjectInstanceForBuildInternal (Project project)
135                 {
136                         if (!instances.ContainsKey (project))
137                                 instances [project] = project.CreateProjectInstance ();
138                         return instances [project];
139                 }
140
141                 public BuildSubmission PendBuildRequest (BuildRequestData requestData)
142                 {
143                         if (ongoing_build_parameters == null)
144                                 throw new InvalidOperationException ("This method cannot be called before calling BeginBuild method.");
145                         var sub = new BuildSubmission (this, requestData);
146                         submissions.Add (sub);
147                         return sub;
148                 }
149
150                 public void ResetCaches ()
151                 {
152                         if (OngoingBuildParameters != null)
153                                 throw new InvalidOperationException ("Cannot reset caches while builds are in progress.");
154                         
155                         BuildNodeManager.ResetCaches ();
156                 }
157                 
158                 BuildNodeManager build_node_manager;
159                 
160                 internal BuildNodeManager BuildNodeManager {
161                         get {
162                                 if (build_node_manager == null)
163                                                 build_node_manager = new BuildNodeManager (this);
164                                 return build_node_manager;
165                         }
166                 }
167         }
168 }