0

I'm currently trying to compile a solution during runtime execution of my own program. This solution is user defined and must have support for any number of projects and in these any nuget dependency the user wants to add. For example, a solution with a singular C# project that is defined like this:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="xunit" Version="2.4.1" />
  </ItemGroup>
</Project>

should compile if the user decides to use xunit or Newtonsoft.Json classes in their code.

I am currently compiling the projects with the following steps:

using var workspace = MSBuildWorkspace.Create();
var solution = await workspace.OpenSolutionAsync(solutionPath, cancellationToken: token);
foreach (var project in solution.Projects)
{
    var compilation = await project.GetCompilationAsync(token);
    // handle compilation
}

The issue I'm facing is that it seems that MSBuild is not resolving all nuget references. This is quite odd because Newtonsoft.Json can be used, and adding references to dlls using hint paths does work as well. However, xunit is never resolved and the compilation fails with the message that the namespace Xunit cannot be found. compilation.References only shows System references as well as for some reason always Newtonsoft.Json, even if it's not referenced. workspace.Diagnostics is empty and I'm at a loss.

How can I get MSBuild to include the nuget packages my users will reference?

6
  • What is the exception you get ? I tried to reproduce it but it worked. Do you have a minimal reproducible example? Commented Feb 20, 2023 at 21:49
  • Does this answer your question? Roslyn fails to compile a trivial project Commented Feb 20, 2023 at 21:54
  • @Carlos Unfortunately the small code from above with that csproj file is my minimal example. This does exactly reproduce my issue for me. Which versions do you use? Currently I am using Version 4.2.0 for the Microsoft.CodeAnalysis packages, 1.4.1 for the locator and 4.7.0 for Microsoft.CSharp Commented Feb 20, 2023 at 23:45
  • After running dotnet build manually on the project's solution it builds fine with my code Commented Feb 20, 2023 at 23:52
  • 1
    Where exactly does it fail? I don't see Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults(), are you using it? where are the Microsoft.CodeAnalysis packages included ? Commented Feb 21, 2023 at 1:58

1 Answer 1

1

The issue is that Roslyn does not restore your projects when you call GetCompilationAsync. Unfortunately, there is no easy way to restore your projects using the MSBuildWorkspace APIs. Fortunately though, the Microsoft.Build NuGet package is the answer.

Make sure to call MSBuildLocator from a different function where you first use classes defined in the Microsoft.Build.* dlls or you will get a FileNotFoundException because the DLLs are not yet findable for your program. After that I used SolutionFile.Parse, iterated through every project in there and used code "heavily inspired" by this class from Roslyn in order to invoke MSBuild with the target step of Restore. After doing that I created my MSBuildWorkspace, opened the solution and now the compilation does succeed every time there was an update to the project's dependencies.

If anyone knows of an easier way to do this, let me know

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.