BenchmarkDotNet icon indicating copy to clipboard operation
BenchmarkDotNet copied to clipboard

Enable including references in autogenerated csproject

Open billwert opened this issue 6 years ago • 7 comments
trafficstars

Today, if a benchmark needs a reference to a Nuget package it goes into the original project (microbenchmarks.csproj, say) and then does not need to be in the auto generated csproj.

I’d like to enable us to remove the requirement that we run .NET Framework tests on VMs / machines that have Visual Studio installed: https://github.com/dotnet/performance/pull/627. The new Microsoft.NetFramework.ReferenceAssemblies package is precisely the answer.

But it fails because the generated project doesn’t include the package reference I added:

[2019/07/11 19:29:39][INFO] $ dotnet run --project C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\src\benchmarks\micro\MicroBenchmarks.csproj --configuration Release --framework net461 --no-restore --no-build -- --anyCategories coreclr corefx --iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --stopOnFirstError true --partition-count 5 --partition-index 0 --packages C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\artifacts\packages --runtimes net461
[2019/07/11 19:29:42][INFO] // Validating benchmarks:
[2019/07/11 19:29:48][INFO] // ***** BenchmarkRunner: Start   *****
[2019/07/11 19:29:48][INFO] // ***** Found 437 benchmark(s) in total *****
[2019/07/11 19:29:48][INFO] // ***** Building 1 exe(s) in Parallel: Start   *****
[2019/07/11 19:29:50][INFO] // start dotnet restore --packages "C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\artifacts\packages"  /p:UseSharedCompilation=false /p:BuildInParallel=false /m:1 in C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\artifacts\bin\MicroBenchmarks\Release\net461\2397be0f-2eba-4afc-b8e3-34ec43808e6d
[2019/07/11 19:29:52][INFO] // command took 2.7s and exited with 0
[2019/07/11 19:29:52][INFO] // start dotnet build -c Release  --no-restore /p:UseSharedCompilation=false /p:BuildInParallel=false /m:1 in C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\artifacts\bin\MicroBenchmarks\Release\net461\2397be0f-2eba-4afc-b8e3-34ec43808e6d
[2019/07/11 19:29:54][INFO] // command took 1.26s and exited with 1
[2019/07/11 19:29:54][INFO] // start dotnet build -c Release  --no-restore --no-dependencies /p:UseSharedCompilation=false /p:BuildInParallel=false /m:1 in C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\artifacts\bin\MicroBenchmarks\Release\net461\2397be0f-2eba-4afc-b8e3-34ec43808e6d
[2019/07/11 19:29:55][INFO] // command took 1.24s and exited with 1
[2019/07/11 19:29:55][INFO] // ***** Done, took 00:00:06 (6.63 sec)   *****
[2019/07/11 19:29:55][INFO] // Found 1 benchmarks:
[2019/07/11 19:29:55][INFO] //   Burgers.Burgers_0: Job-NTJWUA(Runtime=Clr, Toolchain=net461, InvocationCount=1, IterationCount=1, IterationTime=250.0000 ms, MaxIterationCount=20, MinIterationCount=15, RunStrategy=ColdStart, UnrollFactor=1, WarmupCount=0)
[2019/07/11 19:29:55][INFO] 
[2019/07/11 19:29:55][INFO] // Build Error: Standard output:
[2019/07/11 19:29:55][INFO] 
[2019/07/11 19:29:55][INFO]  Standard error:
[2019/07/11 19:29:55][INFO]  Time Elapsed 00:00:00.78
[2019/07/11 19:29:55][INFO]     1 Error(s)
[2019/07/11 19:29:55][INFO]     0 Warning(s)
[2019/07/11 19:29:55][INFO] C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\tools\dotnet\x64\sdk\2.1.701\Microsoft.Common.CurrentVersion.targets(1175,5): error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.6.1" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend. [C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\artifacts\bin\MicroBenchmarks\Release\net461\2397be0f-2eba-4afc-b8e3-34ec43808e6d\BenchmarkDotNet.Autogenerated.csproj]
[2019/07/11 19:29:55][INFO] Build FAILED.
[2019/07/11 19:29:55][INFO] C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\tools\dotnet\x64\sdk\2.1.701\Microsoft.Common.CurrentVersion.targets(1175,5): error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.6.1" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend. [C:\dotnetbuild\work\274ec05f-7f6a-45af-b6aa-aa3f40fa2e5d\Payload\artifacts\bin\MicroBenchmarks\Release\net461\2397be0f-2eba-4afc-b8e3-34ec43808e6d\BenchmarkDotNet.Autogenerated.csproj

