diff --git a/BenchmarkDotNet.sln b/BenchmarkDotNet.sln
index 9537707749..ba31552c8a 100644
--- a/BenchmarkDotNet.sln
+++ b/BenchmarkDotNet.sln
@@ -47,7 +47,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "templates", "templates", "{
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.Templates", "templates\BenchmarkDotNet.Templates.csproj", "{B620D10A-CD8E-4A34-8B27-FD6257E63AD0}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarkDotNet.Diagnostics.dotTrace", "src\BenchmarkDotNet.Diagnostics.dotTrace\BenchmarkDotNet.Diagnostics.dotTrace.csproj", "{C5BDA61F-3A56-4B59-901D-0A17E78F4076}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.Diagnostics.dotTrace", "src\BenchmarkDotNet.Diagnostics.dotTrace\BenchmarkDotNet.Diagnostics.dotTrace.csproj", "{C5BDA61F-3A56-4B59-901D-0A17E78F4076}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks", "tests\BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks\BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks.csproj", "{AACA2C63-A85B-47AB-99FC-72C3FF408B14}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -131,6 +133,10 @@ Global
{C5BDA61F-3A56-4B59-901D-0A17E78F4076}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5BDA61F-3A56-4B59-901D-0A17E78F4076}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5BDA61F-3A56-4B59-901D-0A17E78F4076}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AACA2C63-A85B-47AB-99FC-72C3FF408B14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AACA2C63-A85B-47AB-99FC-72C3FF408B14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AACA2C63-A85B-47AB-99FC-72C3FF408B14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AACA2C63-A85B-47AB-99FC-72C3FF408B14}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -155,6 +161,7 @@ Global
{D9F5065B-6190-431B-850C-117E3D64AB33} = {D6597E3A-6892-4A68-8E14-042FC941FDA2}
{B620D10A-CD8E-4A34-8B27-FD6257E63AD0} = {63B94FD6-3F3D-4E04-9727-48E86AC4384C}
{C5BDA61F-3A56-4B59-901D-0A17E78F4076} = {D6597E3A-6892-4A68-8E14-042FC941FDA2}
+ {AACA2C63-A85B-47AB-99FC-72C3FF408B14} = {14195214-591A-45B7-851A-19D3BA2413F9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4D9AF12B-1F7F-45A7-9E8C-E4E46ADCBD1F}
diff --git a/src/BenchmarkDotNet/Properties/AssemblyInfo.cs b/src/BenchmarkDotNet/Properties/AssemblyInfo.cs
index 596c220645..5327197aa5 100644
--- a/src/BenchmarkDotNet/Properties/AssemblyInfo.cs
+++ b/src/BenchmarkDotNet/Properties/AssemblyInfo.cs
@@ -15,10 +15,12 @@
[assembly: InternalsVisibleTo("BenchmarkDotNet.Diagnostics.Windows,PublicKey=" + BenchmarkDotNetInfo.PublicKey)]
[assembly: InternalsVisibleTo("BenchmarkDotNet.Diagnostics.dotTrace,PublicKey=" + BenchmarkDotNetInfo.PublicKey)]
[assembly: InternalsVisibleTo("BenchmarkDotNet.IntegrationTests.ManualRunning,PublicKey=" + BenchmarkDotNetInfo.PublicKey)]
+[assembly: InternalsVisibleTo("BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks,PublicKey=" + BenchmarkDotNetInfo.PublicKey)]
#else
[assembly: InternalsVisibleTo("BenchmarkDotNet.Tests")]
[assembly: InternalsVisibleTo("BenchmarkDotNet.IntegrationTests")]
[assembly: InternalsVisibleTo("BenchmarkDotNet.Diagnostics.Windows")]
[assembly: InternalsVisibleTo("BenchmarkDotNet.Diagnostics.dotTrace")]
[assembly: InternalsVisibleTo("BenchmarkDotNet.IntegrationTests.ManualRunning")]
+[assembly: InternalsVisibleTo("BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks")]
#endif
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs b/src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs
index cdb253447c..66f17ce246 100644
--- a/src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs
+++ b/src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs
@@ -1,6 +1,7 @@
using System;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Extensions;
+using BenchmarkDotNet.Helpers;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Running;
@@ -34,12 +35,19 @@ internal static IToolchain GetToolchain(this Runtime runtime, Descriptor descrip
switch (runtime)
{
case ClrRuntime clrRuntime:
- if (RuntimeInformation.IsNetCore || preferMsBuildToolchains)
- return clrRuntime.RuntimeMoniker != RuntimeMoniker.NotRecognized
- ? GetToolchain(clrRuntime.RuntimeMoniker)
- : CsProjClassicNetToolchain.From(clrRuntime.MsBuildMoniker);
-
- return RoslynToolchain.Instance;
+ if (!preferMsBuildToolchains && RuntimeInformation.IsFullFramework &&
+ // If dotnet SDK is not installed, we use RoslynToolchain.
+ (!HostEnvironmentInfo.GetCurrent().IsDotNetCliInstalled()
+ // Integration tests take too much time, because each benchmark run rebuilds the test suite and BenchmarkDotNet itself.
+ // To reduce the total duration of the CI workflows, we just use RoslynToolchain.
+ || XUnitHelper.IsIntegrationTest.Value))
+ {
+ return RoslynToolchain.Instance;
+ }
+
+ return clrRuntime.RuntimeMoniker != RuntimeMoniker.NotRecognized
+ ? GetToolchain(clrRuntime.RuntimeMoniker)
+ : CsProjClassicNetToolchain.From(clrRuntime.MsBuildMoniker);
case MonoRuntime mono:
if (RuntimeInformation.IsAndroid())
diff --git a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks.csproj b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks.csproj
new file mode 100644
index 0000000000..f5f83b5cda
--- /dev/null
+++ b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks.csproj
@@ -0,0 +1,46 @@
+
+
+
+ BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks
+
+ net461;net48;netcoreapp2.0;net7.0
+ true
+ BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks
+ BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks
+ true
+ false
+ AnyCPU
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
diff --git a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/MultipleFrameworksTest.cs b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/MultipleFrameworksTest.cs
new file mode 100644
index 0000000000..701b7d7ee1
--- /dev/null
+++ b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/MultipleFrameworksTest.cs
@@ -0,0 +1,50 @@
+using System;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Configs;
+using BenchmarkDotNet.Extensions;
+using BenchmarkDotNet.Jobs;
+using Xunit;
+
+namespace BenchmarkDotNet.IntegrationTests
+{
+ public class MultipleFrameworksTest : BenchmarkTestExecutor
+ {
+ private const string TfmEnvVarName = "TfmEnvVarName";
+
+ [Theory]
+ [InlineData(RuntimeMoniker.Net461)]
+ [InlineData(RuntimeMoniker.Net48)]
+ [InlineData(RuntimeMoniker.NetCoreApp20)]
+ [InlineData(RuntimeMoniker.Net70)]
+ public void EachFrameworkIsRebuilt(RuntimeMoniker runtime)
+ {
+ var config = ManualConfig.CreateEmpty().AddJob(Job.Dry.WithRuntime(runtime.GetRuntime()).WithEnvironmentVariable(TfmEnvVarName, runtime.ToString()));
+ CanExecute(config);
+ }
+
+ public class ValuePerTfm
+ {
+ private const RuntimeMoniker moniker =
+#if NET461
+ RuntimeMoniker.Net461;
+#elif NET48
+ RuntimeMoniker.Net48;
+#elif NETCOREAPP2_0
+ RuntimeMoniker.NetCoreApp20;
+#elif NET7_0
+ RuntimeMoniker.Net70;
+#else
+ RuntimeMoniker.NotRecognized;
+#endif
+
+ [Benchmark]
+ public void ThrowWhenWrong()
+ {
+ if (Environment.GetEnvironmentVariable(TfmEnvVarName) != moniker.ToString())
+ {
+ throw new InvalidOperationException($"Has not been recompiled, the value was {Environment.GetEnvironmentVariable(TfmEnvVarName)}");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/BenchmarkDotNet.IntegrationTests.ManualRunning.csproj b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/BenchmarkDotNet.IntegrationTests.ManualRunning.csproj
index b0259a941e..020b73060c 100755
--- a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/BenchmarkDotNet.IntegrationTests.ManualRunning.csproj
+++ b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/BenchmarkDotNet.IntegrationTests.ManualRunning.csproj
@@ -16,6 +16,8 @@
+
+
@@ -25,7 +27,6 @@
-