Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Program.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.IO;
6 using System.Linq;
7 using System.Runtime.CompilerServices;
8 
9 using Mono.Options;
10 
11 using System.Reflection;
12 using System.Text;
13 using System.Diagnostics;
14 
15 using SiliconStudio.BuildEngine;
16 using SiliconStudio.Core;
17 using SiliconStudio.Core.Diagnostics;
18 using SiliconStudio.Paradox.Assets.Model;
19 using SiliconStudio.Paradox.Assets.SpriteFont;
20 using SiliconStudio.Paradox.Effects.Modules;
21 using SiliconStudio.Paradox.Graphics;
22 
23 namespace SiliconStudio.Assets.CompilerApp
24 {
25  class Program
26  {
27  private static Stopwatch clock;
28  private static string FormatLog(ILogMessage message)
29  {
30  //$filename($row,$column): $error_type $error_code: $error_message
31  //C:\Code\Paradox\sources\assets\SiliconStudio.Assets.CompilerApp\PackageBuilder.cs(89,13,89,70): warning CS1717: Assignment made to same variable; did you mean to assign something else?
32  var builder = new StringBuilder();
33  builder.Append(message.Module);
34  builder.Append(": ");
35  builder.Append(message.Type.ToString().ToLowerInvariant()).Append(" ");
36  builder.Append((clock.ElapsedMilliseconds * 0.001).ToString("0.000"));
37  builder.Append("s: ");
38  builder.Append(message.Text);
39  return builder.ToString();
40  }
41 
42  private static int Main(string[] args)
43  {
44  clock = Stopwatch.StartNew();
45 
46  // TODO this is hardcoded. Check how to make this dynamic instead.
47  RuntimeHelpers.RunModuleConstructor(typeof(MaterialKeys).Module.ModuleHandle);
48  RuntimeHelpers.RunModuleConstructor(typeof(SpriteFontAsset).Module.ModuleHandle);
49  RuntimeHelpers.RunModuleConstructor(typeof(ModelAsset).Module.ModuleHandle);
50  //var project = new Package();
51  //project.Save("test.pdxpkg");
52 
53  //Thread.Sleep(10000);
54  //var spriteFontAsset = StaticFontAsset.New();
55  //Asset.Save("test.pdxfnt", spriteFontAsset);
56  //project.Refresh();
57 
58  //args = new string[] { "test.pdxpkg", "-o:app_data", "-b:tmp", "-t:1" };
59 
60  //hardcoded physics
61  Paradox.Physics.PhysicsEngine.InitializeConverters();
62 
63  var exeName = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
64  var showHelp = false;
65  var options = new PackageBuilderOptions(GlobalLogger.GetLogger("BuildEngine"));
66 
67  var p = new OptionSet
68  {
69  "Copyright (C) 2011-2014 Silicon Studio Corporation. All Rights Reserved",
70  "Paradox Build Tool - Version: "
71  +
72  String.Format(
73  "{0}.{1}.{2}",
74  typeof(Program).Assembly.GetName().Version.Major,
75  typeof(Program).Assembly.GetName().Version.Minor,
76  typeof(Program).Assembly.GetName().Version.Build) + string.Empty,
77  string.Format("Usage: {0} inputPackageFile [options]* -b buildPath", exeName),
78  string.Empty,
79  "=== Options ===",
80  string.Empty,
81  { "h|help", "Show this message and exit", v => showHelp = v != null },
82  { "v|verbose", "Show more verbose progress logs", v => options.Verbose = v != null },
83  { "d|debug", "Show debug logs (imply verbose)", v => options.Debug = v != null },
84  { "log", "Enable file logging", v => options.EnableFileLogging = v != null },
85  { "p|profile=", "Profile name", v => options.BuildProfile = v },
86  { "project-configuration=", "Project configuration", v => options.ProjectConfiguration = v },
87  { "platform=", "Platform name", v => options.Platform = (PlatformType)Enum.Parse(typeof(PlatformType), v) },
88  { "graphics-platform=", "Graphics Platform name", v => options.GraphicsPlatform = (GraphicsPlatform)Enum.Parse(typeof(GraphicsPlatform), v) },
89  { "solution-file=", "Solution File Name", v => options.SolutionFile = v },
90  { "package-id=", "Package Id from the solution file", v => options.PackageId = Guid.Parse(v) },
91  { "package-file=", "Input Package File Name", v => options.PackageFile = v },
92  { "o|output-path=", "Output path", v => options.OutputDirectory = v },
93  { "b|build-path=", "Build path", v => options.BuildDirectory = v },
94  { "log-file=", "Log build in a custom file.", v =>
95  {
96  options.EnableFileLogging = v != null;
97  options.CustomLogFileName = v;
98  } },
99  { "log-pipe=", "Log pipe.", v =>
100  {
101  if (!string.IsNullOrEmpty(v))
102  options.LogPipeNames.Add(v);
103  } },
104  { "monitor-pipe=", "Monitor pipe.", v =>
105  {
106  if (!string.IsNullOrEmpty(v))
107  options.MonitorPipeNames.Add(v);
108  } },
109  { "slave=", "Slave pipe", v => options.SlavePipe = v }, // Benlitz: I don't think this should be documented
110  { "t|threads=", "Number of threads to create. Default value is the number of hardware threads available.", v => options.ThreadCount = int.Parse(v) },
111  { "test=", "Run a test session.", v => options.TestName = v },
112  { "property:", "Properties. Format is name1=value1;name2=value2", v =>
113  {
114  if (!string.IsNullOrEmpty(v))
115  {
116  foreach (var nameValue in v.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
117  {
118  var equalIndex = nameValue.IndexOf('=');
119  if (equalIndex == -1)
120  throw new OptionException("Expect name1=value1;name2=value2 format.", "property");
121 
122  options.Properties.Add(nameValue.Substring(0, equalIndex), nameValue.Substring(equalIndex + 1));
123  }
124  }
125  }
126  },
127  { "compile-property:", "Compile properties. Format is name1=value1;name2=value2", v =>
128  {
129  if (!string.IsNullOrEmpty(v))
130  {
131  if (options.ExtraCompileProperties == null)
132  options.ExtraCompileProperties = new Dictionary<string, string>();
133 
134  foreach (var nameValue in v.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
135  {
136  var equalIndex = nameValue.IndexOf('=');
137  if (equalIndex == -1)
138  throw new OptionException("Expect name1=value1;name2=value2 format.", "property");
139 
140  options.ExtraCompileProperties.Add(nameValue.Substring(0, equalIndex), nameValue.Substring(equalIndex + 1));
141  }
142  }
143  }
144  },
145  };
146 
147  TextWriterLogListener fileLogListener = null;
148 
149  // Output logs to the console with colored messages
150  if (options.SlavePipe == null)
151  {
152  var consoleLogListener = new ConsoleLogListener { TextFormatter = FormatLog, LogMode = ConsoleLogMode.Always };
153  GlobalLogger.GlobalMessageLogged += consoleLogListener;
154  }
155 
156  BuildResultCode exitCode;
157 
158  try
159  {
160  var unexpectedArgs = p.Parse(args);
161  if (unexpectedArgs.Any())
162  {
163  throw new OptionException("Unexpected arguments [{0}]".ToFormat(string.Join(", ", unexpectedArgs)), "args");
164  }
165  try
166  {
167  options.ValidateOptions();
168  }
169  catch (ArgumentException ex)
170  {
171  throw new OptionException(ex.Message, ex.ParamName);
172  }
173 
174  // Also write logs from master process into a file
175  if (options.SlavePipe == null)
176  {
177  if (options.EnableFileLogging)
178  {
179  string logFileName = options.CustomLogFileName;
180  if (string.IsNullOrEmpty(logFileName))
181  {
182  string inputName = Path.GetFileNameWithoutExtension(options.PackageFile);
183  logFileName = "Logs/Build-" + inputName + "-" + DateTime.Now.ToString("yy-MM-dd-HH-mm") + ".txt";
184  }
185 
186  string dirName = Path.GetDirectoryName(logFileName);
187  if (dirName != null)
188  Directory.CreateDirectory(dirName);
189 
190  fileLogListener = new TextWriterLogListener(new FileStream(logFileName, FileMode.Create)) { TextFormatter = FormatLog };
191  GlobalLogger.GlobalMessageLogged += fileLogListener;
192  }
193  options.Logger.Info("BuildEngine arguments: " + string.Join(" ", args));
194  options.Logger.Info("Starting builder.");
195  }
196 
197  if (showHelp)
198  {
199  p.WriteOptionDescriptions(Console.Out);
200  exitCode = BuildResultCode.Successful;
201  }
202  else if (!string.IsNullOrEmpty(options.TestName))
203  {
204  var test = new TestSession();
205  test.RunTest(options.TestName, options.Logger);
206  exitCode = BuildResultCode.Successful;
207  }
208  else
209  {
210  var builder = new PackageBuilder(options);
211  Console.CancelKeyPress += (_, e) => e.Cancel = builder.Cancel();
212  exitCode = builder.Build();
213  }
214  }
215  catch (OptionException e)
216  {
217  options.Logger.Error("Command option '{0}': {1}", e.OptionName, e.Message);
218  exitCode = BuildResultCode.CommandLineError;
219  }
220  catch (Exception e)
221  {
222  options.Logger.Error("Unhandled exception: {0}", e, e.Message);
223  exitCode = BuildResultCode.BuildError;
224  }
225  finally
226  {
227  if (fileLogListener != null)
228  fileLogListener.LogWriter.Close();
229 
230  }
231  return (int)exitCode;
232  }
233  }
234 }
PlatformType
Describes the platform operating system.
Definition: PlatformType.cs:9
static Logger GetLogger(string module)
Gets the GlobalLogger associated to the specified module.
GraphicsPlatform
The graphics platform.
System.IO.FileMode FileMode
Definition: ScriptSync.cs:33
A LogListener implementation redirecting its output to a TextWriter.
The base interface for log messages used by the logging infrastructure.
Definition: ILogMessage.cs:8
A logger that redirect messages to a global handler and handle instantiated MapModuleNameToLogger.
Definition: GlobalLogger.cs:12
A LogListener implementation redirecting its output to the default OS console. If console is not supp...