Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@
<_ResizetizerOutputsFile>$(_ResizetizerIntermediateOutputPath)mauiimage.outputs</_ResizetizerOutputsFile>
<_ResizetizerStampFile>$(_ResizetizerIntermediateOutputPath)mauiimage.stamp</_ResizetizerStampFile>
<_MauiFontInputsFile>$(_ResizetizerIntermediateOutputPath)mauifont.inputs</_MauiFontInputsFile>
<_MauiFontStampFile>$(_ResizetizerIntermediateOutputPath)mauifont.stamp</_MauiFontStampFile>
<_MauiFontOutputsFile>$(_ResizetizerIntermediateOutputPath)mauifont.outputs</_MauiFontOutputsFile>
<_MauiSplashInputsFile>$(_ResizetizerIntermediateOutputPath)mauisplash.inputs</_MauiSplashInputsFile>
<_MauiSplashStampFile>$(_ResizetizerIntermediateOutputPath)mauisplash.stamp</_MauiSplashStampFile>
<_MauiSplashOutputsFile>$(_ResizetizerIntermediateOutputPath)mauisplash.outputs</_MauiSplashOutputsFile>
<_MauiManifestStampFile>$(_ResizetizerIntermediateOutputPath)mauimanifest.stamp</_MauiManifestStampFile>

<_ResizetizerIntermediateOutputRoot>$(_ResizetizerIntermediateOutputPath)resizetizer\</_ResizetizerIntermediateOutputRoot>
Expand Down Expand Up @@ -120,11 +120,16 @@
ProcessMauiSplashScreens;
_ReadResizetizeImagesOutputs;
</ResizetizeDependsOnTargets>
<ProcessMauiSplashScreensDependsOnTargets>
$(ProcessMauiSplashScreensDependsOnTargets);
_ReadMauiSplashOutputs;
</ProcessMauiSplashScreensDependsOnTargets>
<ProcessMauiFontsDependsOnTargets>
$(ProcessMauiFontsDependsOnTargets);
ResizetizeCollectItems;
ProcessMauiAssets;
ProcessMauiSplashScreens;
_ReadMauiFontOutputs;
</ProcessMauiFontsDependsOnTargets>
</PropertyGroup>

Expand Down Expand Up @@ -399,7 +404,8 @@
<Target Name="ProcessMauiSplashScreens"
Condition="'$(EnableMauiSplashScreenProcessing)' == 'true'"
Inputs="$(MSBuildThisFileFullPath);$(_ResizetizerTaskAssemblyName);$(_MauiSplashInputsFile);@(MauiSplashScreen)"
Outputs="$(_MauiSplashStampFile)">
Outputs="$(_MauiSplashOutputsFile);@(_MauiSplashOutputs)"
DependsOnTargets="$(ProcessMauiSplashScreensDependsOnTargets)">

<PropertyGroup>
<_MauiHasSplashScreens>false</_MauiHasSplashScreens>
Expand Down Expand Up @@ -505,21 +511,33 @@
<TizenTpkUserIncludeFiles Include="@(_MauiSplashScreens)" TizenTpkSubDir="shared\res\splash" />
</ItemGroup>

<!-- Stamp file for Outputs -->
<MakeDir Directories="$(_ResizetizerIntermediateOutputPath)"/>
<Touch Files="$(_MauiSplashStampFile)" AlwaysCreate="True" />
<WriteLinesToFile
File="$(_MauiSplashOutputsFile)"
Lines="@(_MauiSplashAssets->'%(FullPath)')"
Overwrite="true"
WriteOnlyWhenDifferent="true"
/>
<Touch Files="$(_MauiSplashOutputsFile)" AlwaysCreate="True" />
<Touch Files="@(_MauiSplashAssets)" Condition="'@(_MauiSplashAssets)' != ''" />

<ItemGroup>
<FileWrites Include="@(_MauiSplashAssets)" />
<FileWrites Include="$(_MauiSplashStampFile)" />
<FileWrites Include="$(_MauiSplashOutputsFile)" />
</ItemGroup>

</Target>

<Target Name="_ReadMauiSplashOutputs">
<ReadLinesFromFile File="$(_MauiSplashOutputsFile)" Condition="Exists ('$(_MauiSplashOutputsFile)')">
<Output TaskParameter="Lines" ItemName="_MauiSplashOutputs" />
</ReadLinesFromFile>
</Target>

