- I build from VS2017 and the packages are downloaded and the projects
build.
- Then I nuke the packages folder.
- Then I build using MSBuild the projects fail because the packages don't
exist, they haven't been restored.
I have "download missing packages" on
The project files would have been originally created in VS 2013
The build.proj using the MSBuild task to build the solution.
<MSBuild Projects ="$(root)\src\MySolution.sln" ContinueOnError ="false" Properties="Configuration=$(Configuration)">
<Output ItemName="OutputFiles" TaskParameter="TargetOutputs"/>
</MSBuild>
My google-fu has failed me, any and all ideas will be greatfully received.
packages.config
based projects need to be restored via NuGet, not MSBuild. Visual Studio does this when requesting a build via VS. If you need to do it from command line, you need to use the command line nuget.exe
utility to restore the packages.
Only the PackageReference
way of referencing NuGet packages is integrated into MSBuild. You can switch to this format by uninstalling all NuGet packages from the project, and changing the default package management format or select the "Allow format selection on first package install" checkbox. Then you can re-add the packages (only top-level packages are needed) and make sure it does not generate a packages.config
file.
There's a few issues here:
After a restore, MSBuild has to re-evaluate the project file. When using the <MSBuild>
task inside a CI script, this only happens when a different set of properties are passed to the task. This is because the Restore generates auto-imported files in the obj\
directory that are checked for during the evaluation.
Should the restore not generate, but alter these files, this is not enough and the project has to be re-evaluated with clean xml caches. This is not possible with the <MSBuild>
task. MSBuild 15.5 has introduces a /restore
option to execute a Restore
target, then clean these caches (for which there was no API before) and execute the rest of the build as requested. Before 15.5, two separate invocations of msbuild.exe
were needed to ensure that incremental restore+builds produce the correct output.
If you want to use a CI build project with PackageReference
, the safest way is to create a build.proj
that has a restore and a build target:
<Project>
<Target Name="Restore">
<MSBuild Projects="$(root)\src\MySolution.sln" Targets="Restore" />
</Target>
<Target Name="Build">
<MSBuild Projects="$(root)\src\MySolution.sln" Targets="Build" />
</Target>
</Project>
And execute it using
msbuild /restore /t:Build build.proj
I found that calling nuget restore MySolution.sln
will restore the packages for a solution.
I put nuget.exe
in my build folder, and run restore for each solution in my source tree.
My MsBuild target to restore packages for all projects in all solutions.
<Target Name="NuGetRestore">
<ItemGroup>
<slns Include="$(MSBuildProjectDirectory)\..\**\*.sln"/>
</ItemGroup>
<Exec Command="$(MSBuildProjectDirectory)\nuget restore %(slns.Identity)"/>
</Target>
Nuget.exe
doesn't have to be in each project folder, just in the folder with build.
I also ran into the issue of MSBuild not pulling the packages. I added the path nuget.config
file using RestoreConfigFile
to the properties parameter
RestoreConfigFile=$(MSBuildStartupDirectory)\.nuget\nuget.config
and also changed the Targets value on the MSBuild task:
MSBuild Targets="Restore;Clean;Build" Projects=...
The Restore
target actually forced the pulling of the packages and the RestoreConfigFile
pointed it to my settings.