diff --git a/src/BenchmarkDotNet/Templates/CsProj.txt b/src/BenchmarkDotNet/Templates/CsProj.txt index 610b204fca..9afef8cf5e 100644 --- a/src/BenchmarkDotNet/Templates/CsProj.txt +++ b/src/BenchmarkDotNet/Templates/CsProj.txt @@ -8,20 +8,12 @@ $PROGRAMNAME$ Exe False - - false + false false - false - false - true - - true false - - true BenchmarkDotNet.Autogenerated.UniqueProgramName diff --git a/src/BenchmarkDotNet/Templates/MonoAOTLLVMCsProj.txt b/src/BenchmarkDotNet/Templates/MonoAOTLLVMCsProj.txt index 248d17329a..f005cd82b4 100644 --- a/src/BenchmarkDotNet/Templates/MonoAOTLLVMCsProj.txt +++ b/src/BenchmarkDotNet/Templates/MonoAOTLLVMCsProj.txt @@ -9,6 +9,9 @@ Exe + False + false + false $TFM$ $RUNTIMEPACK$ $RUNTIMEIDENTIFIER$ @@ -16,11 +19,10 @@ false $PROGRAMNAME$ false + false true BenchmarkDotNet.Autogenerated.UniqueProgramName true - - true diff --git a/src/BenchmarkDotNet/Templates/R2RCsProj.txt b/src/BenchmarkDotNet/Templates/R2RCsProj.txt index ae9fd774d3..e881418b1b 100644 --- a/src/BenchmarkDotNet/Templates/R2RCsProj.txt +++ b/src/BenchmarkDotNet/Templates/R2RCsProj.txt @@ -9,20 +9,12 @@ $PROGRAMNAME$ Exe False - - false + false false - false - false - true - - true false - - true BenchmarkDotNet.Autogenerated.UniqueProgramName false diff --git a/src/BenchmarkDotNet/Templates/WasmCsProj.txt b/src/BenchmarkDotNet/Templates/WasmCsProj.txt index 8542f55eb9..68915fe4f6 100644 --- a/src/BenchmarkDotNet/Templates/WasmCsProj.txt +++ b/src/BenchmarkDotNet/Templates/WasmCsProj.txt @@ -10,6 +10,9 @@ $CORECLR_OVERRIDES$ Exe + False + false + false Release false $TFM$ @@ -23,8 +26,6 @@ $CORECLR_OVERRIDES$ false false false - - true BenchmarkDotNet.Autogenerated.UniqueProgramName diff --git a/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs b/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs index a368959b4f..08956ba6ea 100644 --- a/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs +++ b/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs @@ -33,9 +33,18 @@ public class CsProjGenerator : DotNetCliGenerator, IEquatable "UserSecretsId", "EnablePreviewFeatures", "RuntimeHostConfigurationOption", - "WarningsAsErrors", "Features", - "GarbageCollectionAdaptationMode" // TODO: Remove this setting after https://github.com/dotnet/runtime/pull/131069 issue is resolved, and backported to .NET 10. + + "WarningsAsErrors", + "WarningsNotAsErrors", + "WarningLevel", + "NoWarn", + "MSBuildWarningsAsErrors", + "MSBuildWarningsNotAsErrors", + "MSBuildWarningsAsMessages", + "SuppressTfmSupportBuildWarnings", + + "GarbageCollectionAdaptationMode", // TODO: Remove this setting after https://github.com/dotnet/runtime/pull/131069 issue is resolved, and backported to .NET 10. }.ToImmutableArray(); public string RuntimeFrameworkVersion { get; } diff --git a/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommandExecutor.cs b/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommandExecutor.cs index a37af02634..4bced8ca12 100644 --- a/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommandExecutor.cs +++ b/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommandExecutor.cs @@ -7,6 +7,7 @@ using BenchmarkDotNet.Running; using BenchmarkDotNet.Toolchains.Results; using JetBrains.Annotations; +using System.Collections.Immutable; using System.ComponentModel; using System.Diagnostics; using System.Text; @@ -56,9 +57,38 @@ public static async Task ExecuteAsync(DotNetCliCommand p parameters.Logger.WriteLineInfo($"// command took {stopwatch.Elapsed.TotalSeconds.ToInvariantString("0.##")} sec and exited with {process.ExitCode}"); - return process.ExitCode <= 0 - ? DotNetCliCommandResult.Success(stopwatch.Elapsed, outputReader.GetOutputText()) - : DotNetCliCommandResult.Failure(stopwatch.Elapsed, outputReader.GetOutputText(), outputReader.GetErrorText()); + if (process.ExitCode != 0) + { + return DotNetCliCommandResult.Failure(stopwatch.Elapsed, outputReader.GetOutputText(), outputReader.GetErrorText()); + } + + // A successful build's output is otherwise discarded (see DotNetCliCommandResult.ToBuildResult), so + // build/restore warnings (e.g. NU1701, NU1702) would be invisible unless LogBuildOutput is set. When the + // full output isn't already being streamed, surface just the warning lines so they aren't silently lost. + if (!parameters.LogOutput) + LogBuildWarnings(parameters.Logger, outputReader.GetOutputLines()); + + return DotNetCliCommandResult.Success(stopwatch.Elapsed, outputReader.GetOutputText()); + } + + // Matches an MSBuild/NuGet warning line, e.g. "...csproj : warning NU1702: ..." or "...targets(1,5): warning NETSDK1138: ...". + private static readonly Regex BuildWarningRegex = new(@": warning [A-Za-z]+\d+:", RegexOptions.CultureInvariant | RegexOptions.Compiled); + + // Surfaces just the warning lines from an otherwise-discarded successful build output, deduplicated + // (MSBuild repeats a warning per target framework and again in the summary). + private static void LogBuildWarnings(ILogger logger, ImmutableArray outputLines) + { + HashSet? seen = null; + foreach (var line in outputLines) + { + if (!BuildWarningRegex.IsMatch(line)) + continue; + + string warning = line.Trim(); + seen ??= new HashSet(StringComparer.Ordinal); + if (seen.Add(warning)) + logger.WriteLineWarning($"// {warning}"); + } } internal static string GetDotNetSdkVersion() diff --git a/src/BenchmarkDotNet/Toolchains/NativeAot/Generator.cs b/src/BenchmarkDotNet/Toolchains/NativeAot/Generator.cs index 9280c553ef..8c3a41cd73 100644 --- a/src/BenchmarkDotNet/Toolchains/NativeAot/Generator.cs +++ b/src/BenchmarkDotNet/Toolchains/NativeAot/Generator.cs @@ -147,9 +147,8 @@ private string GenerateProjectForNuGetBuild(string projectFilePath, BuildPartiti true {buildPartition.Platform.ToConfig()} False + false false - false - true false true {ilcOptimizationPreference} @@ -160,7 +159,6 @@ private string GenerateProjectForNuGetBuild(string projectFilePath, BuildPartiti false false false - true {GetInstructionSetSettings(buildPartition)} {GetRuntimeSettings(buildPartition.RepresentativeBenchmarkCase.Job.Environment.Gc, buildPartition.Resolver)} diff --git a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/MultipleFrameworksTest.cs b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/MultipleFrameworksTest.cs index 9cc9ffeae0..b04e8d3640 100644 --- a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/MultipleFrameworksTest.cs +++ b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning.MultipleFrameworks/MultipleFrameworksTest.cs @@ -14,10 +14,10 @@ public MultipleFrameworksTest(ITestOutputHelper output) : base(output) } [Theory] - [InlineData(RuntimeMoniker.Net461)] + [InlineData(RuntimeMoniker.Net462)] [InlineData(RuntimeMoniker.Net48)] - [InlineData(RuntimeMoniker.NetCoreApp20)] [InlineData(RuntimeMoniker.Net80)] + [InlineData(RuntimeMoniker.Net10_0)] public void EachFrameworkIsRebuilt(RuntimeMoniker runtime) { var config = ManualConfig.CreateEmpty().AddJob(Job.Dry.WithRuntime(runtime.GetRuntime()).WithEnvironmentVariable(TfmEnvVarName, runtime.ToString()));