Roslyn, MSBuildWorkspace compiling a .NetStandard project referencing a .NetStandard project throws "No value for RuntimeMetadataVersion found."
Asked Answered
H

1

2

Create a solution with the following projects.

A .NetStandard2.0 project, name it "1"

A .NetStandard2.0 project, name it "2"

Add a reference of project 1 in 2

A .Net4.6.1 console project name it "3" and add the nuget Microsoft.CodeAnalysis.CSharp.Workspaces v2.7.0

Paste in the follwing code into project 3

static void Main(string[] args)
    {
        string dir = Path.Combine(Environment.CurrentDirectory, "..\\..\\..\\");

        string solutionPath = Directory.GetFiles(dir, "*.sln").First();
        var msWorkspace = MSBuildWorkspace.Create();

        Solution solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;

        DateTime date = DateTime.UtcNow;
        foreach (var project in solution.Projects.Take(2))
        {
            Compilation compilation = project.GetCompilationAsync().Result;

            using (var dllStream = new MemoryStream())
            {
                var emitResult = compilation.Emit(dllStream);
                if (emitResult.Success)
                {
                    Console.WriteLine("Success");
                }
                else
                {
                    foreach (var err in emitResult.Diagnostics)
                    {
                        Console.WriteLine($"{err.ToString()}");
                    }
                }
            }
        }
        Console.Read();
    }

executing project 3 throws the following errors for project 2, but not for project 1.

warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.

d:\test\roslyntest\2\Class1.cs(1,7): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)

d:\test\roslyntest\2\Class1.cs(5,18): error CS0518: Predefined type 'System.Object' is not defined or imported

d:\test\roslyntest\2\Class1.cs(5,18): error CS1729: 'object' does not contain a constructor that takes 0 arguments

My question. Why is it not finding the basic classes in project 2 but in project 1?

The only difference is that project 2 references another project.

What am i missing/doing wrong?

Harvestman answered 13/4, 2018 at 12:21 Comment(3)
What kind of project does project 2 reference?Kuomintang
I tried the repro you mention, but since project 2 has no dependencies, it is able to compile both. Let me know what type of project 2 references and I will take a look.Kuomintang
project 2 references project 1Harvestman
K
6

To address this, here are the steps you need to take:

  1. Reference the Microsoft.Build.Locator NuGet package.
  2. Call MSBuildLocator.RegisterDefaults(); before creating the MSBuildWorkspace
  3. Make sure that there aren't any Microsoft.Build.* assemblies in your app bin folder (see below).

With those steps I was able to correctly build the 2 projects.

This is how you can remove the files from the output folder (add this to your .csproj or use the Post Build steps in Visual Studio).

  <PropertyGroup>
    <PostBuildEvent>del "$(TargetDir)\Microsoft.Build.dll"
del "$(TargetDir)\Microsoft.Build.Framework.dll"
del "$(TargetDir)\Microsoft.Build.Tasks.Core.dll"
del "$(TargetDir)\Microsoft.Build.Utilities.Core.dll"
    </PostBuildEvent>
  </PropertyGroup>

For additional information please see: https://github.com/dotnet/roslyn/issues/26029

Kuomintang answered 17/4, 2018 at 19:47 Comment(2)
Make sure that this is at the end of the .csproj fileGalsworthy
This manual deletion of files in a postbuild step is not something I'd recommend. Instead, please consider changing your answer to use the ExcludeAssets="runtime" option as described in the official documentation.Ani

© 2022 - 2024 — McMap. All rights reserved.