/// <summary> /// Generates the user types. /// </summary> private void GenerateUserTypes() { // Verify that included files exist if (!string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName)) { foreach (var file in includedFiles) { if (!File.Exists(file.Path)) { throw new FileNotFoundException("Included file not found", file.Path); } } } // Loading modules ConcurrentDictionary <Module, XmlModule> modules = new ConcurrentDictionary <Module, XmlModule>(); ConcurrentDictionary <XmlModule, Symbol[]> globalTypesPerModule = new ConcurrentDictionary <XmlModule, Symbol[]>(); logger.Write("Loading modules..."); Parallel.ForEach(xmlModules, (xmlModule) => { Module module = moduleProvider.Open(xmlModule); modules.TryAdd(module, xmlModule); }); logger.WriteLine(" {0}", stopwatch.Elapsed); // Enumerating symbols logger.Write("Enumerating symbols..."); Parallel.ForEach(modules, (mm) => { XmlModule xmlModule = mm.Value; Module module = mm.Key; string moduleName = xmlModule.Name; string nameSpace = xmlModule.Namespace; HashSet <Symbol> symbols = new HashSet <Symbol>(); foreach (var type in typeNames) { Symbol[] foundSymbols = module.FindGlobalTypeWildcard(type.NameWildcard); if (foundSymbols.Length == 0) { errorLogger.WriteLine("Symbol not found: {0}", type.Name); } else { foreach (Symbol symbol in foundSymbols) { symbols.Add(symbol); } } if (type.ExportDependentTypes) { foreach (Symbol symbol in foundSymbols) { symbol.ExtractDependentSymbols(symbols, xmlConfig.Transformations); } } } if (symbols.Count == 0) { foreach (Symbol symbol in module.GetAllTypes()) { symbols.Add(symbol); } } globalTypesPerModule.TryAdd( xmlModule, symbols.Where(t => t.Tag == CodeTypeTag.Class || t.Tag == CodeTypeTag.Structure || t.Tag == CodeTypeTag.Union || t.Tag == CodeTypeTag.Enum).ToArray()); }); List <Symbol> allSymbols = new List <Symbol>(); Symbol[][] symbolsPerModule = globalTypesPerModule.Select(ss => ss.Value).ToArray(); int maxSymbols = symbolsPerModule.Max(ss => ss.Length); for (int i = 0; i < maxSymbols; i++) { for (int j = 0; j < symbolsPerModule.Length; j++) { if (i < symbolsPerModule[j].Length) { allSymbols.Add(symbolsPerModule[j][i]); } } } logger.WriteLine(" {0}", stopwatch.Elapsed); #if false // Initialize symbol fields and base classes logger.Write("Initializing symbol values..."); Parallel.ForEach(Partitioner.Create(allSymbols), (symbol) => { var fields = symbol.Fields; var baseClasses = symbol.BaseClasses; }); logger.WriteLine(" {0}", sw.Elapsed); #endif logger.Write("Deduplicating symbols..."); // Group duplicated symbols Dictionary <string, List <Symbol> > symbolsByName = new Dictionary <string, List <Symbol> >(); Dictionary <Symbol, List <Symbol> > duplicatedSymbols = new Dictionary <Symbol, List <Symbol> >(); foreach (var symbol in allSymbols) { List <Symbol> symbols; if (!symbolsByName.TryGetValue(symbol.Name, out symbols)) { symbolsByName.Add(symbol.Name, symbols = new List <Symbol>()); } bool found = false; foreach (var s in symbols.ToArray()) { if (s.Size != 0 && symbol.Size != 0 && s.Size != symbol.Size) { #if DEBUG logger.WriteLine("{0}!{1} ({2}) {3}!{4} ({5})", s.Module.Name, s.Name, s.Size, symbol.Module.Name, symbol.Name, symbol.Size); #endif continue; } if (s.Size == 0 && symbol.Size != 0) { List <Symbol> duplicates; if (!duplicatedSymbols.TryGetValue(s, out duplicates)) { duplicatedSymbols.Add(s, duplicates = new List <Symbol>()); } duplicatedSymbols.Remove(s); duplicates.Add(s); duplicatedSymbols.Add(symbol, duplicates); symbols.Remove(s); symbols.Add(symbol); } else { List <Symbol> duplicates; if (!duplicatedSymbols.TryGetValue(s, out duplicates)) { duplicatedSymbols.Add(s, duplicates = new List <Symbol>()); } duplicates.Add(symbol); } found = true; break; } if (!found) { symbols.Add(symbol); } } // Unlink duplicated symbols if two or more are named the same foreach (var symbols in symbolsByName.Values) { if (symbols.Count <= 1) { continue; } foreach (var s in symbols.ToArray()) { List <Symbol> duplicates; if (!duplicatedSymbols.TryGetValue(s, out duplicates)) { continue; } symbols.AddRange(duplicates); duplicatedSymbols.Remove(s); } } // Extracting deduplicated symbols Dictionary <string, Symbol[]> deduplicatedSymbols = new Dictionary <string, Symbol[]>(); Dictionary <Symbol, string> symbolNamespaces = new Dictionary <Symbol, string>(); foreach (var symbols in symbolsByName.Values) { if (symbols.Count != 1 || modules.Count == 1) { foreach (var s in symbols) { symbolNamespaces.Add(s, modules[s.Module].Namespace); } } else { Symbol symbol = symbols.First(); List <Symbol> duplicates; if (!duplicatedSymbols.TryGetValue(symbol, out duplicates)) { duplicates = new List <Symbol>(); } duplicates.Insert(0, symbol); deduplicatedSymbols.Add(symbol.Name, duplicates.ToArray()); foreach (var s in duplicates) { symbolNamespaces.Add(s, xmlConfig.CommonTypesNamespace); } } } var globalTypes = symbolsByName.SelectMany(s => s.Value).ToArray(); logger.WriteLine(" {0}", stopwatch.Elapsed); logger.WriteLine(" Total symbols: {0}", globalTypesPerModule.Sum(gt => gt.Value.Length)); logger.WriteLine(" Unique symbol names: {0}", symbolsByName.Count); logger.WriteLine(" Dedupedlicated symbols: {0}", globalTypes.Length); // Initialize GlobalCache with deduplicatedSymbols GlobalCache.Update(deduplicatedSymbols); // Collecting types logger.Write("Collecting types..."); foreach (var module in modules.Keys) { userTypes.Add(userTypeFactory.AddSymbol(module.GlobalScope, new XmlType() { Name = "ModuleGlobals" }, modules[module].Namespace, generationOptions)); } ConcurrentBag <Symbol> simpleSymbols = new ConcurrentBag <Symbol>(); Dictionary <Tuple <string, string>, List <Symbol> > templateSymbols = new Dictionary <Tuple <string, string>, List <Symbol> >(); Parallel.ForEach(Partitioner.Create(globalTypes), (symbol) => { string symbolName = symbol.Name; // TODO: Add configurable filter // if (symbolName.StartsWith("$") || symbolName.StartsWith("__vc_attributes") || symbolName.Contains("`anonymous-namespace'") || symbolName.Contains("`anonymous namespace'") || symbolName.Contains("::$") || symbolName.Contains("`")) { return; } // Do not handle template referenced arguments if (symbolName.Contains("&")) { // TODO: Convert this to function pointer return; } // TODO: For now remove all unnamed-type symbols string scopedClassName = symbol.Namespaces.Last(); if (scopedClassName.StartsWith("<") || symbolName.Contains("::<")) { return; } // Check if symbol contains template type. if (SymbolNameHelper.ContainsTemplateType(symbolName) && (symbol.Tag == CodeTypeTag.Class || symbol.Tag == CodeTypeTag.Structure || symbol.Tag == CodeTypeTag.Union)) { List <string> namespaces = symbol.Namespaces; string className = namespaces.Last(); var symbolId = Tuple.Create(symbolNamespaces[symbol], SymbolNameHelper.CreateLookupNameForSymbol(symbol)); lock (templateSymbols) { if (templateSymbols.ContainsKey(symbolId) == false) { templateSymbols[symbolId] = new List <Symbol>() { symbol } } ; else { templateSymbols[symbolId].Add(symbol); } } // TODO: // Do not add physical types for template specialization (not now) // do if types contains static fields // nested in templates } else { simpleSymbols.Add(symbol); } }); logger.WriteLine(" {0}", stopwatch.Elapsed); // Populate Templates logger.Write("Populating templates..."); foreach (List <Symbol> symbols in templateSymbols.Values) { Symbol symbol = symbols.First(); string symbolName = SymbolNameHelper.CreateLookupNameForSymbol(symbol); XmlType type = new XmlType() { Name = symbolName }; userTypes.AddRange(userTypeFactory.AddSymbols(symbols, type, symbolNamespaces[symbol], generationOptions)); } logger.WriteLine(" {0}", stopwatch.Elapsed); // Specialized class logger.Write("Populating specialized classes..."); foreach (Symbol symbol in simpleSymbols) { userTypes.Add(userTypeFactory.AddSymbol(symbol, null, symbolNamespaces[symbol], generationOptions)); } logger.WriteLine(" {0}", stopwatch.Elapsed); // To solve template dependencies. Update specialization arguments once all the templates has been populated. logger.Write("Updating template arguments..."); foreach (TemplateUserType templateUserType in userTypes.OfType <TemplateUserType>()) { foreach (TemplateUserType specializedTemplateUserType in templateUserType.SpecializedTypes) { if (!specializedTemplateUserType.UpdateTemplateArguments(userTypeFactory)) { #if DEBUG logger.WriteLine("Template user type cannot be updated: {0}", specializedTemplateUserType.Symbol.Name); #endif } } } logger.WriteLine(" {0}", stopwatch.Elapsed); // Post processing user types (filling DeclaredInType) logger.Write("Post processing user types..."); var namespaceTypes = userTypeFactory.ProcessTypes(userTypes, symbolNamespaces).ToArray(); userTypes.AddRange(namespaceTypes); logger.WriteLine(" {0}", stopwatch.Elapsed); }
/// <summary> /// Generates user types using the specified XML configuration. /// </summary> /// <param name="xmlConfig">The XML configuration.</param> /// <param name="logger">The logger text writer. If set to null, Console.Out will be used.</param> /// <param name="errorLogger">The error logger text writer. If set to null, Console.Error will be used.</param> public static void Generate(XmlConfig xmlConfig, TextWriter logger = null, TextWriter errorLogger = null) { var sw = System.Diagnostics.Stopwatch.StartNew(); XmlModule[] xmlModules = xmlConfig.Modules; XmlType[] typeNames = xmlConfig.Types; XmlIncludedFile[] includedFiles = xmlConfig.IncludedFiles; XmlReferencedAssembly[] referencedAssemblies = xmlConfig.ReferencedAssemblies; UserTypeGenerationFlags generationOptions = xmlConfig.GetGenerationFlags(); ConcurrentDictionary <string, string> generatedFiles = new ConcurrentDictionary <string, string>(); var syntaxTrees = new ConcurrentBag <SyntaxTree>(); string currentDirectory = Directory.GetCurrentDirectory(); string outputDirectory = currentDirectory + "\\output\\"; // Check logger and error logger if (errorLogger == null) { errorLogger = Console.Error; } if (logger == null) { logger = Console.Out; } // Create output directory Directory.CreateDirectory(outputDirectory); // Verify that included files exist if (!string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName)) { foreach (var file in includedFiles) { if (!File.Exists(file.Path)) { throw new FileNotFoundException("", file.Path); } } } // Loading modules ConcurrentDictionary <Module, XmlModule> modules = new ConcurrentDictionary <Module, XmlModule>(); ConcurrentDictionary <XmlModule, Symbol[]> globalTypesPerModule = new ConcurrentDictionary <XmlModule, Symbol[]>(); logger.Write("Loading modules..."); Parallel.ForEach(xmlModules, (xmlModule) => { Module module = Module.Open(xmlModule); modules.TryAdd(module, xmlModule); }); logger.WriteLine(" {0}", sw.Elapsed); // Enumerating symbols logger.Write("Enumerating symbols..."); Parallel.ForEach(modules, (mm) => { XmlModule xmlModule = mm.Value; Module module = mm.Key; string moduleName = xmlModule.Name; string nameSpace = xmlModule.Namespace; List <Symbol> symbols = new List <Symbol>(); foreach (var type in typeNames) { Symbol[] foundSymbols = module.FindGlobalTypeWildcard(type.NameWildcard); if (foundSymbols.Length == 0) { errorLogger.WriteLine("Symbol not found: {0}", type.Name); } else { symbols.AddRange(foundSymbols); } } symbols.AddRange(module.GetAllTypes()); globalTypesPerModule.TryAdd(xmlModule, symbols.ToArray()); }); List <Symbol> allSymbols = new List <Symbol>(); Symbol[][] symbolsPerModule = globalTypesPerModule.Select(ss => ss.Value).ToArray(); int maxSymbols = symbolsPerModule.Max(ss => ss.Length); for (int i = 0; i < maxSymbols; i++) { for (int j = 0; j < symbolsPerModule.Length; j++) { if (i < symbolsPerModule[j].Length) { allSymbols.Add(symbolsPerModule[j][i]); } } } logger.WriteLine(" {0}", sw.Elapsed); #if false // Initialize symbol fields and base classes logger.Write("Initializing symbol values..."); Parallel.ForEach(Partitioner.Create(allSymbols), (symbol) => { var fields = symbol.Fields; var baseClasses = symbol.BaseClasses; }); logger.WriteLine(" {0}", sw.Elapsed); #endif logger.Write("Deduplicating symbols..."); // Group duplicated symbols Dictionary <string, List <Symbol> > symbolsByName = new Dictionary <string, List <Symbol> >(); Dictionary <Symbol, List <Symbol> > duplicatedSymbols = new Dictionary <Symbol, List <Symbol> >(); foreach (var symbol in allSymbols) { List <Symbol> symbols; if (!symbolsByName.TryGetValue(symbol.Name, out symbols)) { symbolsByName.Add(symbol.Name, symbols = new List <Symbol>()); } bool found = false; foreach (var s in symbols.ToArray()) { if (s.Size != 0 && symbol.Size != 0 && s.Size != symbol.Size) { #if DEBUG logger.WriteLine("{0}!{1} ({2}) {3}!{4} ({5})", s.Module.Name, s.Name, s.Size, symbol.Module.Name, symbol.Name, symbol.Size); #endif continue; } if (s.Size == 0 && symbol.Size != 0) { List <Symbol> duplicates; if (!duplicatedSymbols.TryGetValue(s, out duplicates)) { duplicatedSymbols.Add(s, duplicates = new List <Symbol>()); } duplicatedSymbols.Remove(s); duplicates.Add(s); duplicatedSymbols.Add(symbol, duplicates); symbols.Remove(s); symbols.Add(symbol); } else { List <Symbol> duplicates; if (!duplicatedSymbols.TryGetValue(s, out duplicates)) { duplicatedSymbols.Add(s, duplicates = new List <Symbol>()); } duplicates.Add(symbol); } found = true; break; } if (!found) { symbols.Add(symbol); } } // Unlink duplicated symbols if two or more are named the same foreach (var symbols in symbolsByName.Values) { if (symbols.Count <= 1) { continue; } foreach (var s in symbols.ToArray()) { List <Symbol> duplicates; if (!duplicatedSymbols.TryGetValue(s, out duplicates)) { continue; } symbols.AddRange(duplicates); duplicatedSymbols.Remove(s); } } // Extracting deduplicated symbols Dictionary <string, Symbol[]> deduplicatedSymbols = new Dictionary <string, Symbol[]>(); Dictionary <Symbol, string> symbolNamespaces = new Dictionary <Symbol, string>(); foreach (var symbols in symbolsByName.Values) { if (symbols.Count != 1) { foreach (var s in symbols) { symbolNamespaces.Add(s, modules[s.Module].Namespace); } } else { Symbol symbol = symbols.First(); List <Symbol> duplicates; if (!duplicatedSymbols.TryGetValue(symbol, out duplicates)) { duplicates = new List <Symbol>(); } duplicates.Insert(0, symbol); deduplicatedSymbols.Add(symbol.Name, duplicates.ToArray()); foreach (var s in duplicates) { symbolNamespaces.Add(s, xmlConfig.CommonTypesNamespace); } } } var globalTypes = symbolsByName.SelectMany(s => s.Value).ToArray(); logger.WriteLine(" {0}", sw.Elapsed); logger.WriteLine(" Total symbols: {0}", globalTypesPerModule.Sum(gt => gt.Value.Length)); logger.WriteLine(" Unique symbol names: {0}", symbolsByName.Count); logger.WriteLine(" Dedupedlicated symbols: {0}", globalTypes.Length); // Initialize GlobalCache with deduplicatedSymbols GlobalCache.Update(deduplicatedSymbols); // Collecting types logger.Write("Collecting types..."); var factory = new UserTypeFactory(xmlConfig.Transformations); List <UserType> userTypes = new List <UserType>(); foreach (var module in modules.Keys) { userTypes.Add(factory.AddSymbol(module.GlobalScope, new XmlType() { Name = "ModuleGlobals" }, modules[module].Namespace, generationOptions)); } ConcurrentBag <Symbol> simpleSymbols = new ConcurrentBag <Symbol>(); Dictionary <Tuple <string, string>, List <Symbol> > templateSymbols = new Dictionary <Tuple <string, string>, List <Symbol> >(); Parallel.ForEach(Partitioner.Create(globalTypes), (symbol) => { string symbolName = symbol.Name; // TODO: Add configurable filter // if (symbolName.StartsWith("$") || symbolName.StartsWith("__vc_attributes") || symbolName.Contains("`anonymous-namespace'") || symbolName.Contains("`anonymous namespace'") || symbolName.Contains("::$") || symbolName.Contains("`")) { return; } // Do not handle template referenced arguments if (symbolName.Contains("&")) { // TODO: Convert this to function pointer return; } // TODO: C# doesn't support lengthy names if (symbolName.Length > 160) { return; } // TODO: For now remove all unnamed-type symbols string scopedClassName = symbol.Namespaces.Last(); if (scopedClassName.StartsWith("<") || symbolName.Contains("::<")) { return; } // Check if symbol contains template type. if (SymbolNameHelper.ContainsTemplateType(symbolName)) { List <string> namespaces = symbol.Namespaces; string className = namespaces.Last(); var symbolId = Tuple.Create(symbolNamespaces[symbol], SymbolNameHelper.CreateLookupNameForSymbol(symbol)); lock (templateSymbols) { if (templateSymbols.ContainsKey(symbolId) == false) { templateSymbols[symbolId] = new List <Symbol>() { symbol } } ; else { templateSymbols[symbolId].Add(symbol); } } // TODO: // Do not add physical types for template specialization (not now) // do if types contains static fields // nested in templates } else { simpleSymbols.Add(symbol); } }); logger.WriteLine(" {0}", sw.Elapsed); // Populate Templates logger.Write("Populating templates..."); foreach (List <Symbol> symbols in templateSymbols.Values) { Symbol symbol = symbols.First(); string symbolName = SymbolNameHelper.CreateLookupNameForSymbol(symbol); XmlType type = new XmlType() { Name = symbolName }; userTypes.AddRange(factory.AddSymbols(symbols, type, symbolNamespaces[symbol], generationOptions)); } logger.WriteLine(" {0}", sw.Elapsed); // Specialized class logger.Write("Populating specialized classes..."); foreach (Symbol symbol in simpleSymbols) { userTypes.Add(factory.AddSymbol(symbol, null, symbolNamespaces[symbol], generationOptions)); } logger.WriteLine(" {0}", sw.Elapsed); // To solve template dependencies. Update specialization arguments once all the templates has been populated. logger.Write("Updating template arguments..."); foreach (TemplateUserType templateUserType in userTypes.OfType <TemplateUserType>()) { foreach (TemplateUserType specializedTemplateUserType in templateUserType.SpecializedTypes) { if (!specializedTemplateUserType.UpdateTemplateArguments(factory)) { #if DEBUG logger.WriteLine("Template user type cannot be updated: {0}", specializedTemplateUserType.Symbol.Name); #endif } } } logger.WriteLine(" {0}", sw.Elapsed); // Post processing user types (filling DeclaredInType) logger.Write("Post processing user types..."); var namespaceTypes = factory.ProcessTypes(userTypes, symbolNamespaces).ToArray(); userTypes.AddRange(namespaceTypes); logger.WriteLine(" {0}", sw.Elapsed); // Code generation and saving it to disk logger.Write("Saving code to disk..."); if (!generationOptions.HasFlag(UserTypeGenerationFlags.SingleFileExport)) { // Generate Code Parallel.ForEach(userTypes, (symbolEntry) => { Tuple <string, string> result = GenerateCode(symbolEntry, factory, outputDirectory, errorLogger, generationOptions, generatedFiles); string text = result.Item1; string filename = result.Item2; if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName) && !string.IsNullOrEmpty(text)) { lock (syntaxTrees) { syntaxTrees.Add(CSharpSyntaxTree.ParseText(text, path: filename, encoding: System.Text.UTF8Encoding.Default)); } } }); } else { string filename = string.Format(@"{0}\everything.exported.cs", outputDirectory); HashSet <string> usings = new HashSet <string>(); foreach (var symbolEntry in userTypes) { foreach (var u in symbolEntry.Usings) { usings.Add(u); } } generatedFiles.TryAdd(filename.ToLowerInvariant(), filename); using (StringWriter stringOutput = new StringWriter()) using (TextWriter masterOutput = !xmlConfig.DontSaveGeneratedCodeFiles ? new StreamWriter(filename, false /* append */, System.Text.Encoding.UTF8, 16 * 1024 * 1024) : TextWriter.Null) { foreach (var u in usings.OrderBy(s => s)) { masterOutput.WriteLine("using {0};", u); if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName)) { stringOutput.WriteLine("using {0};", u); } } masterOutput.WriteLine(); if (xmlConfig.GenerateAssemblyWithRoslyn) { stringOutput.WriteLine(); } ObjectPool <StringWriter> stringWriterPool = new ObjectPool <StringWriter>(() => new StringWriter()); Parallel.ForEach(userTypes, (symbolEntry) => { var output = stringWriterPool.GetObject(); output.GetStringBuilder().Clear(); GenerateCodeInSingleFile(output, symbolEntry, factory, errorLogger, generationOptions); string text = output.ToString(); if (!string.IsNullOrEmpty(text)) { lock (masterOutput) { masterOutput.WriteLine(text); if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName)) { stringOutput.WriteLine(text); } } } stringWriterPool.PutObject(output); }); if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName)) { syntaxTrees.Add(CSharpSyntaxTree.ParseText(stringOutput.ToString(), path: filename, encoding: UTF8Encoding.Default)); } } } logger.WriteLine(" {0}", sw.Elapsed); // Compiling the code string binFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName)) { List <MetadataReference> references = new List <MetadataReference> { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location) }; references.AddRange(xmlConfig.ReferencedAssemblies.Select(r => MetadataReference.CreateFromFile(r.Path))); foreach (var includedFile in includedFiles) { syntaxTrees.Add(CSharpSyntaxTree.ParseText(File.ReadAllText(includedFile.Path), path: includedFile.Path, encoding: System.Text.UTF8Encoding.Default)); } CSharpCompilation compilation = CSharpCompilation.Create( Path.GetFileNameWithoutExtension(xmlConfig.GeneratedAssemblyName), syntaxTrees: syntaxTrees, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, platform: Platform.X64)); logger.WriteLine("Syntax trees: {0}", syntaxTrees.Count); string dllFilename = Path.Combine(outputDirectory, xmlConfig.GeneratedAssemblyName); string pdbFilename = Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(dllFilename) + ".pdb"); using (var dllStream = new FileStream(dllFilename, FileMode.Create)) using (var pdbStream = new FileStream(pdbFilename, FileMode.Create)) { var result = compilation.Emit(dllStream, !xmlConfig.DisablePdbGeneration ? pdbStream : null); if (!result.Success) { IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); errorLogger.WriteLine("Compile errors (top 1000):"); foreach (var diagnostic in failures.Take(1000)) { errorLogger.WriteLine(diagnostic); } } else { logger.WriteLine("DLL size: {0}", dllStream.Position); logger.WriteLine("PDB size: {0}", pdbStream.Position); } } logger.WriteLine("Compiling: {0}", sw.Elapsed); } // Check whether we should generate assembly if (!xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName)) { var codeProvider = new CSharpCodeProvider(); var compilerParameters = new CompilerParameters() { IncludeDebugInformation = !xmlConfig.DisablePdbGeneration, OutputAssembly = outputDirectory + xmlConfig.GeneratedAssemblyName, }; compilerParameters.ReferencedAssemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic).Select(a => a.Location).ToArray()); //compilerParameters.ReferencedAssemblies.AddRange(referencedAssemblies); const string MicrosoftCSharpDll = "Microsoft.CSharp.dll"; if (!compilerParameters.ReferencedAssemblies.Cast <string>().Where(a => a.Contains(MicrosoftCSharpDll)).Any()) { compilerParameters.ReferencedAssemblies.Add(MicrosoftCSharpDll); } compilerParameters.ReferencedAssemblies.Add(Path.Combine(binFolder, "CsDebugScript.Engine.dll")); compilerParameters.ReferencedAssemblies.Add(Path.Combine(binFolder, "CsDebugScript.CommonUserTypes.dll")); var filesToCompile = generatedFiles.Values.Union(includedFiles.Select(f => f.Path)).ToArray(); var compileResult = codeProvider.CompileAssemblyFromFile(compilerParameters, filesToCompile); if (compileResult.Errors.Count > 0) { errorLogger.WriteLine("Compile errors (top 1000):"); foreach (CompilerError err in compileResult.Errors.Cast <CompilerError>().Take(1000)) { errorLogger.WriteLine(err); } } logger.WriteLine("Compiling: {0}", sw.Elapsed); } // Generating props file if (!string.IsNullOrEmpty(xmlConfig.GeneratedPropsFileName)) { using (TextWriter output = new StreamWriter(outputDirectory + xmlConfig.GeneratedPropsFileName, false /* append */, System.Text.Encoding.UTF8, 16 * 1024 * 1024)) { output.WriteLine(@"<?xml version=""1.0"" encoding=""utf-8""?>"); output.WriteLine(@"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"); output.WriteLine(@" <ItemGroup>"); foreach (var file in generatedFiles.Values) { output.WriteLine(@" <Compile Include=""{0}"" />", file); } output.WriteLine(@" </ItemGroup>"); output.WriteLine(@"</Project>"); } } logger.WriteLine("Total time: {0}", sw.Elapsed); }