-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[mono] Extend MonoAOTCompiler Task #70851
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -111,6 +111,16 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task | |||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
| public bool UseDwarfDebug { get; set; } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// Path to Dotnet PGO binary (dotnet-pgo) | ||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
| public string? PgoBinaryPath { get; set; } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// NetTrace file to use when invoking dotnet-pgo for | ||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
| public string? NetTracePath { get; set; } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// File to use for profile-guided optimization, *only* the methods described in the file will be AOT compiled. | ||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
|
|
@@ -119,7 +129,7 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task | |||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// Mibc file to use for profile-guided optimization, *only* the methods described in the file will be AOT compiled. | ||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
| public string[]? MibcProfilePath { get; set; } | ||||||||||||||||||||||||
| public string[] MibcProfilePath { get; set; } = Array.Empty<string>(); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// List of profilers to use. | ||||||||||||||||||||||||
|
|
@@ -271,6 +281,20 @@ private bool ProcessAndValidateArguments() | |||||||||||||||||||||||
| if (!Directory.Exists(IntermediateOutputPath)) | ||||||||||||||||||||||||
| Directory.CreateDirectory(IntermediateOutputPath); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (!string.IsNullOrEmpty(NetTracePath)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (!File.Exists(NetTracePath)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| Log.LogError($"NetTracePath={nameof(NetTracePath)} doesn't exist"); | ||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| if (!File.Exists(PgoBinaryPath)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| Log.LogError($"NetTracePath was provided, but {nameof(PgoBinaryPath)}='{PgoBinaryPath}' doesn't exist"); | ||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (AotProfilePath != null) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| foreach (var path in AotProfilePath) | ||||||||||||||||||||||||
|
|
@@ -283,15 +307,12 @@ private bool ProcessAndValidateArguments() | |||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (MibcProfilePath != null) | ||||||||||||||||||||||||
| foreach (var path in MibcProfilePath) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| foreach (var path in MibcProfilePath) | ||||||||||||||||||||||||
| if (!File.Exists(path)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (!File.Exists(path)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| Log.LogError($"MibcProfilePath '{path}' doesn't exist."); | ||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| Log.LogError($"MibcProfilePath '{path}' doesn't exist."); | ||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
@@ -400,6 +421,39 @@ public override bool Execute() | |||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private bool ProcessNettrace(string netTraceFile) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| var outputMibcPath = Path.Combine(OutputDir, Path.ChangeExtension(Path.GetFileName(netTraceFile), ".mibc")); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (_cache!.Enabled) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| string hash = Utils.ComputeHash(netTraceFile); | ||||||||||||||||||||||||
| if (!_cache!.UpdateAndCheckHasFileChanged($"-mibc-source-file-{Path.GetFileName(netTraceFile)}", hash)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| Log.LogMessage(MessageImportance.Low, $"Skipping generating {outputMibcPath} from {netTraceFile} because source file hasn't changed"); | ||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| Log.LogMessage(MessageImportance.Low, $"Generating {outputMibcPath} from {netTraceFile} because the source file's hash has changed."); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| (int exitCode, string output) = Utils.TryRunProcess(Log, | ||||||||||||||||||||||||
| PgoBinaryPath!, | ||||||||||||||||||||||||
| $"create-mibc --trace {netTraceFile} --output {outputMibcPath}"); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (exitCode != 0) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| Log.LogError($"dotnet-pgo({PgoBinaryPath}) failed for {netTraceFile}:{output}"); | ||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| MibcProfilePath = MibcProfilePath.Append(outputMibcPath).ToArray(); | ||||||||||||||||||||||||
| Log.LogMessage(MessageImportance.Low, $"Generated {outputMibcPath} from {PgoBinaryPath}"); | ||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private bool ExecuteInternal() | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (!ProcessAndValidateArguments()) | ||||||||||||||||||||||||
|
|
@@ -417,6 +471,9 @@ private bool ExecuteInternal() | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| _cache = new FileCache(CacheFilePath, Log); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (!string.IsNullOrEmpty(NetTracePath) && !ProcessNettrace(NetTracePath)) | ||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| List<PrecompileArguments> argsList = new(); | ||||||||||||||||||||||||
| foreach (var assemblyItem in _assembliesToCompile) | ||||||||||||||||||||||||
| argsList.Add(GetPrecompileArgumentsFor(assemblyItem, monoPaths)); | ||||||||||||||||||||||||
|
|
@@ -756,7 +813,7 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st | |||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (MibcProfilePath?.Length > 0) | ||||||||||||||||||||||||
| if (MibcProfilePath.Length > 0) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| aotArgs.Add("profile-only"); | ||||||||||||||||||||||||
| foreach (var path in MibcProfilePath) | ||||||||||||||||||||||||
|
|
@@ -833,12 +890,13 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st | |||||||||||||||||||||||
| private bool PrecompileLibrary(PrecompileArguments args) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| string assembly = args.AOTAssembly.GetMetadata("FullPath"); | ||||||||||||||||||||||||
| string output; | ||||||||||||||||||||||||
| try | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| string msgPrefix = $"[{Path.GetFileName(assembly)}] "; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // run the AOT compiler | ||||||||||||||||||||||||
| (int exitCode, string output) = Utils.TryRunProcess(Log, | ||||||||||||||||||||||||
| (int exitCode, output) = Utils.TryRunProcess(Log, | ||||||||||||||||||||||||
| CompilerBinaryPath, | ||||||||||||||||||||||||
| $"--response=\"{args.ResponseFilePath}\"", | ||||||||||||||||||||||||
| args.EnvironmentVariables, | ||||||||||||||||||||||||
|
|
@@ -878,6 +936,12 @@ private bool PrecompileLibrary(PrecompileArguments args) | |||||||||||||||||||||||
| bool copied = false; | ||||||||||||||||||||||||
| foreach (var proxyFile in args.ProxyFiles) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (!File.Exists(proxyFile.TempFile)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| Log.LogError($"Precompile command succeeded, but can't find the expected temporary output file - {proxyFile.TempFile} for {assembly}.{Environment.NewLine}{output}"); | ||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check is causing some Android AOT builds to fail with: This started happening here: dotnet/android#7127 Here is the project with BuildBasicApplicationReleaseProfiledAotTrue.zip I think the file it's looking for doesn't actually exist: And this file is at: Let me know if I need to change something in the Android workload, thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Full mono-aot-cross command:
(I'll anyway prep a PR for fixing some temp file stuff) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #71411 should remove the error. But IIUC, in this case if the Maybe we should add a check to ensure that all the "expected" output files actually exist after running There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm honestly not sure about any of the intermediate files that are created here. We only really use the We also don't use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jonathanpeppers There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, we don't set this metadata at all. I think it's because we use the There were some ideas about using a native linker to do extra things (which would need the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @akoeplinger please help out with this if ankit's fix doesn't solve the issue There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code indicates that it is expecting an output file by creating this runtime/src/tasks/AotCompilerTask/MonoAOTCompiler.cs Lines 784 to 785 in cc3ac1b
So, from correctness pov it would be completely fair to check that the expected output file exists after
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see it being used at: runtime/src/tasks/AppleAppBuilder/AppleAppBuilder.cs Lines 203 to 205 in 5877e8b
runtime/src/tasks/AndroidAppBuilder/ApkBuilder.cs Lines 141 to 143 in 5877e8b
I'll make this file optional (for the existence check), and check for all other files. |
||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| copied |= proxyFile.CopyOutputFileIfChanged(); | ||||||||||||||||||||||||
| _fileWrites.Add(proxyFile.TargetFile); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
@@ -1092,8 +1156,20 @@ public FileCache(string? cacheFilePath, TaskLoggingHelper log) | |||||||||||||||||||||||
| _newCache = new(_oldCache.FileHashes); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| public bool UpdateAndCheckHasFileChanged(string filePath, string newHash) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (!Enabled) | ||||||||||||||||||||||||
| throw new InvalidOperationException("Cache is not enabled. Make sure the cache file path is set"); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| _newCache!.FileHashes[filePath] = newHash; | ||||||||||||||||||||||||
| return !_oldCache!.FileHashes.TryGetValue(filePath, out string? oldHash) || oldHash != newHash; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| public bool ShouldCopy(ProxyFile proxyFile, [NotNullWhen(true)] out string? cause) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (!Enabled) | ||||||||||||||||||||||||
| throw new InvalidOperationException("Cache is not enabled. Make sure the cache file path is set"); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| cause = null; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| string newHash = Utils.ComputeHash(proxyFile.TempFile); | ||||||||||||||||||||||||
|
|
@@ -1151,6 +1227,9 @@ public bool CopyOutputFileIfChanged() | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| try | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (!File.Exists(TempFile)) | ||||||||||||||||||||||||
| throw new LogAsErrorException($"Could not find the temporary file {TempFile} for target file {TargetFile}. Look for any errors/warnings generated earlier in the build."); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (!_cache.ShouldCopy(this, out string? cause)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| _cache.Log.LogMessage(MessageImportance.Low, $"Skipping copying over {TargetFile} as the contents are unchanged"); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.