<Target Name="ProcessMauiFonts"
Condition="'$(EnableMauiFontProcessing)' == 'true'"
Inputs="$(MSBuildThisFileFullPath);$(_ResizetizerTaskAssemblyName);$(_MauiFontInputsFile);@(MauiFont)"
Outputs="$(_MauiFontStampFile)"
Outputs="$(_MauiFontOutputsFile);@(_MauiFontOutputs)"
AfterTargets="$(ProcessMauiFontsAfterTargets)"
BeforeTargets="$(ProcessMauiFontsBeforeTargets)"
DependsOnTargets="$(ProcessMauiFontsDependsOnTargets)">
Expand All @@ -531,7 +549,7 @@
SkipUnchangedFiles="true" />

<ItemGroup>
<_MauiFontCopied Include="$(_MauiIntermediateFonts)*" />
<_MauiFontCopied Include="$(_MauiIntermediateFonts)*" Exclude="$(_MauiIntermediateFonts)MauiInfo.plist" />
</ItemGroup>

<!-- iOS -->
Expand Down Expand Up @@ -595,16 +613,30 @@
<TizenTpkUserIncludeFiles Include="@(_MauiFontCopied)" Condition="'@(_MauiFontCopied)' != ''" TizenTpkSubDir="res\fonts\" />
</ItemGroup>

<!-- Touch/create our stamp file for outputs -->
<Touch Files="$(_MauiFontStampFile)" AlwaysCreate="True" />
<Touch Files="@(_MauiFontCopied)" Condition="'@(_MauiFontCopied)' != ''" />

<!-- Include our fonts and stamp file as filewrites so they don't get rm'd -->
<MakeDir Directories="$(_ResizetizerIntermediateOutputPath)"/>
<WriteLinesToFile
File="$(_MauiFontOutputsFile)"
Lines="@(_MauiFontCopied->'%(FullPath)');@(_MauiFontPListFiles->'%(FullPath)')"
Comment thread
jfversluis marked this conversation as resolved.
Comment thread
jfversluis marked this conversation as resolved.
Overwrite="true"
WriteOnlyWhenDifferent="true"
/>
<Touch Files="$(_MauiFontOutputsFile)" AlwaysCreate="True" />

<!-- Include our fonts and output manifest as filewrites so they don't get rm'd -->
<ItemGroup>
<FileWrites Include="$(_MauiFontStampFile)" />
<FileWrites Include="$(_MauiFontOutputsFile)" />
<FileWrites Include="@(_MauiFontCopied)" />
</ItemGroup>
</Target>

<Target Name="_ReadMauiFontOutputs">
<ReadLinesFromFile File="$(_MauiFontOutputsFile)" Condition="Exists ('$(_MauiFontOutputsFile)')">
<Output TaskParameter="Lines" ItemName="_MauiFontOutputs" />
</ReadLinesFromFile>
</Target>

<Target Name="_ReadResizetizeImagesOutputs">
<ReadLinesFromFile File="$(_ResizetizerOutputsFile)" Condition="Exists ('$(_ResizetizerOutputsFile)')">
<Output TaskParameter="Lines" ItemName="_ResizetizerOutputs" />
Expand Down
108 changes: 108 additions & 0 deletions src/TestUtils/src/Microsoft.Maui.IntegrationTests/ResizetizerTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using Microsoft.Build.Framework;
using Microsoft.Build.Logging.StructuredLogger;

namespace Microsoft.Maui.IntegrationTests;

[Trait("Category", "Build")]
Expand Down Expand Up @@ -99,4 +102,109 @@ public void CollectsAssets(string id, string libid, bool unpackaged)
Assert.True(File.Exists(Path.Combine(appDir, $"obj\\Debug\\{DotNetCurrent}-windows10.0.19041.0\\win-x64\\resizetizer\\r\\the_image.scale-100.png")),
"Windows was missing the image file.");
}

