From e968c2ebb21f555281a841f7b82e1fade4c27634 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:04:07 +0000 Subject: [PATCH 1/5] Initial plan From 8f228526f04062c7b53cb5440ba709ccb67276d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:52:08 +0000 Subject: [PATCH 2/5] Fix PublishAot + NoBuild embedded resources issue Adds PrepareResources dependency to _GenerateCompileDependencyCache and implements fallback to populate _CoreCompileResourceInputs when _GenerateCompileInputs is skipped Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com> --- .../Microsoft.Common.CurrentVersion.targets | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.Common.CurrentVersion.targets b/src/Tasks/Microsoft.Common.CurrentVersion.targets index 5ee5e3bc6fd..ff65ad81406 100644 --- a/src/Tasks/Microsoft.Common.CurrentVersion.targets +++ b/src/Tasks/Microsoft.Common.CurrentVersion.targets @@ -3846,7 +3846,25 @@ Copyright (C) Microsoft Corporation. All rights reserved. contribute to incremental build inconsistencies. ============================================================ --> - + + + + + <_CoreCompileResourceInputs Include="@(EmbeddedResource->'%(OutputResource)')" Condition="'%(EmbeddedResource.WithCulture)' == 'false' and '%(EmbeddedResource.Type)' == 'Resx'" /> + <_CoreCompileResourceInputs Include="@(EmbeddedResource)" Condition="'%(EmbeddedResource.WithCulture)' == 'false' and '%(EmbeddedResource.Type)' == 'Non-Resx' " /> + <_CoreCompileResourceInputs Include="@(ManifestResourceWithNoCulture)" Condition="'%(ManifestResourceWithNoCulture.EmittedForCompatibilityOnly)'==''"> + Resx + false + + <_CoreCompileResourceInputs Include="@(ManifestNonResxWithNoCultureOnDisk)" Condition="'%(ManifestNonResxWithNoCultureOnDisk.EmittedForCompatibilityOnly)'==''"> + Non-Resx + false + + + From f61713e94e0358140cd39eed29b7d383063a8b1f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Dec 2025 09:46:45 +0000 Subject: [PATCH 3/5] Refactor: Make _GenerateCompileInputs always run instead of duplicating logic Instead of duplicating resource population logic in _GenerateCompileDependencyCache, make _GenerateCompileInputs always run by adding Outputs="" and clearing items before repopulating to avoid duplicates. This is much more maintainable. Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com> --- .../Microsoft.Common.CurrentVersion.targets | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/Tasks/Microsoft.Common.CurrentVersion.targets b/src/Tasks/Microsoft.Common.CurrentVersion.targets index ff65ad81406..f184ba9d766 100644 --- a/src/Tasks/Microsoft.Common.CurrentVersion.targets +++ b/src/Tasks/Microsoft.Common.CurrentVersion.targets @@ -3663,7 +3663,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. Create the _CoreCompileResourceInputs list of inputs to the CoreCompile target. ============================================================ --> - + + + <_CoreCompileResourceInputs Remove="@(_CoreCompileResourceInputs)" /> <_CoreCompileResourceInputs Include="@(EmbeddedResource->'%(OutputResource)')" Condition="'%(EmbeddedResource.WithCulture)' == 'false' and '%(EmbeddedResource.Type)' == 'Resx'" /> @@ -3847,24 +3849,6 @@ Copyright (C) Microsoft Corporation. All rights reserved. ============================================================ --> - - - - <_CoreCompileResourceInputs Include="@(EmbeddedResource->'%(OutputResource)')" Condition="'%(EmbeddedResource.WithCulture)' == 'false' and '%(EmbeddedResource.Type)' == 'Resx'" /> - <_CoreCompileResourceInputs Include="@(EmbeddedResource)" Condition="'%(EmbeddedResource.WithCulture)' == 'false' and '%(EmbeddedResource.Type)' == 'Non-Resx' " /> - <_CoreCompileResourceInputs Include="@(ManifestResourceWithNoCulture)" Condition="'%(ManifestResourceWithNoCulture.EmittedForCompatibilityOnly)'==''"> - Resx - false - - <_CoreCompileResourceInputs Include="@(ManifestNonResxWithNoCultureOnDisk)" Condition="'%(ManifestNonResxWithNoCultureOnDisk.EmittedForCompatibilityOnly)'==''"> - Non-Resx - false - - - From 33d17a9fe2571fe922d74e1ce7c0d16672d5d96f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Dec 2025 10:04:55 +0000 Subject: [PATCH 4/5] Fix: Use CallTarget to ensure _GenerateCompileInputs runs in NoBuild scenarios Instead of forcing the target to always run with Outputs="", use CallTarget to explicitly invoke _GenerateCompileInputs from _GenerateCompileDependencyCache. This ensures _CoreCompileResourceInputs is populated even when MSBuild's target skipping logic would normally skip _GenerateCompileInputs. Also added PrepareResources dependency to ensure resource metadata is set before calling _GenerateCompileInputs. Added end-to-end test EmbeddedResourcesWithNoBuildPublish to verify embedded resources work correctly with NoBuild publish. Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com> --- .../ProjectCache/ProjectCacheTests.cs | 75 +++++++++++++++++++ .../Microsoft.Common.CurrentVersion.targets | 11 ++- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/Build.UnitTests/ProjectCache/ProjectCacheTests.cs b/src/Build.UnitTests/ProjectCache/ProjectCacheTests.cs index 9f0c43fe6e6..b404a6d76a7 100644 --- a/src/Build.UnitTests/ProjectCache/ProjectCacheTests.cs +++ b/src/Build.UnitTests/ProjectCache/ProjectCacheTests.cs @@ -1749,5 +1749,80 @@ static void Main() output.ShouldNotContain("A=1"); output.ShouldContain("B=1"); } + + [DotNetOnlyFact("The netfx bootstrap layout created with 'dotnet build' is incomplete")] + /// + /// Test for https://github.com/dotnet/msbuild/issues/12712 + /// Verifies that embedded resources are correctly included when using NoBuild during publish. + /// This was regressed by PR #10928 when _GenerateCompileInputs was made a dependency of _GenerateCompileDependencyCache. + /// + public void EmbeddedResourcesWithNoBuildPublish() + { + var directory = _env.CreateFolder(); + string content = ObjectModelHelpers.CleanupFileContents( + $""" + + + {s_currentTargetNETFramework} + Exe + bin/ + + + + + + """); + var projectPath = directory.CreateFile("app.csproj", content).Path; + directory.CreateFile( + "Program.cs", + """ + using System; + using System.IO; + using System.Reflection; + + class Program + { + static void Main() + { + var assembly = Assembly.GetExecutingAssembly(); + var resourceNames = assembly.GetManifestResourceNames(); + + if (resourceNames.Length == 0) + { + Console.WriteLine("ERROR: No resources found"); + Environment.Exit(1); + } + + foreach (var resourceName in resourceNames) + { + using (var stream = assembly.GetManifestResourceStream(resourceName)) + using (var reader = new StreamReader(stream)) + { + var content = reader.ReadToEnd(); + Console.WriteLine($"SUCCESS:{content}"); + } + } + } + } + """); + + // Create EmbeddedResource file + directory.CreateFile("Resource.txt", "ResourceContent"); + + // Build the project first + string output = RunnerUtilities.ExecBootstrapedMSBuild($"{projectPath} -restore", out bool success); + success.ShouldBeTrue(output); + + // Publish with NoBuild=true - this should still include embedded resources + output = RunnerUtilities.ExecBootstrapedMSBuild($"{projectPath} -t:Publish -p:NoBuild=true", out success); + success.ShouldBeTrue(output); + + string bootstrapCorePath = Path.Combine(RunnerUtilities.BootstrapRootPath, "core", Constants.DotnetProcessName); + string appDllPath = Path.Combine(directory.Path, $"bin/{s_currentTargetNETFramework}/publish/app.dll"); + + // Verify that the published app contains the embedded resource + output = RunnerUtilities.RunProcessAndGetOutput(bootstrapCorePath, $"exec \"{appDllPath}\"", out success, false, _output); + output.ShouldContain("SUCCESS:ResourceContent"); + } } } diff --git a/src/Tasks/Microsoft.Common.CurrentVersion.targets b/src/Tasks/Microsoft.Common.CurrentVersion.targets index f184ba9d766..45703f090a9 100644 --- a/src/Tasks/Microsoft.Common.CurrentVersion.targets +++ b/src/Tasks/Microsoft.Common.CurrentVersion.targets @@ -3663,7 +3663,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. Create the _CoreCompileResourceInputs list of inputs to the CoreCompile target. ============================================================ --> - + - - <_CoreCompileResourceInputs Remove="@(_CoreCompileResourceInputs)" /> <_CoreCompileResourceInputs Include="@(EmbeddedResource->'%(OutputResource)')" Condition="'%(EmbeddedResource.WithCulture)' == 'false' and '%(EmbeddedResource.Type)' == 'Resx'" /> @@ -3848,7 +3846,12 @@ Copyright (C) Microsoft Corporation. All rights reserved. contribute to incremental build inconsistencies. ============================================================ --> - + + + + From 11f38247ffef8721204473bcb9dc31f6f62e99cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Provazn=C3=ADk?= Date: Fri, 19 Dec 2025 11:33:15 +0100 Subject: [PATCH 5/5] dependency --- src/Tasks/Microsoft.Common.CurrentVersion.targets | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Tasks/Microsoft.Common.CurrentVersion.targets b/src/Tasks/Microsoft.Common.CurrentVersion.targets index 45703f090a9..335aa84778f 100644 --- a/src/Tasks/Microsoft.Common.CurrentVersion.targets +++ b/src/Tasks/Microsoft.Common.CurrentVersion.targets @@ -3661,9 +3661,10 @@ Copyright (C) Microsoft Corporation. All rights reserved. _GenerateCompileInputs Create the _CoreCompileResourceInputs list of inputs to the CoreCompile target. + Requires PrepareResources to have run first to set metadata on EmbeddedResource items. ============================================================ --> - + - - - - +