C
C#16mo ago
Byron

✅ dotnet Restore and Targets in NuGet packages not found until second build

Hey folks, I have a NoTargets project file which contains logic for running our Ci/Cd. This file has a series of functions in there for build automation and running locally. It has logic for using the NuGet package GitVersion which is pulled in as a project reference.
<Project Sdk="Microsoft.Build.NoTargets/3.7.0">
<ItemGroup>
<PackageReference Include="GitVersion.MsBuild" Version="5.10.3"/>
</ItemGroup>
<Project Sdk="Microsoft.Build.NoTargets/3.7.0">
<ItemGroup>
<PackageReference Include="GitVersion.MsBuild" Version="5.10.3"/>
</ItemGroup>
Then my custom target has a dependency on a target defined within that package called GetVersion https://github.com/GitTools/GitVersion/blob/main/src/GitVersion.MsBuild/msbuild/tools/GitVersion.MsBuild.targets#L24. The target looks like this
<Target Name="__GenerateSharedGitAssemblyInfo" DependsOnTargets="WriteGitShaHash;GetVersion">
<!-- other stuff -->
</Target>
<Target Name="__GenerateSharedGitAssemblyInfo" DependsOnTargets="WriteGitShaHash;GetVersion">
<!-- other stuff -->
</Target>
The solution I am working with has 50+ projects which all need to be versioned so instead of running gitversion per assembly, I run it once and cache it with incremental building by sharing a single generated C# class. Each project calls into the build script using the MSBuild method to make sure the shared class in generated. It looks like this
<MSBuild Projects="$(MSBuildThisFileDirectory)Build.targets" Targets="Restore;GenerateSharedGitAssemblyInfo"/>
<MSBuild Projects="$(MSBuildThisFileDirectory)Build.targets" Targets="Restore;GenerateSharedGitAssemblyInfo"/>
The problem is that Restore will restore the packages for Build.targets however the targets defined in NuGet packages are not loaded into the current context, so they fail to resolve. The user has to build twice. Is there a simple way to force them to be resolved?
GitHub
GitVersion/src/GitVersion.MsBuild/msbuild/tools/GitVersion.MsBuild....
From git log to SemVer in no time. Contribute to GitTools/GitVersion development by creating an account on GitHub.
7 Replies
Byron
ByronOP16mo ago
I have attempted to do the build in two steps
<MSBuild Projects="$(MSBuildThisFileDirectory)Build.targets" Targets="Restore"/>
<MSBuild Projects="$(MSBuildThisFileDirectory)Build.targets" Targets="GenerateSharedGitAssemblyInfo"/>
<MSBuild Projects="$(MSBuildThisFileDirectory)Build.targets" Targets="Restore"/>
<MSBuild Projects="$(MSBuildThisFileDirectory)Build.targets" Targets="GenerateSharedGitAssemblyInfo"/>
This however still fails. It should be noted I must use DependsOnTargets because GitVersion task exports properties which I need access to later in the script. Using the MSBbuild Task there are not avaiable
Accord
Accord16mo ago
Looks like nothing has happened here. I will mark this as stale and this post will be archived until there is new activity.
reflectronic
reflectronic16mo ago
this is sort of expected https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#restoring-and-building-with-one-msbuild-command
Due to the fact that NuGet can restore packages that bring down MSBuild targets and props, the restore and build evaluations are run with different global properties. This means that the following will have an unpredictable and often incorrect behavior.
msbuild -t:restore,build
msbuild -t:restore,build
Instead the recommended approach is:
msbuild -t:build -restore
msbuild -t:build -restore
The same logic applies to other targets similar to build.
reflectronic
reflectronic16mo ago
of course, this isn't exactly what you have, but the problem is similar: because MSBuild aggressively caches project parses/evaluations/imports, if Restore happens in the same invocation as the rest of your build, targets pulled in from your packages won't reliably load. there is some more nuanced discussion here: https://github.com/dotnet/msbuild/issues/2811
GitHub
MSBuild-task equivalent of "msbuild.exe /restore /t:Target" · Issue...
https://github.com/Microsoft/msbuild/pull/2414 added support for msbuild /restore /t:Target which executes /t:Restore in a new build context before invoking /t:Target. Is it possible to perform the...
reflectronic
reflectronic16mo ago
the only way to work around this is to trigger a restore using msbuild /r or dotnet restore or whatever before you msbuild or dotnet build. the caching means that it will not work any other way
Accord
Accord16mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Byron
ByronOP16mo ago
Thanks for chiming in, I figured I was a bit out of luck with what I was trying to do
Want results from more Discord servers?
Add your server