dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.92k stars 4.02k forks source link

How to use MSBuildWorkspace on Ubuntu #35766

Open abhijitparkhi1983 opened 5 years ago

abhijitparkhi1983 commented 5 years ago

Version Used: .NET CLI version 2.8.2

Steps to Reproduce:

  1. I am trying to Analyze each document of a .csproj. For this purpose, i am using various API's provided by Roslyn Compiler.
  2. I already had an application developed in .NET Framework which utilizes the MSBuildWorkspace class for loading the .csproj files and then their respective .cs files using the following code:
    
    using (var workspace = MSBuildWorkspace.Create())
    {
      Project currentProject = workspace.OpenProjectAsync(projectPath).Result;
       workspace.LoadMetadataForReferencedProjects = true;
       if (currentProject.HasDocuments)
       {
           foreach(Document document in currentProject.Documents)
           {
                  var name = document.Name;
            }
        }
    }


3. The above code works well on a Windows machine for both .NET Framework based .csproj's and .NET Core based .csrpoj's input projects.

4. I had a new requirement for supporting the same application on Ubuntu 16.4 environment. As per my research on different forums related to Roslyn, writing the above .NET Framework based code using .NET Core can help in running the application on Ubuntu as well . But obviously, .NET Core does not support MSBuildWorkspace out of the box is what the research suggested.

5. How can i use **MSBuildWorkspace**  on Ubuntu OR What is the alternative for using **MSBuildWorkspace** ?
jinujoseph commented 5 years ago

cc @DustinCampbell , @JoeRobich

JoeRobich commented 5 years ago

Hi @abhijitparkhi1983,

The dotnet-format global tool uses MSBuildWorkspace on .NET Core and you can too. One thing to note is that all project types may not load with .NET Core. Full framework ASP.NET project targets are not part of the .NET Core MSBuild.

dotnet-format uses MSBuildLocator (https://www.nuget.org/packages/Microsoft.Build.Locator/) to ensure that the MSBuild libraries are loaded in memory.

https://github.com/dotnet/format/blob/95d54828e05357b342ec794b03d6ff2e0778d0ac/src/Program.cs#L79-L89

One thing to note is that we do register an assembly resolver to ensure the proper version of msbuild dependencies are loaded. (https://github.com/dotnet/format/blob/master/src/MSBuild/LooseVersionAssemblyLoader.cs)

Then we use MSBuildWorkspace just as you have.

https://github.com/dotnet/format/blob/95d54828e05357b342ec794b03d6ff2e0778d0ac/src/CodeFormatter.cs#L108-L139

Hope that helps get you started, -Joey

abhijitparkhi1983 commented 5 years ago

Thanks @JoeRobich for sharing the information.

When i make the necessary changes to the code as suggested by you, i get following runtime error :

Could not load file or assembly 'System.Runtime.Loader, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058) I am debugging this error through Visual Studios 2017 and the project version is .NET Framework 4.7.2. I have checked that System.Runtime.Loader .dll is been refereed in the project. Looks like i am missing something very basic. It will be helpful if you can guide me on the same

abhijitparkhi1983 commented 5 years ago

Also, is there any way to support MSBuildWorkspace in .NET Core project ? If not, whats an alternative for it?

JoeRobich commented 5 years ago

the project version is .NET Framework 4.7.2.

@abhijitparkhi1983 AssemblyLoadContext is only available in .NET Core. Starting with version 3.0.0 of Microsoft.CodeAnalysis.Workspaces.MSBuild the MSBuildWorkspace supports .NET Core 2.1 or higher.

abhijitparkhi1983 commented 5 years ago

Thanks @JoeRobich I had to upgrade my code base to Visual Studios 2019 and migrated code from .NET framework to .NET Core 2.1 code. This enabled me to add nuget package reference to Microsoft.CodeAnalysis.MSBuild. Now I am able to use MSBuildWorkspace for .NET core and .NET Framework based applications on Windows. Now I will be testing the same on Linux platform.

Need one more input : I have a mix code based on .NET Core and .NET Framework and i want to use MSBuildWorkspace for both these code bases on Linux Platform which will, i think, wont work for .NET Framework code base (assuming .net framework based code wont work on linux as it will not have .net framework installed on the linux machine). Is there any way in which MSBuildWorkspace can be used for both .NET Framework and .NET Core on Linux ?

JoeRobich commented 5 years ago

@abhijitparkhi1983 It is good to hear that you are making progress.

Is there any way in which MSBuildWorkspace can be used for both .NET Framework and .NET Core on Linux ?

Not with the .NET Core version of MSBuildWorkspace, since the Core version of MSBuild doesn't know about full framework build tasks and targets. You could possibly use Mono and the .NET Framework build of your tool, but I don't have any experience in that scenario.