diff --git a/src/Tasks/Common/MetadataKeys.cs b/src/Tasks/Common/MetadataKeys.cs index aa0522eb3718..5569d9a584ed 100644 --- a/src/Tasks/Common/MetadataKeys.cs +++ b/src/Tasks/Common/MetadataKeys.cs @@ -129,6 +129,8 @@ internal static class MetadataKeys public const string IsVersion5 = "IsVersion5"; public const string CreateCompositeImage = "CreateCompositeImage"; public const string PerfmapFormatVersion = "PerfmapFormatVersion"; + public const string RequiresNativeLink = "RequiresNativeLink"; + public const string NativeLinkerInputPath = "NativeLinkerInputPath"; // Debug symbols public const string RelatedProperty = "related"; diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PrepareForReadyToRunCompilation.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PrepareForReadyToRunCompilation.cs index b990120d246e..423e5e6e1aea 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PrepareForReadyToRunCompilation.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PrepareForReadyToRunCompilation.cs @@ -20,6 +20,7 @@ public class PrepareForReadyToRunCompilation : TaskBase public bool EmitSymbols { get; set; } public bool ReadyToRunUseCrossgen2 { get; set; } public bool Crossgen2Composite { get; set; } + public string Crossgen2ContainerFormat { get; set; } [Required] public string OutputPath { get; set; } @@ -278,7 +279,21 @@ private void ProcessInputFileList( var compositeR2RImageRelativePath = MainAssembly.GetMetadata(MetadataKeys.RelativePath); compositeR2RImageRelativePath = Path.ChangeExtension(compositeR2RImageRelativePath, "r2r" + Path.GetExtension(compositeR2RImageRelativePath)); + + // For non-PE formats, we may need to do a post-processing step to get the final R2R image + // after running crossgen2. In this case, compositeR2RImageRelativePath is the intermediate file + // produced by crossgen2, and compositeR2RFinalImageRelativePath is the final file to be published + // by any post-crossgen2 linking steps and used at runtime. + var compositeR2RFinalImageRelativePath = compositeR2RImageRelativePath; + + if (Crossgen2ContainerFormat == "macho") + { + compositeR2RImageRelativePath = Path.ChangeExtension(compositeR2RImageRelativePath, ".o"); + compositeR2RFinalImageRelativePath = Path.ChangeExtension(compositeR2RImageRelativePath, ".dylib"); + } + var compositeR2RImage = Path.Combine(OutputPath, compositeR2RImageRelativePath); + var compositeR2RImageFinal = Path.Combine(OutputPath, compositeR2RFinalImageRelativePath); TaskItem r2rCompilationEntry = new(MainAssembly) { @@ -333,10 +348,17 @@ private void ProcessInputFileList( // Publish it TaskItem compositeR2RFileToPublish = new(MainAssembly) { - ItemSpec = compositeR2RImage + ItemSpec = compositeR2RImageFinal }; compositeR2RFileToPublish.RemoveMetadata(MetadataKeys.OriginalItemSpec); - compositeR2RFileToPublish.SetMetadata(MetadataKeys.RelativePath, compositeR2RImageRelativePath); + compositeR2RFileToPublish.SetMetadata(MetadataKeys.RelativePath, compositeR2RFinalImageRelativePath); + + if (compositeR2RImageFinal != compositeR2RImage) + { + compositeR2RFileToPublish.SetMetadata(MetadataKeys.RequiresNativeLink, "true"); + compositeR2RFileToPublish.SetMetadata(MetadataKeys.NativeLinkerInputPath, compositeR2RImage); + } + r2rFilesPublishList.Add(compositeR2RFileToPublish); } } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/RunReadyToRunCompiler.cs b/src/Tasks/Microsoft.NET.Build.Tasks/RunReadyToRunCompiler.cs index feca628b33d5..c5c7523099e7 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/RunReadyToRunCompiler.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/RunReadyToRunCompiler.cs @@ -24,6 +24,7 @@ public class RunReadyToRunCompiler : ToolTask public bool UseCrossgen2 { get; set; } public string Crossgen2ExtraCommandLineArgs { get; set; } public ITaskItem[] Crossgen2PgoFiles { get; set; } + public string Crossgen2ContainerFormat { get; set; } [Output] public bool WarningsDetected { get; set; } @@ -342,6 +343,11 @@ private string GenerateCrossgen2ResponseFile() } } + if (!string.IsNullOrEmpty(Crossgen2ContainerFormat)) + { + result.AppendLine($"--obj-format:{Crossgen2ContainerFormat}"); + } + if (!string.IsNullOrEmpty(Crossgen2ExtraCommandLineArgs)) { foreach (string extraArg in Crossgen2ExtraCommandLineArgs.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.CrossGen.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.CrossGen.targets index 60115b373731..8bd49dd1839b 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.CrossGen.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.CrossGen.targets @@ -25,6 +25,14 @@ Copyright (c) .NET Foundation. All rights reserved. true 1 false + pe + + false + false + false + false + false + false + <_IgnoreLinkerWarnings Condition="'$(_XcodeVersion)' == '16'">true + + + + + + + + @rpath/%(_ReadyToRunNativeObjectOutputs.Filename)%(_ReadyToRunNativeObjectOutputs.Extension) + + + + <_MachLinkerArg Include="-Wl,-install_name,"$(SharedLibraryInstallName)"" /> + <_MachLinkerArg Include="%(_ReadyToRunNativeObjectOutputs.NativeLinkerInputPath)" /> + <_MachLinkerArg Include="-o %(_ReadyToRunNativeObjectOutputs.Identity)" /> + + + + + + + + + + +