-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fix MauiFont and MauiSplashScreen assets missing on first/incremental builds #34567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jfversluis
wants to merge
4
commits into
main
Choose a base branch
from
fix/font-copy-first-build-main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+169
−17
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
3de8728
Fix MauiFont assets missing on first build (Android)
jfversluis 5b98890
Add regression tests for ProcessMauiFonts target structure
jfversluis 7886195
Fix splash screen incremental build bug (#33092)
jfversluis 6e1efe9
Rename test file to match class name
jfversluis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
src/SingleProject/Resizetizer/test/UnitTests/ResizetizeTargetStructureTests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| using System; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.Xml.Linq; | ||
| using Xunit; | ||
| using Xunit.Abstractions; | ||
|
|
||
| namespace Microsoft.Maui.Resizetizer.Tests | ||
| { | ||
| /// <summary> | ||
| /// Verifies the MSBuild target structure in Microsoft.Maui.Resizetizer.After.targets | ||
| /// to prevent regression of the "fonts missing on first build" bug (#23268) and | ||
| /// the "splash screens randomly missing" bug (#33092). | ||
| /// | ||
| /// Root cause: ProcessMauiFonts and ProcessMauiSplashScreens used Inputs/Outputs | ||
| /// for incremental builds. When the target was skipped (stamp file up-to-date), | ||
| /// platform item groups (AndroidAsset, BundleResource, etc.) were never populated | ||
| /// — causing fonts/splash screens to silently disappear from build output. | ||
| /// </summary> | ||
| public class ResizetizeTargetStructureTests | ||
| { | ||
| static readonly XNamespace MSBuildNs = "http://schemas.microsoft.com/developer/msbuild/2003"; | ||
|
|
||
| readonly ITestOutputHelper _output; | ||
| readonly XDocument _targetsDoc; | ||
|
|
||
| public ResizetizeTargetStructureTests(ITestOutputHelper output) | ||
| { | ||
| _output = output; | ||
|
|
||
| // Navigate from test output dir (artifacts/bin/.../net10.0/) to repo root | ||
| var repoRoot = Path.GetFullPath(Path.Combine( | ||
| Directory.GetCurrentDirectory(), "..", "..", "..", "..", "..")); | ||
| var targetsFilePath = Path.Combine(repoRoot, | ||
| "src", "SingleProject", "Resizetizer", "src", "nuget", | ||
| "buildTransitive", "Microsoft.Maui.Resizetizer.After.targets"); | ||
|
|
||
| Assert.True(File.Exists(targetsFilePath), | ||
| $"Targets file not found at: {targetsFilePath}"); | ||
| _output.WriteLine($"Loading targets from: {targetsFilePath}"); | ||
|
|
||
| _targetsDoc = XDocument.Load(targetsFilePath); | ||
| } | ||
|
|
||
| XElement FindTarget(string name) => | ||
| _targetsDoc.Root! | ||
| .Elements(MSBuildNs + "Target") | ||
| .FirstOrDefault(t => t.Attribute("Name")?.Value == name); | ||
|
|
||
| XElement FindAndroidPropertyGroup() => | ||
| _targetsDoc.Root! | ||
| .Elements(MSBuildNs + "PropertyGroup") | ||
| .FirstOrDefault(pg => | ||
| { | ||
| var cond = pg.Attribute("Condition")?.Value; | ||
| return cond != null | ||
| && cond.Contains("_ResizetizerIsAndroidApp", StringComparison.Ordinal) | ||
| && !cond.Contains("_ResizetizerIsiOSApp", StringComparison.Ordinal); | ||
| }); | ||
|
|
||
| // ────────────────────────────────────────────────────────── | ||
| // ProcessMauiFonts — #23268 | ||
| // ────────────────────────────────────────────────────────── | ||
|
|
||
| [Fact] | ||
| public void ProcessMauiFonts_ShouldNotHaveInputsAttribute() | ||
| { | ||
| var target = FindTarget("ProcessMauiFonts"); | ||
| Assert.NotNull(target); | ||
| Assert.True(target.Attribute("Inputs") is null, | ||
| "ProcessMauiFonts must not use Inputs for incremental builds. " + | ||
| "See https://github.com/dotnet/maui/issues/23268"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void ProcessMauiFonts_ShouldNotHaveOutputsAttribute() | ||
| { | ||
| var target = FindTarget("ProcessMauiFonts"); | ||
| Assert.NotNull(target); | ||
| Assert.True(target.Attribute("Outputs") is null, | ||
| "ProcessMauiFonts must not use Outputs for incremental builds. " + | ||
| "See https://github.com/dotnet/maui/issues/23268"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Android_ProcessMauiFontsBeforeTargets_ShouldIncludeComputeAndroidAssetsPaths() | ||
| { | ||
| var androidPG = FindAndroidPropertyGroup(); | ||
| Assert.NotNull(androidPG); | ||
|
|
||
| var beforeTargets = androidPG.Element(MSBuildNs + "ProcessMauiFontsBeforeTargets"); | ||
| Assert.NotNull(beforeTargets); | ||
| Assert.Contains("_ComputeAndroidAssetsPaths", beforeTargets.Value, StringComparison.Ordinal); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void ProcessMauiFonts_MatchesWorkingProcessMauiAssetsPattern() | ||
| { | ||
| var assetsTarget = FindTarget("ProcessMauiAssets"); | ||
| Assert.NotNull(assetsTarget); | ||
| Assert.Null(assetsTarget.Attribute("Inputs")); | ||
| Assert.Null(assetsTarget.Attribute("Outputs")); | ||
|
|
||
| var fontsTarget = FindTarget("ProcessMauiFonts"); | ||
| Assert.NotNull(fontsTarget); | ||
| Assert.Null(fontsTarget.Attribute("Inputs")); | ||
| Assert.Null(fontsTarget.Attribute("Outputs")); | ||
| } | ||
|
|
||
| // ────────────────────────────────────────────────────────── | ||
| // ProcessMauiSplashScreens — #33092 | ||
| // ────────────────────────────────────────────────────────── | ||
|
|
||
| /// <summary> | ||
| /// ProcessMauiSplashScreens must NOT have Inputs. Same root cause as fonts: | ||
| /// when skipped, platform item groups (LibraryResourceDirectories, | ||
| /// BundleResource, ContentWithTargetPath) may not be populated, causing | ||
| /// splash screens to randomly disappear from builds. | ||
| /// The custom tasks (GenerateSplashAndroidResources, etc.) have built-in | ||
| /// file-level incrementality via Resizer.IsUpToDate(), so removing | ||
| /// Inputs/Outputs does not cause expensive re-rendering. | ||
| /// </summary> | ||
| [Fact] | ||
| public void ProcessMauiSplashScreens_ShouldNotHaveInputsAttribute() | ||
| { | ||
| var target = FindTarget("ProcessMauiSplashScreens"); | ||
| Assert.NotNull(target); | ||
| Assert.True(target.Attribute("Inputs") is null, | ||
| "ProcessMauiSplashScreens must not use Inputs for incremental builds. " + | ||
| "See https://github.com/dotnet/maui/issues/33092"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void ProcessMauiSplashScreens_ShouldNotHaveOutputsAttribute() | ||
| { | ||
| var target = FindTarget("ProcessMauiSplashScreens"); | ||
| Assert.NotNull(target); | ||
| Assert.True(target.Attribute("Outputs") is null, | ||
| "ProcessMauiSplashScreens must not use Outputs for incremental builds. " + | ||
| "See https://github.com/dotnet/maui/issues/33092"); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// All three content-producing targets should follow the same pattern | ||
| /// as ProcessMauiAssets (no Inputs/Outputs). | ||
| /// </summary> | ||
| [Fact] | ||
| public void AllContentTargets_FollowProcessMauiAssetsPattern() | ||
| { | ||
| foreach (var targetName in new[] { "ProcessMauiAssets", "ProcessMauiFonts", "ProcessMauiSplashScreens" }) | ||
| { | ||
| var target = FindTarget(targetName); | ||
| Assert.NotNull(target); | ||
| Assert.True(target.Attribute("Inputs") is null, | ||
| $"{targetName} must not use Inputs. See #23268 / #33092"); | ||
| Assert.True(target.Attribute("Outputs") is null, | ||
| $"{targetName} must not use Outputs. See #23268 / #33092"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.