public void Compile() { if (_thread != null) { throw new InvalidOperationException("Compile is already running"); } WasSuccessful = false; var compileParameters = new CompileParameters { DataUnits = DataUnits, ResourceDatabase = ResourceDatabase, LogErrors = LogErrors, OnComplete = OnComplete }; if (UseThread) { _thread = new Thread(o => { DoCompile(o as CompileParameters); }); _thread.Start(compileParameters); } else { DoCompile(compileParameters); } }
private static void DoCompile(CompileParameters p) { using (var provider = new CSharpCodeProvider()) { var compileUnits = new List <CodeCompileUnit>(); if (p.ResourceDatabase != null) { var compiler = new ResourceCompiler(); compiler.ClassName = TypeSafeUtil.GetFinalClassName(Strings.ResourcesTypeName); compiler.Namespace = Settings.Instance.Namespace; try { var u = compiler.Compile(p.ResourceDatabase); compileUnits.Add(u); } catch (Exception e) { TSLog.LogError(LogCategory.Compile, "Exception occured while compiling resources unit."); TSLog.LogError(LogCategory.Compile, e.ToString()); } } if (p.DataUnits != null) { var compiler = new DataUnitCompiler(); compiler.Namespace = Settings.Instance.Namespace; foreach (var dataUnit in p.DataUnits) { try { compileUnits.Add(compiler.Compile(dataUnit)); } catch (Exception e) { TSLog.LogError(LogCategory.Compile, string.Format("Exception occured while compiling data unit {0}", dataUnit.ClassName)); TSLog.LogError(LogCategory.Compile, e.ToString()); } } } var results = new List <string>(); var didSucceed = false; switch (p.CompileMode) { case CompileModes.Dll: string path; didSucceed = CompileToDll(provider, compileUnits, p, out path); results.Add(path); break; case CompileModes.SourceFiles: IList <string> r; didSucceed = CompileToSourceFiles(provider, compileUnits, p, out r); results.AddRange(r); break; } if (p.OnComplete != null) { p.OnComplete(didSucceed, results); } } }
private static bool CompileToSourceFiles(CodeDomProvider provider, IEnumerable <CodeCompileUnit> compileUnits, CompileParameters p, out IList <string> paths) { TSLog.Log(LogCategory.Trace, "Compiling to Source Files"); PathUtility.EnsureDirectoryExists(PathUtility.GetBuildTempDirectory()); var codeGeneratorOptions = new CodeGeneratorOptions(); codeGeneratorOptions.VerbatimOrder = true; var outputPath = PathUtility.GetBuildTempDirectory(); var outputPaths = new List <string>(); foreach (var c in compileUnits) { var found = false; foreach (var key in c.UserData.Keys) { var s = key as string; if (s != null && s == Strings.CompileUnitUserDataKey) { found = true; break; } } if (!found) { TSLog.LogError(LogCategory.Compile, "Compile unit does not contain name user data key"); continue; } var name = (string)c.UserData[Strings.CompileUnitUserDataKey]; var fileName = string.Format(Strings.SourceFileNameFormat, name); var o = Path.Combine(outputPath, fileName); using (var fs = File.Open(o, FileMode.Create, FileAccess.Write)) { using (var tw = new StreamWriter(fs)) { provider.GenerateCodeFromCompileUnit(c, tw, codeGeneratorOptions); } } // Read the newly generated file var file = File.ReadAllLines(o); // It's not worth the bother to do this. sealed and private constructor achieve the same effect. /*// Replace sealed classes with static ones. (CodeDOM doesn't have a way of creating static classes by default) * for (var i = 0; i < file.Length; i++) { * * var s = file[i]; * * if (s.Contains("public sealed ")) { * file[i] = s.Replace("public sealed ", "public static "); * break; * } * * }*/ // Write with default header removed File.WriteAllLines(o, file.Skip(10).ToArray()); outputPaths.Add(o); } paths = outputPaths; return(true); }
private static bool CompileToDll(CodeDomProvider provider, IEnumerable <CodeCompileUnit> compileUnits, CompileParameters p, out string path) { TSLog.Log(LogCategory.Trace, "Compiling to DLL"); var compilerParameters = new CompilerParameters(); compilerParameters.ReferencedAssemblies.Add(typeof(int).Assembly.Location); compilerParameters.ReferencedAssemblies.Add(typeof(Object).Assembly.Location); compilerParameters.ReferencedAssemblies.Add("TypeSafe.dll"); if (p.ResourceDatabase != null) { // Include references to assemblies used in resources var list = GetReferencedAssemblies(p.ResourceDatabase); foreach (var s in list) { if (!compilerParameters.ReferencedAssemblies.Contains(s)) { compilerParameters.ReferencedAssemblies.Add(s); } } } for (var i = 0; i < compilerParameters.ReferencedAssemblies.Count; i++) { TSLog.Log(LogCategory.Trace, string.Format("Referencing Assembly: {0}", compilerParameters.ReferencedAssemblies[i])); } PathUtility.EnsureDirectoryExists(PathUtility.GetBuildTempDirectory()); compilerParameters.OutputAssembly = PathUtility.GetBuildTempDirectory() + "/" + Strings.DllName; //compilerParameters.TempFiles.KeepFiles = true; TSLog.Log(LogCategory.Trace, "Compile starting..."); var result = provider.CompileAssemblyFromDom(compilerParameters, compileUnits.ToArray()); if (p.LogErrors) { for (var i = 0; i < result.Errors.Count; i++) { var error = result.Errors[i]; if (error.IsWarning) { TSLog.LogWarning(LogCategory.Compile, error.ToString()); } else { TSLog.LogError(LogCategory.Compile, error.ToString()); } } } path = result.PathToAssembly; return(result.NativeCompilerReturnValue == 0); }