KirillOsenkov / MSBuildStructuredLog

A logger for MSBuild that records a structured representation of executed targets, tasks, property and item values.
MIT License
1.41k stars 188 forks source link

System.IO.FileNotFoundException : Could not load file or assembly 'Microsoft.Build.Framework, Version=15.1.0.0 #692

Closed pascalberger closed 7 months ago

pascalberger commented 11 months ago

I'm referencing MSBuildStructuredLogger 2.1.820 in an assembly which is multi-targeted to net6.0 and net7.0. Unit tests on net.7.0 work fine, but tests on net6.0 fail with the following error:

System.IO.FileNotFoundException : Could not load file or assembly 'Microsoft.Build.Framework, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.

Can be reproduced on the release/3.0 branch of https://github.com/cake-contrib/Cake.Issues.MsBuild/tree/3.0.0

Is there anything I can do to get the tests running under net6.0?

pascalberger commented 11 months ago

Tests are running successfully under net6.0 and net7.0 with MsBuildStructuredLogger 2.1.815

KirillOsenkov commented 11 months ago

Hmm, when I build your repo locally, the .dll does get copied:

image

Can you do the same on your machine (after you git clean -xdff and rebuild), and see whether the .dll is in the net6.0 directory?

KirillOsenkov commented 11 months ago

I did make this change: https://github.com/KirillOsenkov/MSBuildStructuredLog/commit/260c84be7368d04ef989d2bc9157a068d2886d21

and this one: https://github.com/KirillOsenkov/MSBuildStructuredLog/commit/49d1c91a417dcb41f965b53075fba4a5f8c4b113

What broke it is likely this one: https://github.com/KirillOsenkov/MSBuildStructuredLog/commit/4e3d4516087c84054f59d469246335aa773ef602

bdukes commented 8 months ago

We have the same error in our .NET 6 build after upgrading from 2.1.820 to 2.1.858 https://github.com/dnnsoftware/Dnn.Platform/pull/5855

KirillOsenkov commented 8 months ago

@bdukes are you able to reproduce this locally on your own machine? Try changing 820 to 858 locally as in the PR, then git clean -xdff and rebuild.

I did it using msbuild /r /m /bl build\Build.csproj

and Microsoft.Build.Framework.dll does get copied to output: image

If I'm able to reproduce this locally I can certainly help. But right now I don't know which process fails, it's probably missing Microsoft.Build.Framework.dll in the output directory.

To be able to investigate further, I need to have the exact local repro steps that I can try. I need to know which process is running, from what directory, and whether that directory contains Microsoft.Build.Framework.dll.

I suspect that if you target net7.0 then it will fix itself. I've seen the .dll get copied for 7.0, but not copied for 6.0.

KirillOsenkov commented 8 months ago

I filed an issue here because I couldn't build Dnn: https://github.com/dnnsoftware/Dnn.Platform/issues/5858

KirillOsenkov commented 8 months ago

I got unblocked with Dnn, so I investigated some more.

The build fails because C:\Dnn.Platform\Build\bin\Debug\net6.0\Microsoft.Build.Framework.dll is version 16.10, which does not have the type TargetSkipReason.

That file is version 16.10, because of this set of PackageReferences: https://github.com/dnnsoftware/Dnn.Platform/blob/dd0e72d006711064fb38133f0b5f541291d74c5b/Build/Build.csproj#L17-L27

It is being copied from Cake.Issues.MSBuild: image

Although MSBuild.StructuredLogger does declare a dependency on Microsoft.Build.Framework 17.5.0, the layout of the package only includes the .dll for net7.0 and net472: image

This means that Build.csproj is targeting net6.0 and it doesn't receive the latest version of Microsoft.Build.Framework.dll.

I'll try to submit a workaround PR for this soonish.

KirillOsenkov commented 8 months ago

Oh, and the TargetSkipReason type is expected by the new version of MSBuild.StructuredLogger.dll.

We probably need to bump Cake to both MSBuild 17.5 as well as the latest StructuredLogger, then bump Dnn to the latest Cake and StructuredLogger, then it'll all resolve itself.

We'll still need a workaround to force the 17.5 version of Microsoft.Build.Framework.dll to get copied to output, because Dnn is still targeting net6.0.

pascalberger commented 8 months ago

