I'd like to have an MSBuild target that runs before a restore operation. Also this target should be triggered by both CLI and Visual Studio. Probably a post restore target would be good too.
I would use this to extend the restore logical operation to consume other package sources that are not supported by NuGet.
According to this documentation https://docs.microsoft.com/en-us/nuget/schema/msbuild-targets#target-build-order there should be one.
As discussed in dotnet/cli#5683 and #4634 there is a pre restore target that is private (_GenerateRestoreProjectSpec
) but is not triggered by Visual Studio.
Edit:
Use CollectPackageReferences
as per NuGet.Targets
@davkean any ideas on how we could run targets from Visual Studio that are set to run before restore?
MSBuild has extensibility built into it. So you can add an MSBuild Target that runs before Restore by putting the following in your MSBuild .proj file (or a .targets file imported by the .proj):
<Target Name="DoSomethingBeforeRestore"
BeforeTargets="Restore">
<Message Text="Got here before Restore!" Importance="high" />
</Target>
outputs:
PS F:\DotNetTest> dotnet restore .\ProjectB\
Got here before Restore!
Restoring packages for F:\DotNetTest\ProjectB\ProjectB.csproj...
Lock file has not changed. Skipping lock file write. Path: F:\DotNetTest\ProjectB\obj\project.assets.json
Restore completed in 366.29 ms for F:\DotNetTest\ProjectB\ProjectB.csproj.
You can also use AfterTargets
to do something after Restore.
@eerhardt As discussed in the dotnet cli issue, this did not work with the target Restore but had to use _GenerateRestoreProjectSpec. If this got fixed in the mean time, this is good. But still the issue is that Visual Studio does not get the "Got here before Restore!".
@eerhardt that still does not work for dotnet restore
on the solution.
Restore is not currently the correct target but we should make that work. We should mimize the target differences between command-line and VS.
Currently, the CollectPackageReferences
target is used to get the package references to restore in VS. So you can do BeforeTargets="Restore;CollectPackageReferences"
to run before restore in both VS and the command line.
It would be good to have a single target that works for building projects from the command line, building solutions from the command line, and building in VS.
@dsplaisted I tried the CollectPackageReferences
target as a before-dependency but it works more like a post-restore rather than a pre-restore target.
What I do to test it in VS is use the context menu of the solution to do "Restore NuGet Packages". The log from the Package Manager in VS Output Window shows that it is restoring the packages and that it finished. A few seconds later, my target completes. Unfortunately the log of the Package Manager is very scarce and does not seem to be affected by the MSBuild verbosity and I am not able to understand what is really happening. My custom target produces a file and this is how I know that it has completed.
To summarize, a custom target that has a BeforeTargets=CollectPackageReferences
completes a few seconds after the log in VS reported that the restore operation has completed. If the target fails that does not fails the Restore operation either.
As far as I understand, with the latest preview of dotnet cli, the restore operation is implicit, that is, you don't need to do a restore before a build operation. Is that implicit restore running as an MSBuild target?
Is there going to be a way to do a pre-restore target that would be triggered by this implicit restore?
don't believe we've yet addressed this issue, even with the new noop restore work in NuGet 4.3 (shipping in VS 2017 15.3).
Putting in 4.5 release for consideration on our backlog. Would love to get this kind of scenario solved.
@nkolev92 @emgarten
I would like to see this happen also. I think to solve this restore will need to add its own target that then runs before or after CollectPackageReferences to allow this to get hit in VS. From the command line the CollectPackageReferences target is not there for all project types, so we cannot rely on only that target.
It should be a relatively simple fix, it just needs a good name and someone to try it out.
We should push CollectPackageReferences into NuGet.
We should push CollectPackageReferences into NuGet.
That's a good idea, is it part of the NETCore SDK currently?
Thanks @davkean! It looks like that could be copied to NuGet's targets, either the SDK or NuGet would override the other, but the result would be the same. That would make this much easier.
With this approach, would it be possible to inject new PackageRefence items in that target?
The use case is - have custom tooling that calculates the PackageReference items and creates them at a time when the Restore can later see them.
@atanasa that should be possible.
Any idea when this would be public? I guess this is not available in dotnet cli 2.0?
@emgarten all targets that consume PackageReference items should call into this CollectPackageRefereces target, including the Publish build targets.
I've hit the case where target _ComputeExcludeFromPublishPackageReference would be build but the CollectPackageRefereces target is not called thus it does not consider all references. I've worked around this by running the "collect" target before the PrepareForPublish.
For NuGet command line restore CollectPackageReferences is the only method used to get PackageReference items. Fixed with: https://github.com/NuGet/NuGet.Client/pull/1615
@atanasa I'm not familiar with _ComputeExcludeFromPublishPackageReference
would you log an issue on the repository where that target lives?
The NuGet restore changes will be part of 15.4 if it still makes it in. Otherwise 15.5.
Does this also provide a target that VS calls before restore?
Registering my target to run before CollectPackageRefereces;_GenerateRestoreProjectSpec; works well for nuget restore and msbuild /t:restore, but VS seems not to call them, or call them after it resolves other properties, like the project version I am interested in changing.
VS calls CollectPackageReferences
@emgarten @andreesteve s/CollectPackageRefereces/CollectPackageReferences/ ?
I added this but I don't see restoring of dotnet tools
<Target Name="LocalToolRestore" BeforeTargets="CollectPackageRefereces">
<Message Text="Restoring tools" Importance="High" />
<Exec Command="dotnet tool restore" />
</Target>
<Target Name="LocalToolRestore2" BeforeTargets="_GenerateRestoreProjectSpec">
<Message Text="Restoring tools" Importance="High" />
<Exec Command="dotnet tool restore" />
</Target>
@NN---
There's a typo there.
It should be CollectPackageReferences
. I updated the issue body with the correct spelling.
Most helpful comment
Restore is not currently the correct target but we should make that work. We should mimize the target differences between command-line and VS.