From d11f3fb3c1e9b387071bf82c623a519392ab812e Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Tue, 27 Jan 2026 01:39:00 +0100 Subject: [PATCH] Content.Packaging can now emit binlogs for the build (#42659) * Content.Packaging can now emit binlogs for the build I was checking why packaging is so much slower and it *seems* to be entirely the actual build being twice as slow as before .NET 10. Strange. Content.Packaging can now emit MSBuild binlogs that we can analyze to see why that's the case. * Enable --log-build on Test Packaging workflow, produce artifact with binlogs * Disable setup-dotnet in packaging workflow I have a suspicion... --- .github/workflows/test-packaging.yml | 19 +++++++++++++------ Content.Packaging/ClientPackaging.cs | 14 +++++++++++--- Content.Packaging/CommandLineArgs.cs | 15 ++++++++++++++- Content.Packaging/Program.cs | 4 ++-- Content.Packaging/ServerPackaging.cs | 25 +++++++++++++++++++------ 5 files changed, 59 insertions(+), 18 deletions(-) diff --git a/.github/workflows/test-packaging.yml b/.github/workflows/test-packaging.yml index 6cb6d836d52..46ce13013a2 100644 --- a/.github/workflows/test-packaging.yml +++ b/.github/workflows/test-packaging.yml @@ -48,10 +48,11 @@ jobs: cd RobustToolbox/ git submodule update --init --recursive - - name: Setup .NET Core - uses: actions/setup-dotnet@v4.1.0 - with: - dotnet-version: 10.0.x + # ubuntu-latest has .NET 10 + # - name: Setup .NET Core + # uses: actions/setup-dotnet@v4.1.0 + # with: + # dotnet-version: 10.0.x - name: Install dependencies run: dotnet restore @@ -60,7 +61,13 @@ jobs: run: dotnet build Content.Packaging --configuration Release --no-restore /m - name: Package server - run: dotnet run --project Content.Packaging server --platform win-x64 --platform win-arm64 --platform linux-x64 --platform linux-arm64 --platform osx-x64 --platform osx-arm64 + run: dotnet run --project Content.Packaging server --log-build --platform win-x64 --platform win-arm64 --platform linux-x64 --platform linux-arm64 --platform osx-x64 --platform osx-arm64 - name: Package client - run: dotnet run --project Content.Packaging client --no-wipe-release + run: dotnet run --project Content.Packaging client --log-build --no-wipe-release + + - uses: actions/upload-artifact@v4 + with: + name: binlogs + path: release/*.binlog + retention-days: 7 diff --git a/Content.Packaging/ClientPackaging.cs b/Content.Packaging/ClientPackaging.cs index 21215d3bcbf..f17ebf5d20f 100644 --- a/Content.Packaging/ClientPackaging.cs +++ b/Content.Packaging/ClientPackaging.cs @@ -13,13 +13,13 @@ public static class ClientPackaging /// /// Be advised this can be called from server packaging during a HybridACZ build. /// - public static async Task PackageClient(bool skipBuild, string configuration, IPackageLogger logger) + public static async Task PackageClient(bool skipBuild, bool logBuild, string configuration, IPackageLogger logger) { logger.Info("Building client..."); if (!skipBuild) { - await ProcessHelpers.RunCheck(new ProcessStartInfo + var startInfo = new ProcessStartInfo { FileName = "dotnet", ArgumentList = @@ -33,7 +33,15 @@ public static class ClientPackaging "/p:FullRelease=true", "/m" } - }); + }; + + if (logBuild) + { + startInfo.ArgumentList.Add($"/bl:{Path.Combine("release", "client.binlog")}"); + startInfo.ArgumentList.Add("/p:ReportAnalyzer=true"); + } + + await ProcessHelpers.RunCheck(startInfo); } logger.Info("Packaging client..."); diff --git a/Content.Packaging/CommandLineArgs.cs b/Content.Packaging/CommandLineArgs.cs index 23f661921e0..ed5e5f2b29b 100644 --- a/Content.Packaging/CommandLineArgs.cs +++ b/Content.Packaging/CommandLineArgs.cs @@ -36,6 +36,11 @@ public sealed class CommandLineArgs /// public string Configuration { get; set; } + /// + /// Log builds with MSBuild binlog. Logs get saved to release/ + /// + public bool LogBuild { get; set; } + // CommandLineArgs, 3rd of her name. public static bool TryParse(IReadOnlyList args, [NotNullWhen(true)] out CommandLineArgs? parsed) { @@ -44,6 +49,7 @@ public sealed class CommandLineArgs var skipBuild = false; var wipeRelease = true; var hybridAcz = false; + var logBuild = false; var configuration = "Release"; List? platforms = null; @@ -84,6 +90,10 @@ public sealed class CommandLineArgs { hybridAcz = true; } + else if (arg == "--log-build") + { + logBuild = true; + } else if (arg == "--platform") { if (!enumerator.MoveNext()) @@ -122,7 +132,7 @@ public sealed class CommandLineArgs return false; } - parsed = new CommandLineArgs(client.Value, skipBuild, wipeRelease, hybridAcz, platforms, configuration); + parsed = new CommandLineArgs(client.Value, skipBuild, wipeRelease, hybridAcz, logBuild, platforms, configuration); return true; } @@ -137,6 +147,7 @@ Options: --hybrid-acz Use HybridACZ for server builds. --platform Platform for server builds. Default will output several x64 targets. --configuration Configuration to use for building the server (Release, Debug, Tools). Default is Release. + --log-build Log builds with MSBuild binlog. Logs get saved to release/ "); } @@ -145,6 +156,7 @@ Options: bool skipBuild, bool wipeRelease, bool hybridAcz, + bool logBuild, List? platforms, string configuration) { @@ -154,5 +166,6 @@ Options: HybridAcz = hybridAcz; Platforms = platforms; Configuration = configuration; + LogBuild = logBuild; } } diff --git a/Content.Packaging/Program.cs b/Content.Packaging/Program.cs index 9457e9dacc9..25fc550a2fd 100644 --- a/Content.Packaging/Program.cs +++ b/Content.Packaging/Program.cs @@ -22,11 +22,11 @@ if (!parsed.SkipBuild) if (parsed.Client) { - await ClientPackaging.PackageClient(parsed.SkipBuild, parsed.Configuration, logger); + await ClientPackaging.PackageClient(parsed.SkipBuild, parsed.LogBuild, parsed.Configuration, logger); } else { - await ServerPackaging.PackageServer(parsed.SkipBuild, parsed.HybridAcz, logger, parsed.Configuration, parsed.Platforms); + await ServerPackaging.PackageServer(parsed.SkipBuild, parsed.HybridAcz, parsed.LogBuild, logger, parsed.Configuration, parsed.Platforms); } void WipeBin() diff --git a/Content.Packaging/ServerPackaging.cs b/Content.Packaging/ServerPackaging.cs index 8e559d5a65b..b64e02ced75 100644 --- a/Content.Packaging/ServerPackaging.cs +++ b/Content.Packaging/ServerPackaging.cs @@ -60,7 +60,7 @@ public static class ServerPackaging "zh-Hant" }; - public static async Task PackageServer(bool skipBuild, bool hybridAcz, IPackageLogger logger, string configuration, List? platforms = null) + public static async Task PackageServer(bool skipBuild, bool hybridAcz, bool logBuild, IPackageLogger logger, string configuration, List? platforms = null) { if (platforms == null) { @@ -73,7 +73,7 @@ public static class ServerPackaging // Rather than hosting the client ZIP on the watchdog or on a separate server, // Hybrid ACZ uses the ACZ hosting functionality to host it as part of the status host, // which means that features such as automatic UPnP forwarding still work properly. - await ClientPackaging.PackageClient(skipBuild, configuration, logger); + await ClientPackaging.PackageClient(skipBuild, logBuild, configuration, logger); } // Good variable naming right here. @@ -82,17 +82,22 @@ public static class ServerPackaging if (!platforms.Contains(platform.Rid)) continue; - await BuildPlatform(platform, skipBuild, hybridAcz, configuration, logger); + await BuildPlatform(platform, skipBuild, hybridAcz, logBuild, configuration, logger); } } - private static async Task BuildPlatform(PlatformReg platform, bool skipBuild, bool hybridAcz, string configuration, IPackageLogger logger) + private static async Task BuildPlatform(PlatformReg platform, + bool skipBuild, + bool hybridAcz, + bool logBuild, + string configuration, + IPackageLogger logger) { logger.Info($"Building project for {platform.TargetOs}..."); if (!skipBuild) { - await ProcessHelpers.RunCheck(new ProcessStartInfo + var startInfo = new ProcessStartInfo { FileName = "dotnet", ArgumentList = @@ -107,7 +112,15 @@ public static class ServerPackaging "/p:FullRelease=true", "/m" } - }); + }; + + if (logBuild) + { + startInfo.ArgumentList.Add($"/bl:{Path.Combine("release", $"server-{platform.Rid}.binlog")}"); + startInfo.ArgumentList.Add("/p:ReportAnalyzer=true"); + } + + await ProcessHelpers.RunCheck(startInfo); await PublishClientServer(platform.Rid, platform.TargetOs, configuration); }