We probably need to bump Cake to both MSBuild 17.5 as well as the latest StructuredLogger, then bump Dnn to the latest Cake and StructuredLogger, then it'll all resolve itself.

Thanks for the investigation @KirillOsenkov. I'm not sure I understand the issue correctly though.

You mentioned the Microsoft.Build.Framework.dll dependency comes from Cake.Issues.MsBuild (https://github.com/cake-contrib/Cake.Issues.MsBuild/) which is an addin to Cake, not Cake itself.

Cake.Issues.MsBuild version 3.0.0 which is used by DNN is built against MsBuildStructuredLogger 2.1.815. It also ships with the corresponding version of MsBuildStructuredLogger.dll, Microsoft.Build.Framework.dll and Microsoft.Build.Utilities.Core.dll (see https://github.com/cake-contrib/Cake.Issues.MsBuild/blob/develop/nuspec/nuget/Cake.Issues.MsBuild.nuspec#L34C1-L36C81) for net6.0 and net7.0 (which are the two TFM supported by Cake itself).

One issue I see here is that DNN additionally references MsBuildStructuredLogger directly in the build (https://github.com/dnnsoftware/Dnn.Platform/blob/dd0e72d006711064fb38133f0b5f541291d74c5b/Build/Build.csproj#L27), which will bring in MsBuildStructuredLogger.dll, Microsoft.Build.Framework.dll and Microsoft.Build.Utilities.Core.dll.

@bdukes What's the reason you're referencing MsBuildStructuredLogger directly?

The reason why Cake.Issues.MsBuild ships with the dependencies instead of referencing them is for Cake Scripting runner to avoid versioning conflicts. In case of DNN Cake Frosting runner is used, wich is a standard .NET console application and where I could provide a different version of the assembly which would come with a reference to MsBuildStructuredLogger so that dependencies can be resolved at build time.

Update of MsBuildStructuredLogger to a newer version is actually blocked by this issue (see also https://github.com/cake-contrib/Cake.Issues.MsBuild/pull/332 and https://dev.azure.com/cake-contrib/Cake.Issues.MsBuild/_build/results?buildId=11539&view=logs&j=2d2b3007-3c5c-5840-9bb0-2b1ea49925f3&t=c37637b8-ed57-5a02-c556-da2855a7e2d3&l=482 for the failing test case under net6.0 with newer version).

bdukes commented 8 months ago

@pascalberger Thanks, I had forgotten that we'd manually added that reference and probably don't need it anymore. At one time, there was a mismatch between the version of the binary log that MSBuild produced and what Cake.Issues.MsBuild supported, so we were manually reading and reporting issues. Once Cake.Issues.MsBuild updated, we didn't remove the direct reference.

KirillOsenkov commented 8 months ago

@pascalberger I've made a sample of how to target net6.0 and make sure Microsoft.Build.Framework.dll and Microsoft.Build.Tasks.Core.dll get copied to output:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MSBuild.StructuredLogger" Version="2.1.858" />
    <PackageReference Include="Microsoft.Build.Framework" Version="17.5.0" ExcludeAssets="all" PrivateAssets="all" GeneratePathProperty="true" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.5.0" ExcludeAssets="all" PrivateAssets="all" GeneratePathProperty="true" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="$(PkgMicrosoft_Build_Framework)\lib\net472\Microsoft.Build.Framework.dll" />
    <Reference Include="$(PkgMicrosoft_Build_Utilities_Core)\lib\net472\Microsoft.Build.Utilities.Core.dll" />
  </ItemGroup>

</Project>

You only need this for net6.0, not for net7.0.

It is unfortunate how the Microsoft.Build.Framework Nuget package is designed, it has the lib folder with net7.0 and net472, and the ref folder with netstandard2.0. So you can reference MSBuild but it won't get copied to output if you're targeting .NET core earlier than net7.0.

Let me know if that helps.

KirillOsenkov commented 7 months ago

Is anyone here still blocked or needs any help? Otherwise I'll close the issue. The problem is that you need to make sure that the right Microsoft.Build.Framework.dll ends up in the same directory from where your assembly is.

pascalberger commented 7 months ago

@KirillOsenkov Sorry, was still on my todo list to test your fix.

Did it now and it indeed was the issue with the missing assemblies. The original issue I had reported has been resolved by this.

Thank you very much ❤️