[msbuild] refactor BenchmarkDotNet.Weaver.targets to support mobile platforms#2931
Conversation
… platforms Context: dotnet#2929 Context: https://github.com/dotnet/android/blob/4aa9af89102af2e745a8507992187d3c5993d638/Documentation/guides/MSBuildBestPractices.md In initially testing BenchmarkDotNet with .NET MAUI, I found that the weaver was not being executed because the `Publish` target is not called during the build process for Android and iOS projects. I think the target could actually run much sooner during builds and achieve better results. To address this, I refactored the `BenchmarkDotNet.Weaver.targets` file to run after `CoreCompile` on the `@(IntermediateAssembly)` in the `obj` directory. This is similar to what other targets do, such as the XamlC compiler: https://github.com/dotnet/maui/blob/8224becbb3a8a6bb1caaca4bbe70c56e88875506/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets#L213-L255 Other general MSBuild improvements: * Defined an MSBuild property for everything that seems useful. This allows consuming projects to configure the behavior (or workarounds!) as needed. * Made the MSBuild target incremental by using inputs and outputs. If the `.dll` file is an input, we can write a `.stamp` file as an output to indicate that the weaver has already been run for that assembly. If the `.dll` file changes, the weaver will run again. I tested this change with a .NET MAUI on 4 platforms and also the existing `BenchmarkDotNet.Samples` console app.
|
Thanks. I initially tried to do it after |
|
I think this might have broken us. We have now started to see NETSDK1152 in our performance runs. Chatting with Copilot, it believes that the issue is from this change. This is its logic Why It Breaks
[2025/12/18 10:33:54][INFO] /home/helixbot/work/942D0884/w/A92E09B4/e/performance/tools/dotnet/x64/sdk/11.0.100-alpha.1.25618.105/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.ConflictResolution.targets(112,5): error NETSDK1152: Found multiple publish output files with the same relative path: /home/helixbot/work/942D0884/w/A92E09B4/e/performance/artifacts/obj/BenchmarkDotNet.Autogenerated/Release/MicroBenchmarks-Job-ALNHUU-1.dll, /home/helixbot/work/942D0884/w/A92E09B4/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-Job-ALNHUU-1/bin/Release/net11.0/publish/MicroBenchmarks-Job-ALNHUU-1.dll. [/home/helixbot/work/942D0884/w/A92E09B4/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-Job-ALNHUU-1/BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net11.0] |
|
@DrewScoggins can you share a |
|
@DrewScoggins How to repro? We have some toolchains that do publish, but the error doesn't occur in our tests. I'd like to add a test case for that if possible. Also, can you see if #2935 fixes it? |
|
@timcassell Right now, we have only been able to repro it in our internal CI :( We will try tomorrow to get you something more targeted. |
|
@DrewScoggins that
Do you have a I also authored this PR, so you should be able to get back the previous behavior (untested): <PropertyGroup>
<BenchmarkDotNetWeaveAssembliesAfterTargets>Build</BenchmarkDotNetWeaveAssembliesAfterTargets>
<BenchmarkDotNetWeaveAssembliesBeforeTargets>Publish</BenchmarkDotNetWeaveAssembliesBeforeTargets>
<BenchmarkDotNetWeaveAssemblyPath>$(TargetDir)$(TargetFileName)</BenchmarkDotNetWeaveAssemblyPath>
</PropertyGroup>(Try putting in a Share either a |
I thought The change to run after [Edit] Would |
|
@timcassell Why not just pass |
|
@timcassell if someone can share a project that doesn't work, that would help me understand what is going on. The changes here run after |
I don't know what you mean by that. We already pass the path to the assembly. The issue is the references of the target assembly can be nuget packages or otherwise that we cannot resolve after
You can try it out with the update-asmresolver branch. If you simply build |
This comment was marked as outdated.
This comment was marked as outdated.
|
https://github.com/dotnet/BenchmarkDotNet/actions/runs/22322058229 Is there a specific line I should look at? This has unrelated errors. |
The test failures are downstream issues from the weaver failing. You will see the real error (as a warning) when you build the project (the error is pasted in Washi1337/AsmResolver#716). |
Actually if you look at the |
|
Does the "weaver" need to be able to find all assembly references? Because they won't be found in the same folder. |
It needs to walk the hierarchy of attributes on methods, and to do that it must resolve the assemblies. I'm trying a custom resolver to search the OutDir now to see if we can keep it after |
|
I think @js6pak is right that you can look at the |
|
|
|

Context: #2929
Context: https://github.com/dotnet/android/blob/4aa9af89102af2e745a8507992187d3c5993d638/Documentation/guides/MSBuildBestPractices.md
In initially testing BenchmarkDotNet with .NET MAUI, I found that the weaver was not being executed because the
Publishtarget is not called during the build process for Android and iOS projects. I think the target could actually run much sooner during builds and achieve better results.To address this, I refactored the
BenchmarkDotNet.Weaver.targetsfile to run afterCoreCompileon the@(IntermediateAssembly)in theobjdirectory. This is similar to what other targets do, such as the XamlC compiler:https://github.com/dotnet/maui/blob/8224becbb3a8a6bb1caaca4bbe70c56e88875506/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets#L213-L255
Other general MSBuild improvements:
Defined an MSBuild property for everything that seems useful. This allows consuming projects to configure the behavior (or workarounds!) as needed.
Made the MSBuild target incremental by using inputs and outputs. If the
.dllfile is an input, we can write a.stampfile as an output to indicate that the weaver has already been run for that assembly. If the.dllfile changes, the weaver will run again.I tested this change with a .NET MAUI on 4 platforms and also the existing
BenchmarkDotNet.Samplesconsole app.