Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
VSProjectHelper.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Threading.Tasks;
7 using Microsoft.Build.Evaluation;
8 using Microsoft.Build.Execution;
9 using Microsoft.Build.Framework;
10 using SiliconStudio.Core;
11 using SiliconStudio.Core.Diagnostics;
13 
14 namespace SiliconStudio.Assets
15 {
16  public interface ICancellableAsyncBuild
17  {
18  string AssemblyPath { get; }
19 
20  Task<BuildResult> BuildTask { get; }
21 
22  bool IsCanceled { get; }
23 
24  void Cancel();
25  }
26 
27  public static class VSProjectHelper
28  {
29  private const string SiliconStudioProjectType = "SiliconStudioProjectType";
30  private const string SiliconStudioPlatform = "SiliconStudioPlatform";
31 
32  private static BuildManager mainBuildManager = new BuildManager();
33 
34  public static Guid GetProjectGuid(Microsoft.Build.Evaluation.Project project)
35  {
36  if (project == null) throw new ArgumentNullException("project");
37  return Guid.Parse(project.GetPropertyValue("ProjectGuid"));
38  }
39 
40  public static PlatformType? GetPlatformTypeFromProject(Microsoft.Build.Evaluation.Project project)
41  {
42  return GetEnumFromProperty<PlatformType>(project, SiliconStudioPlatform);
43  }
44 
45  public static ProjectType? GetProjectTypeFromProject(Microsoft.Build.Evaluation.Project project)
46  {
47  return GetEnumFromProperty<ProjectType>(project, SiliconStudioProjectType);
48  }
49 
50  private static T? GetEnumFromProperty<T>(Microsoft.Build.Evaluation.Project project, string propertyName) where T : struct
51  {
52  if (project == null) throw new ArgumentNullException("project");
53  if (propertyName == null) throw new ArgumentNullException("propertyName");
54  var value = project.GetPropertyValue(propertyName);
55  if (string.IsNullOrEmpty(value))
56  {
57  return null;
58  }
59  return (T)Enum.Parse(typeof(T), value);
60  }
61 
62  public static string GetOrCompileProjectAssembly(string fullProjectLocation, ILogger logger, bool autoCompileProject, string configuration = "Debug", string platform = "AnyCPU", Dictionary<string, string> extraProperties = null, bool onlyErrors = false, BuildRequestDataFlags flags = BuildRequestDataFlags.None)
63  {
64  if (fullProjectLocation == null) throw new ArgumentNullException("fullProjectLocation");
65  if (logger == null) throw new ArgumentNullException("logger");
66 
67  var project = LoadProject(fullProjectLocation, configuration, platform, extraProperties);
68  var assemblyPath = project.GetPropertyValue("TargetPath");
69 
70  if (!string.IsNullOrWhiteSpace(assemblyPath))
71  {
72  if (autoCompileProject)
73  {
74  var asyncBuild = new CancellableAsyncBuild(project, assemblyPath);
75  asyncBuild.Build(project, "Build", flags, new LoggerRedirect(logger, onlyErrors));
76  var buildResult = asyncBuild.BuildTask.Result;
77  }
78  }
79 
80  return assemblyPath;
81  }
82 
83  public static ICancellableAsyncBuild CompileProjectAssemblyAsync(string fullProjectLocation, ILogger logger, string targets = "Build", string configuration = "Debug", string platform = "AnyCPU", Dictionary<string, string> extraProperties = null, BuildRequestDataFlags flags = BuildRequestDataFlags.None)
84  {
85  if (fullProjectLocation == null) throw new ArgumentNullException("fullProjectLocation");
86  if (logger == null) throw new ArgumentNullException("logger");
87 
88  var project = LoadProject(fullProjectLocation, configuration, platform, extraProperties);
89  var assemblyPath = project.GetPropertyValue("TargetPath");
90 
91  if (!string.IsNullOrWhiteSpace(assemblyPath))
92  {
93  var asyncBuild = new CancellableAsyncBuild(project, assemblyPath);
94  asyncBuild.Build(project, targets, flags, new LoggerRedirect(logger));
95  return asyncBuild;
96  }
97 
98  return null;
99  }
100 
101  public static Microsoft.Build.Evaluation.Project LoadProject(string fullProjectLocation, string configuration = "Debug", string platform = "AnyCPU", Dictionary<string, string> extraProperties = null)
102  {
103  configuration = configuration ?? "Debug";
104  platform = platform ?? "AnyCPU";
105 
106  var globalProperties = new Dictionary<string, string>();
107  globalProperties["Configuration"] = configuration;
108  globalProperties["Platform"] = platform;
109 
110  if (extraProperties != null)
111  {
112  foreach (var extraProperty in extraProperties)
113  {
114  globalProperties[extraProperty.Key] = extraProperty.Value;
115  }
116  }
117 
118  var projectCollection = new Microsoft.Build.Evaluation.ProjectCollection(globalProperties);
119  projectCollection.LoadProject(fullProjectLocation);
120  var project = projectCollection.LoadedProjects.First();
121  return project;
122  }
123 
124  private class LoggerRedirect : Microsoft.Build.Utilities.Logger
125  {
126  private readonly ILogger logger;
127  private readonly bool onlyErrors;
128 
129  public LoggerRedirect(ILogger logger, bool onlyErrors = false)
130  {
131  if (logger == null) throw new ArgumentNullException("logger");
132  this.logger = logger;
133  this.onlyErrors = onlyErrors;
134  }
135 
136  public override void Initialize(Microsoft.Build.Framework.IEventSource eventSource)
137  {
138  if (eventSource == null) throw new ArgumentNullException("eventSource");
139  if (!onlyErrors)
140  {
141  eventSource.MessageRaised += MessageRaised;
142  eventSource.WarningRaised += WarningRaised;
143  }
144  eventSource.ErrorRaised += ErrorRaised;
145  }
146 
147  void MessageRaised(object sender, BuildMessageEventArgs e)
148  {
149  var loggerResult = logger as LoggerResult;
150  if (loggerResult != null)
151  {
152  loggerResult.Module = string.Format("{0}({1},{2})", e.File, e.LineNumber, e.ColumnNumber);
153  }
154  switch (e.Importance)
155  {
156  case MessageImportance.High:
157  logger.Info(e.Message);
158  break;
159  case MessageImportance.Normal:
160  logger.Verbose(e.Message);
161  break;
162  case MessageImportance.Low:
163  logger.Debug(e.Message);
164  break;
165  }
166  }
167 
168  void WarningRaised(object sender, BuildWarningEventArgs e)
169  {
170  var loggerResult = logger as LoggerResult;
171  if (loggerResult != null)
172  {
173  loggerResult.Module = string.Format("{0}({1},{2})", e.File, e.LineNumber, e.ColumnNumber);
174  }
175  logger.Warning(e.Message);
176  }
177 
178  void ErrorRaised(object sender, Microsoft.Build.Framework.BuildErrorEventArgs e)
179  {
180  var loggerResult = logger as LoggerResult;
181  if (loggerResult != null)
182  {
183  loggerResult.Module = string.Format("{0}({1},{2})", e.File, e.LineNumber, e.ColumnNumber);
184  }
185  logger.Error(e.Message);
186  }
187  }
188 
189  private class CancellableAsyncBuild : ICancellableAsyncBuild
190  {
191  public CancellableAsyncBuild(Project project, string assemblyPath)
192  {
193  Project = project;
194  AssemblyPath = assemblyPath;
195  }
196 
197  public string AssemblyPath { get; private set; }
198 
199  public Project Project { get; private set; }
200 
201  public Task<BuildResult> BuildTask { get; private set; }
202 
203  public bool IsCanceled { get; private set; }
204 
205  internal void Build(Microsoft.Build.Evaluation.Project project, string targets, BuildRequestDataFlags flags, Microsoft.Build.Utilities.Logger logger)
206  {
207  if (project == null) throw new ArgumentNullException("project");
208  if (logger == null) throw new ArgumentNullException("logger");
209 
210  // Make sure that we are using the project collection from the loaded project, otherwise we are getting
211  // weird cache behavior with the msbuild system
212  var projectInstance = new ProjectInstance(project.Xml, project.ProjectCollection.GlobalProperties, null, project.ProjectCollection);
213 
214  BuildTask = Task.Run(() =>
215  {
216  var buildResult = mainBuildManager.Build(
217  new BuildParameters(project.ProjectCollection)
218  {
219  Loggers = new[] { logger }
220  },
221  new BuildRequestData(projectInstance, targets.Split(';'), null, flags));
222 
223  return buildResult;
224  });
225  }
226 
227  public void Cancel()
228  {
229  var localManager = mainBuildManager;
230  if (localManager != null)
231  {
232  localManager.CancelAllSubmissions();
233  IsCanceled = true;
234  }
235  }
236  }
237  }
238 }
static ICancellableAsyncBuild CompileProjectAssemblyAsync(string fullProjectLocation, ILogger logger, string targets="Build", string configuration="Debug", string platform="AnyCPU", Dictionary< string, string > extraProperties=null, BuildRequestDataFlags flags=BuildRequestDataFlags.None)
PlatformType
Describes the platform operating system.
Definition: PlatformType.cs:9
SiliconStudio.Core.Diagnostics.ILogger ILogger
static PlatformType GetPlatformTypeFromProject(Microsoft.Build.Evaluation.Project project)
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
Definition: DirectXTexP.h:170
SiliconStudio.Core.Diagnostics.LoggerResult LoggerResult
static string GetOrCompileProjectAssembly(string fullProjectLocation, ILogger logger, bool autoCompileProject, string configuration="Debug", string platform="AnyCPU", Dictionary< string, string > extraProperties=null, bool onlyErrors=false, BuildRequestDataFlags flags=BuildRequestDataFlags.None)
static ProjectType GetProjectTypeFromProject(Microsoft.Build.Evaluation.Project project)
Base implementation for ILogger.
Definition: Logger.cs:10
System.IO.File File
EnvDTE.Project Project
static Microsoft.Build.Evaluation.Project LoadProject(string fullProjectLocation, string configuration="Debug", string platform="AnyCPU", Dictionary< string, string > extraProperties=null)
ProjectType
Type of the project.
Definition: ProjectType.cs:11
The dialog has been closed by a cancellation from the user.
Interface for logging.
Definition: ILogger.cs:8
static Guid GetProjectGuid(Microsoft.Build.Evaluation.Project project)