[Fact]
public void BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing()
{
SetTestIdentifier("MissingResizetizerOutputs");

var projectDir = TestDirectory;
var projectFile = Path.Combine(projectDir, $"{Path.GetFileName(projectDir)}.csproj");
const string config = "Debug";

Assert.True(DotnetInternal.New("maui", projectDir, DotNetCurrent, output: _output),
$"Unable to create template maui. Check test output for errors.");

Assert.True(DotnetInternal.Build(projectFile, config, properties: BuildProps, output: _output),
$"Project {Path.GetFileName(projectFile)} failed to build. Check test output/attachments for errors.");

var intermediateOutputRoots = GetResizetizerOutputRoots(projectDir, config);
AssertBuiltTargetPlatforms(intermediateOutputRoots);
AssertIntermediateOutputsExist(intermediateOutputRoots);

foreach (var intermediateOutputRoot in intermediateOutputRoots)
{
DeleteDirectory(Path.Combine(intermediateOutputRoot, "resizetizer", "f"));
DeleteDirectory(Path.Combine(intermediateOutputRoot, "resizetizer", "sp"));
}

Assert.True(DotnetInternal.Build(projectFile, config, properties: BuildProps, output: _output),
$"Project {Path.GetFileName(projectFile)} failed to rebuild. Check test output/attachments for errors.");

AssertIntermediateOutputsExist(intermediateOutputRoots);

var noOpBinlogPath = Path.Combine(projectDir, "no-op.binlog");
Assert.True(DotnetInternal.Build(projectFile, config, properties: BuildProps, binlogPath: noOpBinlogPath, output: _output),
$"Project {Path.GetFileName(projectFile)} failed to no-op rebuild. Check test output/attachments for errors.");

AssertTargetSkipped(noOpBinlogPath, "ProcessMauiFonts", intermediateOutputRoots.Count);
AssertTargetSkipped(noOpBinlogPath, "ProcessMauiSplashScreens", intermediateOutputRoots.Count);
AssertIntermediateOutputsExist(intermediateOutputRoots);
}

static IReadOnlyList<string> GetResizetizerOutputRoots(string projectDir, string config)
{
var intermediateOutputPath = Path.Combine(projectDir, "obj", config);
var outputRoots = Directory
.GetFiles(intermediateOutputPath, "mauifont.outputs", SearchOption.AllDirectories)
.Select(Path.GetDirectoryName)
.Where(root => root is not null && File.Exists(Path.Combine(root, "mauisplash.outputs")))
.Cast<string>()
.OrderBy(root => root, StringComparer.OrdinalIgnoreCase)
.ToArray();

Assert.NotEmpty(outputRoots);
return outputRoots;
}

static void AssertBuiltTargetPlatforms(IReadOnlyList<string> intermediateOutputRoots)
{
Assert.Contains(intermediateOutputRoots, root => ContainsTargetFramework(root, $"{DotNetCurrent}-android"));
Assert.Contains(intermediateOutputRoots, root => ContainsTargetFramework(root, $"{DotNetCurrent}-ios"));
Assert.Contains(intermediateOutputRoots, root => ContainsTargetFramework(root, $"{DotNetCurrent}-maccatalyst"));

if (TestEnvironment.IsWindows)
Assert.Contains(intermediateOutputRoots, root => ContainsTargetFramework(root, $"{DotNetCurrent}-windows"));
}

static bool ContainsTargetFramework(string path, string targetFramework) =>
path.Contains(targetFramework, StringComparison.OrdinalIgnoreCase);

static void AssertIntermediateOutputsExist(IReadOnlyList<string> intermediateOutputRoots)
{
foreach (var intermediateOutputRoot in intermediateOutputRoots)
{
var fontsDir = Path.Combine(intermediateOutputRoot, "resizetizer", "f");
Assert.True(File.Exists(Path.Combine(fontsDir, "OpenSans-Regular.ttf")),
$"Missing OpenSans-Regular.ttf in {fontsDir}.");
Assert.True(File.Exists(Path.Combine(fontsDir, "OpenSans-Semibold.ttf")),
$"Missing OpenSans-Semibold.ttf in {fontsDir}.");

if (!ContainsTargetFramework(intermediateOutputRoot, $"{DotNetCurrent}-maccatalyst"))
{
var splashDir = Path.Combine(intermediateOutputRoot, "resizetizer", "sp");
Assert.True(
Directory.Exists(splashDir) && Directory.EnumerateFiles(splashDir, "*", SearchOption.AllDirectories).Any(),
$"Missing generated splash screen files in {splashDir}.");
}
}
}

static void DeleteDirectory(string path)
{
if (Directory.Exists(path))
Directory.Delete(path, recursive: true);
}

static void AssertTargetSkipped(string binlogPath, string targetName, int minimumSkipCount)
{
var skipCount = new BinLogReader()
.ReadRecords(binlogPath)
.Count(record => record.Args is BuildMessageEventArgs { Message: string message } &&
message.Contains($"Skipping target \"{targetName}\"", StringComparison.Ordinal) &&
message.Contains("because all output files are up-to-date", StringComparison.OrdinalIgnoreCase));

Assert.True(skipCount >= minimumSkipCount,
$"Expected target '{targetName}' to be skipped at least {minimumSkipCount} times, but found {skipCount}. See binlog: {binlogPath}");
}
}
Loading