Retry clean rebuild and preserve PCH mtimes

This commit is contained in:
patchzyy
2026-08-23 20:01:31 +02:00
parent 18e02595c4
commit 1feffcd7b0
6 changed files with 58 additions and 21 deletions
+1 -1
View File
@@ -253,7 +253,7 @@ foreach ($required in @('ToolkitFingerprint','TranslationFingerprint','NativeToo
$manifest = [ordered]@{
SchemaVersion = 2
ProductVersion = '0.2.15'
ProductVersion = '0.2.17'
ExpectedGameId = $pins.GameId
ExpectedDolSha256 = $pins.DolSha256
ExpectedRelSha256 = $pins.RelSha256
@@ -233,12 +233,13 @@ internal sealed class ProductRepairService
retroOutput = Path.Combine(scratchRoot, "retro-output");
_reporter.Progress(InstallStages.BuildBase,
"Recompiling Mario Kart Wii and Retro Rewind with the installed toolkit...", 5);
await builder.BuildAsync(_installation.Root, BuildProfile.Both, retroOutput,
requestedPayloadMode, payloadSnapshot?.Directory, cancellationToken,
toolkitComponents, forceCleanBuild,
progress: new BuildProgressWindow(_reporter, InstallStages.BuildBase, 5, 92),
retroRewindPackageDirectory: compileInputs.RetroRewindRoot,
baseOutputDirectory: baseOutput);
await BuildWithCleanRetryAsync(forceCleanBuild, clean =>
builder.BuildAsync(_installation.Root, BuildProfile.Both, retroOutput,
requestedPayloadMode, payloadSnapshot?.Directory, cancellationToken,
toolkitComponents, clean,
progress: new BuildProgressWindow(_reporter, InstallStages.BuildBase, 5, 92),
retroRewindPackageDirectory: compileInputs.RetroRewindRoot,
baseOutputDirectory: baseOutput));
LocalBuildService.WriteFingerprint(baseOutput, BuildProfile.Base, toolkitFingerprint,
dolSha, relSha, "", RetroWfcPayloadMode.NotApplicable);
LocalBuildService.WriteFingerprint(retroOutput, BuildProfile.RetroRewind,
@@ -251,10 +252,11 @@ internal sealed class ProductRepairService
baseOutput = Path.Combine(scratchRoot, "base-output");
_reporter.Progress(InstallStages.BuildBase,
"Recompiling Mario Kart Wii with the installed toolkit...", 5);
await builder.BuildAsync(_installation.Root, BuildProfile.Base, baseOutput,
RetroWfcPayloadMode.NotApplicable, null, cancellationToken,
toolkitComponents, forceCleanBuild,
progress: new BuildProgressWindow(_reporter, InstallStages.BuildBase, 5, 92));
await BuildWithCleanRetryAsync(forceCleanBuild, clean =>
builder.BuildAsync(_installation.Root, BuildProfile.Base, baseOutput,
RetroWfcPayloadMode.NotApplicable, null, cancellationToken,
toolkitComponents, clean,
progress: new BuildProgressWindow(_reporter, InstallStages.BuildBase, 5, 92)));
LocalBuildService.WriteFingerprint(baseOutput, BuildProfile.Base, toolkitFingerprint,
dolSha, relSha, "", RetroWfcPayloadMode.NotApplicable);
}
@@ -265,11 +267,12 @@ internal sealed class ProductRepairService
retroOutput = Path.Combine(scratchRoot, "retro-output");
_reporter.Progress(InstallStages.BuildRetro,
"Recompiling Retro Rewind for the canonical Code.pul...", 5);
await builder.BuildAsync(_installation.Root, BuildProfile.RetroRewind, retroOutput,
requestedPayloadMode, payloadSnapshot?.Directory, cancellationToken,
toolkitComponents, forceCleanBuild,
progress: new BuildProgressWindow(_reporter, InstallStages.BuildRetro, 5, 92),
retroRewindPackageDirectory: compileInputs.RetroRewindRoot);
await BuildWithCleanRetryAsync(forceCleanBuild, clean =>
builder.BuildAsync(_installation.Root, BuildProfile.RetroRewind, retroOutput,
requestedPayloadMode, payloadSnapshot?.Directory, cancellationToken,
toolkitComponents, clean,
progress: new BuildProgressWindow(_reporter, InstallStages.BuildRetro, 5, 92),
retroRewindPackageDirectory: compileInputs.RetroRewindRoot));
LocalBuildService.WriteFingerprint(retroOutput, BuildProfile.RetroRewind,
toolkitFingerprint, dolSha, relSha, compileInputs.CodePulSha256,
requestedPayloadMode, compileInputs.CompileInputsSha256,
@@ -465,6 +468,20 @@ internal sealed class ProductRepairService
transaction.Commit();
}
private async Task BuildWithCleanRetryAsync(bool forceCleanBuild, Func<bool, Task> build)
{
try
{
await build(forceCleanBuild);
}
catch (InvalidOperationException ex) when (!forceCleanBuild)
{
_reporter.Diagnostic(
$"Incremental recompilation failed ({ex.Message}); retrying with a clean build.");
await build(true);
}
}
private void EnsureSufficientRepairDiskSpace()
{
const long localBuildAllowance = 14L * 1024 * 1024 * 1024;
+1 -1
View File
@@ -121,7 +121,7 @@ internal static class PlatformChecks
internal static class ProductInfo
{
public const string Name = "WiiCompiled";
public const string Version = "0.2.15";
public const string Version = "0.2.17";
/// <summary>
/// The setup executable is copied into the installation under this name. It is the launcher and
+7 -2
View File
@@ -109,6 +109,9 @@ internal static class SelfTests
Directory.CreateDirectory(Path.Combine(staged, "runtime", "src"));
File.WriteAllText(Path.Combine(installed, "runtime", "src", "same.cpp"), "int same();");
File.WriteAllText(Path.Combine(staged, "runtime", "src", "same.cpp"), "int same();");
var installedSameStamp = new DateTime(2026, 1, 2, 3, 4, 5, DateTimeKind.Utc);
File.SetLastWriteTimeUtc(Path.Combine(installed, "runtime", "src", "same.cpp"),
installedSameStamp);
File.WriteAllText(Path.Combine(installed, "runtime", "src", "edited.cpp"), "int old();");
File.WriteAllText(Path.Combine(staged, "runtime", "src", "edited.cpp"), "int new_();");
File.WriteAllText(Path.Combine(staged, "runtime", "src", "added.cpp"), "int added();");
@@ -117,8 +120,10 @@ internal static class SelfTests
WorkspaceTimestamps.MarkChangedFiles(installed, staged, _ => { });
if (File.GetLastWriteTimeUtc(Path.Combine(staged, "runtime", "src", "same.cpp")).Year != 2000)
throw new Exception("An unchanged workspace file lost its normalized timestamp.");
if (File.GetLastWriteTimeUtc(Path.Combine(staged, "runtime", "src", "same.cpp")) !=
installedSameStamp)
throw new Exception("An unchanged workspace file did not inherit the installed " +
"timestamp; clang would reject the previous build's PCHs.");
if (File.GetLastWriteTimeUtc(Path.Combine(staged, "runtime", "src", "edited.cpp")).Year == 2000)
throw new Exception("A changed workspace file kept its normalized timestamp; " +
"Ninja would never recompile it.");
@@ -7,7 +7,7 @@
<AssemblyName>WiiCompiled.Setup</AssemblyName>
<RootNamespace>WiiCompiled.Setup</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Version>0.2.15</Version>
<Version>0.2.17</Version>
<Authors>patchzy</Authors>
<Product>WiiCompiled</Product>
<Description>Command-line installer and launcher for WiiCompiled</Description>
@@ -18,8 +18,12 @@ internal static class WorkspaceTimestamps
{
cancellationToken.ThrowIfCancellationRequested();
var relative = Path.GetRelativePath(stagedWorkspace, stagedFile);
if (FileUnchanged(Path.Combine(installedWorkspace, relative), stagedFile))
var installedFile = Path.Combine(installedWorkspace, relative);
if (FileUnchanged(installedFile, stagedFile))
{
// Clang validates PCH dependency mtimes by equality, so an unchanged file must
// keep the exact timestamp the previous build recorded, not the normalized one.
InheritTimestamp(installedFile, stagedFile);
unchanged++;
continue;
}
@@ -30,6 +34,17 @@ internal static class WorkspaceTimestamps
$"{unchanged} unchanged file(s) keep the incremental build cache valid.");
}
private static void InheritTimestamp(string installedFile, string stagedFile)
{
try
{
File.SetLastWriteTimeUtc(stagedFile, File.GetLastWriteTimeUtc(installedFile));
}
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
{
}
}
private static bool FileUnchanged(string installedFile, string stagedFile)
{
try