Treat ProjectReference as PackageReference or allow PackageReference to local csproj

2.3k views Asked by At

I have a netstandard2.0 csproj (let's call it MyPackage) that is packed at build time (as specified by GeneratePackageOnBuild) into a nuget package. This nuget package has custom props and targets in the build directory (so referencing projects get these imported).

I have another project (let's call it MyConsumer) in the same solution for testing MyPackage. I want MyConsumer to have the build asset props and targets imported from MyPackage at build time, just as if it were consuming it as a PackageReference from some remote nuget source.

How can I get this working (most simply)?

I have been able to do it via a very convoluted method where I have MyConsumer add a PackageReference to MyPackage and override the RestoreSources in MyConsumer to point to the bin directory of MyPackage. This gets very weird when running dotnet build or Visual Studio build of the sln, because project metadata is generated upfront for all projects during Restore and thus MyPackage doesn't exist at that point. The resolution was to add nested calls to MSBuild within the MyConsumer project, but then this becomes even worse, since Visual Studio restores operate quite differently than that automatic restores performed by dotnet build.

Is there any simple way of doing this?

This is what I have now

<Project> 
  <Target Name="Build">    
    <Message Text="Running inner build" Importance="high" />

    <!-- 
    Need to call MSBuild twice, once to restore, then again to restore and build to get the restore of the Sdk to work
    because of this bug in MSBuild: https://github.com/Microsoft/msbuild/issues/2455
    Note the trailing Prop=1 is required to get MSBuild to invalid it's cache of the project target imports
    -->
    <MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Restore" Properties="Configuration=$(Configuration);Version=$(Version);IsInnerBuild=true;Prop=1" />
    <!-- Have to use dotnet build instead of another call to MSBuild because of another bug that prevents proper imports within the same physical process  -->
    <Exec Command="dotnet build /p:Configuration=$(Configuration) /p:Version=$(Version) /p:IsInnerBuild=true" />
    <Message Text="Finished inner build" Importance="high" />
  </Target>

  <Target Name="Restore" />

  <Target Name="RemoveBin">
    <RemoveDir Directories="bin" />
  </Target>

  <!-- Don't do real cleans old rebuild since it breaks MSBuild due to the same above bug -->
  <Target Name="Rebuild" DependsOnTargets="RemoveBin;Build">
  </Target>
</Project>
1

There are 1 answers

3
Leo Liu On

Treat ProjectReference as PackageReference or allow PackageReference to local csproj

If I understand you correct, you want to generate the package with project MyPackage, then install it to the test project MyConsumer and have the build asset props and targets imported from MyPackage at build time.

To accomplish this goal, you need to complete the following few things:

  • Make sure the project MyPackage build before the project MyConsumer.
  • Set the package into the packager source
  • Add the package MyPackage.nupkg to the test project MyConsumer during the build time.

Details for above:

  • Make sure the project MyPackage build before the project MyConsumer.

Since you wan to test the package which generated by the project MyConsumer, you should make sure this package grnerate before test project using it, so we need set the project MyConsumer reference the the project MyPackage.

  • Set the package into the packager source

You can use a post-build event for the project MyPackage to copy the package MyPackage.nupkg to the local feed, or you can just add the bin directory of MyPackage.nupkg to the package source.

  • Add the package MyPackage.nupkg to the test project MyConsumer during the build time.

Using VS 2017 and the PackageReference style of the test project MyConsumer, you can set a Directory.Build.props file into the root of your solution containing the test project MyConsumer you need:

<Project>
  <ItemGroup>
    <PackageReference Include="MyPackage" Version="1.0.* />
  </ItemGroup>
</Project>

This will add these NuGet packages to the test project MyConsumer in the solution, it will be used as a PackageReference from some remote nuget source.

Check the Martin`s answer for some more details.

Hope this helps.