Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Sequence contains no elements" exception during msbuild after restore - .NET 7 #154

Open
erikmav opened this issue Dec 13, 2022 · 8 comments

Comments

@erikmav
Copy link

erikmav commented Dec 13, 2022

After converting a fully working .NET 6 repo to .NET 7 and VS 17.4.2, command line builds started failing with exceptions from NuGet.BuildTasks. This occurs on Windows only, and only within .vcxproj projects. The repo uses Directory.Packages.props global packages. It does not occur if dotnet restore is used (see below), just when restoring with msbuild /t:Restore. It usually does not happen in Visual Studio. Our ADO based build pipeline does not repro this, but it uses dotnet restore.

Repro sequence in our repo:

  • git clean -xfd at root
  • msbuild /t:Restore (works successfully)
  • msbuild /p:Configuration=Debug

Interestingly, with the same exact machine, dotnet restore instead of msbuild /t:Restore does not reproduce the problem.

Exact MSBuild version from console output:

msbuild /t:Restore
MSBuild version 17.4.0+18d5aef85 for .NET Framework

The exception stack:

C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\NuGet\17.0\Microsoft.NuGet.targets(198,5): error : Sequence contains no elements [C:\myrepo\src\\MyUnmanaged\exe\MyUnmanaged.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\NuGet\17.0\Microsoft.NuGet.targets(198,5): error :    at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) [C:\myrepo\src\\MyUnmanaged\exe\MyUnmanaged.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\NuGet\17.0\Microsoft.NuGet.targets(198,5): error :    at Microsoft.NuGet.Build.Tasks.ResolveNuGetPackageAssets.GiveErrorForMissingFramework() [C:\myrepo\src\\MyUnmanaged\exe\MyUnmanaged.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\NuGet\17.0\Microsoft.NuGet.targets(198,5): error :    at Microsoft.NuGet.Build.Tasks.ResolveNuGetPackageAssets.GetTargetOrAttemptFallback(JObject lockFile, Boolean needsRuntimeIdentifier) [C:\myrepo\src\\MyUnmanaged\exe\MyUnmanaged.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\NuGet\17.0\Microsoft.NuGet.targets(198,5): error :    at Microsoft.NuGet.Build.Tasks.ResolveNuGetPackageAssets.GetReferences(JObject lockFile) [C:\myrepo\src\\MyUnmanaged\exe\MyUnmanaged.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\NuGet\17.0\Microsoft.NuGet.targets(198,5): error :    at Microsoft.NuGet.Build.Tasks.ResolveNuGetPackageAssets.ExecuteCore() [C:\myrepo\src\\MyUnmanaged\exe\MyUnmanaged.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\NuGet\17.0\Microsoft.NuGet.targets(198,5): error :    at Microsoft.NuGet.Build.Tasks.ResolveNuGetPackageAssets.Execute() [C:\myrepo\src\\MyUnmanaged\exe\MyUnmanaged.vcxproj]
@erikmav
Copy link
Author

erikmav commented Dec 13, 2022

More info: dotnet restore kicks out this warning, hence it is not trying a restore in the vcxproj:

C:\myrepo\src\MyUnmanaged\exe\MyUnmanaged.vcxproj : warning NU1503: Skipping restore for project 'C:\myrepo\src\myUnmanaged\exe\MyUnmanaged.vcxproj'. The project file may be invalid or missing targets required for restore. [C:\myrepo\repo.sln]

Whereas msbuild /t:Restore generates a project.assets.json for the vcxproj.

@erikmav
Copy link
Author

erikmav commented Dec 13, 2022

A project.assets.json is actually the desired result, as there is a global package reference in Directory.Packages.props for an MSBuild plugin that needs to be applied to all projects.

@erikmav
Copy link
Author

erikmav commented Dec 13, 2022

Verified still present in just-released VS 17.4.3 (MSBuild version 17.4.1+9a89d02ff for .NET Framework)

@erikmav
Copy link
Author

erikmav commented Dec 20, 2022

For future reference on the NU1503 error under dotnet restore: vcxproj restore using dotnet restore runs into a Windows MSBuild.exe specific chicken-and-egg problem involving the VCTargetsPath macro definition. It is not set at all during a dotnet restore, only in MSBuild.exe /t:Restore, as its main definition is in MSBuild.exe.config next to MSBuild.exe. See here for the code. dotnet does not have an equivalent property definition. To get global packages to restore in .vcxproj files I had to add this EnsureVCTargetsPathSetForDotnetRestore.props file to my repo, then include it at the top of each .vcxproj:

<!-- Must be first import for .vcxproj files. On Windows, $(VCTargetsPath) is needed to bootstrap common and C++
     .props and .targets files but it's only set in an MSBuild.exe environment via
     MSBuild.exe.config (see https://github.com/dotnet/msbuild/blob/main/src/MSBuild/app.amd64.config#L194 ).
     'dotnet restore' does not invoke MSBuild.exe and there is no MSBuild.dll.config with this property,
     hence VCTargetsPath is never set, making it impossible to bootstrap C++ imports.
     Additionally in dotnet restore $(MSBuildExtensionsPath32) is not the same as for MSBuild.exe.
     Set the default value to what MSBuild would have done. -->
<Project>
  <PropertyGroup>
    <VCTargetsPath Condition=" '$(OS)' == 'Windows_NT' and '$(VCTargetsPath)'=='' ">$(ProgramFiles)\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\</VCTargetsPath>
  </PropertyGroup>
</Project>

@smaine
Copy link

smaine commented Feb 16, 2023

I'm hitting this same problem and would love to see this get fixed!

@erikmav
Copy link
Author

erikmav commented Sep 20, 2023

Found one workaround from https://github.com/japj/CppWithNuGetPackageReference/blob/master/Directory.Build.props that adds a nuget fallback. When I set this in Directory.Build.props globally things work once again:

  <!-- Enable NuGet TargetMonikers fallback to vcxproj. https://github.com/japj/CppWithNuGetPackageReference/blob/master/Directory.Build.props -->
  <PropertyGroup>
    <_NuGetTargetFallbackMoniker>$(_NuGetTargetFallbackMoniker);native,Version=v0.0</_NuGetTargetFallbackMoniker>
  </PropertyGroup>

@Arcnor
Copy link

Arcnor commented Jan 3, 2024

Not sure if this will help anybody until this issue is fixed, but got the same annoying problem on a CMake mixed CXX + C# project. My Directory.Build.props ended up containing:

<PropertyGroup>
	<_NuGetTargetFallbackMoniker>$(_NuGetTargetFallbackMoniker);net8.0</_NuGetTargetFallbackMoniker>
	<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
</PropertyGroup>

Obviously your RuntimeIdentifiers might change, but having netX.0 (instead of native,Version=v0.0) & the RuntimeIdentifiers part made everything work.

@chrarnoldus
Copy link

In case it helps someone, I got this error because multiple projects (generated by CMake) were sharing the same 'obj' folder. I could work around it by creating a Directory.Build.props file ensuring the obj-path for each project is unique:

<Project>
    <PropertyGroup>
        <BaseIntermediateOutputPath>$(MSBuildProjectDirectory)\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
    </PropertyGroup>
</Project>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants