I have a piece of software that generates code for a C# project based on user actions. I would like to create a GUI to automatically compile the solution so I don't have to load up Visual Studio just to trigger a recompile.
I've been looking for a chance to play with Roslyn a bit and decided to try and use Roslyn instead of msbuild to do this. Unfortunately, I can't seem to find any good resources on using Roslyn in this fashion.
Can anyone point me in the right direction?
Step 1: Open turbo C IDE(Integrated Development Environment), click on File and then click on New. Step 2: Write the C program code. Step 3: Click on Compile or press Alt + F9 to compile the code. Step 4: Click on Run or press Ctrl + F9 to run the code.
Run the gcc command to compile your C program. The syntax you'll use is gcc filename. c -o filename.exe . This compiles the program and makes it executable.
Type "cl filename. c" (without quotes) and press the "Enter" key to compile the code page. The C file is compiled into an executable (EXE) file named "filename.exe."
C is a mid-level language and it needs a compiler to convert it into an executable code so that the program can be run on our machine.
You can load the solution by using Roslyn.Services.Workspace.LoadSolution
. Once you have done so, you need to go through each of the projects in dependency order, get the Compilation
for the project and call Emit
on it.
You can get the compilations in dependency order with code like below. (Yes, I know that having to cast to IHaveWorkspaceServices sucks. It'll be better in the next public release, I promise).
using Roslyn.Services; using Roslyn.Services.Host; using System; using System.Collections.Generic; using System.IO; class Program { static void Main(string[] args) { var solution = Solution.Create(SolutionId.CreateNewId()).AddCSharpProject("Foo", "Foo").Solution; var workspaceServices = (IHaveWorkspaceServices)solution; var projectDependencyService = workspaceServices.WorkspaceServices.GetService<IProjectDependencyService>(); var assemblies = new List<Stream>(); foreach (var projectId in projectDependencyService.GetDependencyGraph(solution).GetTopologicallySortedProjects()) { using (var stream = new MemoryStream()) { solution.GetProject(projectId).GetCompilation().Emit(stream); assemblies.Add(stream); } } } }
Note1: LoadSolution
still does use msbuild under the covers to parse the .csproj files and determine the files/references/compiler options.
Note2: As Roslyn is not yet language complete, there will likely be projects that don't compile successfully when you attempt this.
I also wanted to compile a full solution on the fly. Building from Kevin Pilch-Bisson's answer and Josh E's comment, I wrote code to compile itself and write it to files.
Software Used
Visual Studio Community 2015 Update 1
Microsoft.CodeAnalysis v1.1.0.0 (Installed using Package Manager Console with command Install-Package Microsoft.CodeAnalysis
).
Code
using System; using System.Collections.Generic; using System.IO; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.MSBuild; namespace Roslyn.TryItOut { class Program { static void Main(string[] args) { string solutionUrl = "C:\\Dev\\Roslyn.TryItOut\\Roslyn.TryItOut.sln"; string outputDir = "C:\\Dev\\Roslyn.TryItOut\\output"; if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } bool success = CompileSolution(solutionUrl, outputDir); if (success) { Console.WriteLine("Compilation completed successfully."); Console.WriteLine("Output directory:"); Console.WriteLine(outputDir); } else { Console.WriteLine("Compilation failed."); } Console.WriteLine("Press the any key to exit."); Console.ReadKey(); } private static bool CompileSolution(string solutionUrl, string outputDir) { bool success = true; MSBuildWorkspace workspace = MSBuildWorkspace.Create(); Solution solution = workspace.OpenSolutionAsync(solutionUrl).Result; ProjectDependencyGraph projectGraph = solution.GetProjectDependencyGraph(); Dictionary<string, Stream> assemblies = new Dictionary<string, Stream>(); foreach (ProjectId projectId in projectGraph.GetTopologicallySortedProjects()) { Compilation projectCompilation = solution.GetProject(projectId).GetCompilationAsync().Result; if (null != projectCompilation && !string.IsNullOrEmpty(projectCompilation.AssemblyName)) { using (var stream = new MemoryStream()) { EmitResult result = projectCompilation.Emit(stream); if (result.Success) { string fileName = string.Format("{0}.dll", projectCompilation.AssemblyName); using (FileStream file = File.Create(outputDir + '\\' + fileName)) { stream.Seek(0, SeekOrigin.Begin); stream.CopyTo(file); } } else { success = false; } } } else { success = false; } } return success; } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With