Interestingly, on my machine the second build (which includes --no-dependencies) works on my machine, probably because it’s using some ambient state at that point.

I see that csproj.txt doesn’t have a parameter for this, so we need some feature to plumb this through.

billwert avatar Jul 11 '19 20:07 billwert

I thought I could work around this by emitting a Directory.Build.props, but y'all thought of that :) https://github.com/dotnet/BenchmarkDotNet/blob/58fde64c809ceadb3fca9d677a7cec83071b833f/src/BenchmarkDotNet/Templates/CsProj.txt#L4-L5

I definitely understand why this is there, and think it's a good idea. It just prevented the work around I had hoped would be cheap of ensuring that there's a Directory.Build.props in the correct place. As msbuild will stop looking, I can feel confident this is going to have the behavior I wanted. Alas.

billwert avatar Jul 14 '19 18:07 billwert

This issue is very similar to #1023 :

  • a project with benchmark A has a reference to package B
  • BenchmarkDotNet generates a new project C that references 'A'
  • the reference to package B is non transitive and BDN fails to build the auto-generated project because it lacks the reference

@viktorhofer @ericstj @eerhardt would it be possible to make Microsoft.NetFramework.ReferenceAssemblies package transitive? or somehow tell MSBuild to reference in C everything that A references? to solve things like #1023 as well?

adamsitnik avatar Jul 22 '19 07:07 adamsitnik

@billwert if I won't be able to find any clean solution the only idea I currently have it to introduce a concept of BenchmarkDotNet.props files that would be always included by the auto-generated project files.

adamsitnik avatar Jul 22 '19 07:07 adamsitnik

The reason the reference to B isn't included in C is because the reference has PrivateAssets=All on it:

https://github.com/dotnet/performance/pull/627/files#diff-931d1b8d9e5f2892d7f8e001da3bf159R25.

This means that this reference is "private" to A and shouldn't be made transitive.

Possible fixes:

  1. Remove PrivateAssets=All on the reference in the benchmark.csproj (A).
    • I am not sure why marking it as PrivateAssets=All in a benchmark project would be necessary. You don't really expect other projects referencing benchmark projects.
  2. BDN could potentially scan the benchmark .csproj for PrivateAssets=All and copy them to the generated project C.

eerhardt avatar Jul 22 '19 15:07 eerhardt

@eerhardt thank you!

Remove PrivateAssets=All on the reference in the benchmark.csproj

@billwert could you please give it a try?

adamsitnik avatar Jul 22 '19 15:07 adamsitnik

Remove PrivateAssets=All on the reference in the benchmark.csproj

FWIW this does not solve the problem (tested myself)

adamsitnik avatar Nov 19 '19 08:11 adamsitnik

I've come here from https://stackoverflow.com/questions/58990324/how-to-benchmark-two-different-versions-of-the-same-non-nuget-library-in-benchma Have the same issue. I need to benchmark some changes in WinForms. For this I manually reference my newly build assembles:

<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net6.0-windows</TargetFramework>
		<UseWindowsForms>true</UseWindowsForms>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
	</PropertyGroup>

	<ItemGroup>
		<Reference Include="d:\save\projects\winforms\artifacts\bin\System.Windows.Forms\Release\net6.0\System.Windows.Forms.dll" />
		<Reference Include="d:\save\projects\winforms\artifacts\bin\System.Windows.Forms.Primitives\Release\net6.0\System.Windows.Forms.Primitives.dll" />
	</ItemGroup>

	<ItemGroup>
		<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
	</ItemGroup>
</Project>

but System.Windows.Forms.dll and System.Windows.Forms.Primitives.dll simply not copied into autogenerated folder - benchmark uses default assemblies :(

kirsan31 avatar Jul 03 '22 15:07 kirsan31