| File: Crossgen.cs | Web Access |
| Project: src\sdk\src\Tasks\sdk-tasks\sdk-tasks.csproj (sdk-tasks) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable namespace Microsoft.DotNet.Build.Tasks { public sealed class Crossgen : ToolTask { [Required] public string SourceAssembly { get;set; } [Required] public string DestinationPath { get; set; } [Required] public string TargetArchitecture { get; set; } [Required] public string TargetOS { get; set; } public string CrossgenPath { get; set; } public bool CreateSymbols { get; set; } public ITaskItem[] PlatformAssemblyPaths { get; set; } private string TempOutputPath { get; set; } protected override bool ValidateParameters() { base.ValidateParameters(); if (!File.Exists(SourceAssembly)) { Log.LogError($"SourceAssembly '{SourceAssembly}' does not exist."); return false; } return true; } public override bool Execute() { string tempDirPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(tempDirPath); TempOutputPath = Path.Combine(tempDirPath, Path.GetFileName(DestinationPath)); var toolResult = base.Execute(); if (toolResult) { var files = Directory.GetFiles(Path.GetDirectoryName(TempOutputPath)); var destination = Path.GetDirectoryName(DestinationPath); // Copy both dll and pdb files to the destination folder foreach(var file in files) { File.Copy(file, Path.Combine(destination, Path.GetFileName(file)), overwrite: true); // Delete file in temp File.Delete(file); } } if (File.Exists(TempOutputPath)) { File.Delete(TempOutputPath); } Directory.Delete(tempDirPath); return toolResult; } protected override string ToolName => "crossgen2"; // Default is low, but we want to see output at normal verbosity. protected override MessageImportance StandardOutputLoggingImportance => MessageImportance.Normal; // This turns stderr messages into msbuild errors below. protected override MessageImportance StandardErrorLoggingImportance => MessageImportance.High; protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance) { // Crossgen's error/warning formatting is inconsistent and so we do // not use the "canonical error format" handling of base. // // Furthermore, we don't want to log crossgen warnings as msbuild // warnings because we cannot prevent them and they are only // occasionally formatted as something that base would recognize as // a canonically formatted warning anyway. // // One thing that is consistent is that crossgen errors go to stderr // and everything else goes to stdout. Above, we set stderr to high // importance above, and stdout to normal. So we can use that here // to distinguish between errors and messages. if (messageImportance == MessageImportance.High) { Log.LogError(singleLine); } else { Log.LogMessage(messageImportance, singleLine); } } protected override string GenerateFullPathToTool() => CrossgenPath ?? "crossgen2"; protected override string GenerateCommandLineCommands() => $"{GetInPath()} {GetOutPath()} {GetTargetOS()} {GetArchitecture()} {GetPlatformAssemblyPaths()} {GetCreateSymbols()}"; private string GetArchitecture() => $"--targetarch {TargetArchitecture}"; private string GetTargetOS() => $"--targetos {TargetOS}"; private string GetCreateSymbols() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "--pdb" : "--perfmap"; private string GetInPath() => $"\"{SourceAssembly}\""; private string GetOutPath() => $"-o \"{TempOutputPath}\""; private string GetPlatformAssemblyPaths() { var platformAssemblyPaths = string.Empty; if (PlatformAssemblyPaths != null) { foreach (var excludeTaskItem in PlatformAssemblyPaths) { platformAssemblyPaths += $"-r {excludeTaskItem.ItemSpec}{Path.DirectorySeparatorChar}*.dll "; } } return platformAssemblyPaths; } protected override void LogToolCommand(string message) => base.LogToolCommand($"{GetWorkingDirectory()}> {message}"); } }