dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.21k stars 1.35k forks source link

TargetFrameworks causes error when a space is in referenced project's path #8165

Open JakubFojtik opened 1 year ago

JakubFojtik commented 1 year ago

Issue Description

Simply changing the tag TargetFramework to TargetFrameworks can cause msbuild to fail to build with the error message:

error NETSDK1005: Assets file 'project\obj\project.assets.json' doesn't have a target for 'net6.0-windows'. Ensure that restore has run and that you have included 'net6.0-windows' in the TargetFrameworks for your project.

This happens solely because of a space in path of a referenced project, and only when TargetFrameworks are used (even with only one moniker).

Steps to Reproduce

Either see the attached full sample^1 with log^2 or follow the steps in an empty dir:

  1. dotnet new classlib -o net6_win
  2. dotnet new classlib -o "net6 spaced"
  3. dotnet add net6_win reference "net6 spaced"
  4. change TargetFramework to net6.0-windows in net6_win\net6_win.csproj
  5. change TargetFramework to TargetFrameworks in net6_win\net6_win.csproj //this causes the bug
  6. msbuild /restore net6_win

Expected Behavior

The projects build when the old TargetFramework tag is used, they should build with the new TargetFrameworks too.

Actual Behavior

The build fails only when there is a space on the path and when the new TargetFrameworks tag is used.

Analysis

Removing the space in the name of net6 spaced.csproj and in the project reference works around the bug.

Versions & Configurations

MSBuild version 17.4.0+18d5aef85 for .NET Framework 17.4.0.51802 happens with both net6.0 and net7.0

Attachments

benvillalobos commented 1 year ago

Team Triage: Thanks for the great bug report! In the .NET ecosystem it's unusual to have a space in your project file. The name of the project file is typically the name of the output assembly, which typically doesn't have spaces. As a result, investigating this is not likely to be a high priority.

tomupson commented 1 year ago

I'm seeing this error when multi-targeting and overwriting the AssemblyName for one of the frameworks. Interestingly this only occurs when using "dotnet msbuild" without the -restore flag. If I use either "dotnet build" or "dotnet msbuild -restore" it works fine.

Example csproj for project named "MyAssembly":

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

  <PropertyGroup>
    <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
    <Nullable>enable</Nullable>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>

  <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
    <AssemblyName>MyAssembly.NetStandard2</AssemblyName>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="AWSSDK.Extensions.NETCore.Setup" Version="3.7.2" />
    <PackageReference Include="AWSSDK.KeyManagementService" Version="3.7.101" />
    <PackageReference Include="AWSSDK.SecurityToken" Version="3.7.100.25" />
    <PackageReference Include="AwsSignatureVersion4" Version="4.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.0" />
    <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.25.0" />
    <PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.2.1" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
    <PackageReference Include="BouncyCastle.NetCore" Version="1.9.0" />
    <PackageReference Include="System.Text.Json" Version="7.0.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
    <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
  </ItemGroup>

</Project>

dotnet msbuild output:

MSBuild version 17.4.0+18d5aef85 for .NET
C:\Program Files\dotnet\sdk\7.0.100\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(267,5): error NETSDK1004: Assets file 'C:\Example\MyAssembly\obj\project.assets.json' not found. Run a NuGet package restore to generate this file. [C:\Example\MyAssembly\MyAssembly.csproj::TargetFramework=netstandard2.0]
C:\Program Files\dotnet\sdk\7.0.100\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(267,5): error NETSDK1004: Assets file 'C:\Example\MyAssembly\obj\project.assets.json' not found. Run a NuGet package restore to generate this file. [C:\Example\MyAssembly\MyAssembly.csproj::TargetFramework=net6.0]

dotnet build output:

MSBuild version 17.4.0+18d5aef85 for .NET
  Determining projects to restore...
  Restored C:\Example\MyAssembly\MyAssembly.csproj (in 830 ms).
  2 of 3 projects are up-to-date for restore.
  MyAssembly -> C:\Example\MyAssembly\bin\Debug\netstandard2.0\MyAssembly.NetStandard2.dll
  MyAssembly -> C:\Example\MyAssembly\bin\Debug\net6.0\MyAssembly.dll

Build succeeded.

    2 Warning(s)
    0 Error(s)

Time Elapsed 00:00:05.42

In both cases I am running with clean bin/obj folders

JakubFojtik commented 1 year ago

@tomupson Unless I'm wrong your error seems warranted to me. Without running restore you get an error: Run a NuGet package restore. The missing Target would then be caused by the whole file missing.

tomupson commented 1 year ago

@JakubFojtik Upon further investigation, I think the problem is within the restore itself. project.assets.json contains this:

"logs": [
    {
      "code": "NU1105",
      "level": "Error",
      "message": "Unable to read project information for 'MyAssembly': Sequence contains more than one element"
    }
  ]