-
Notifications
You must be signed in to change notification settings - Fork 440
Source-build symbols repackaging #17454
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
e7882bb
abc74a8
292b853
b9f64fd
fe99927
afd434a
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 |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| <UsingTask AssemblyFile="$(LeakDetectionTasksAssembly)" TaskName="CheckForPoison" /> | ||
| <UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="WriteUsageBurndownData" /> | ||
| <UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="ReplaceTextInFile" /> | ||
| <UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="CreateSdkSymbolsLayout" /> | ||
|
|
||
| <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /> | ||
|
|
||
|
|
@@ -57,6 +58,84 @@ | |
| <MSBuild Projects="$(RepoProjectsDir)$(RootRepo).proj" Targets="WritePrebuiltUsageData;ReportPrebuiltUsage" /> | ||
| </Target> | ||
|
|
||
| <Target Name="DiscoverSymbolsTarballs" | ||
| AfterTargets="Build"> | ||
| <ItemGroup> | ||
| <SymbolsTarball Include="$(OutputPath)Symbols.*.tar.gz" /> | ||
| </ItemGroup> | ||
| </Target> | ||
|
|
||
| <Target Name="ExtractSymbolsTarballs" | ||
|
Member
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 should have a
Member
Author
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 don't think it's necessary due to target order in But, it won't hurt to have it here as well.
Member
Author
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. Fixed in abc74a8 |
||
| AfterTargets="Build" | ||
| DependsOnTargets="DiscoverSymbolsTarballs" | ||
| Outputs="%(SymbolsTarball.Identity)"> | ||
|
|
||
| <PropertyGroup> | ||
| <Filename>$([System.IO.Path]::GetFileName('%(SymbolsTarball.Identity)'))</Filename> | ||
| <RepositoryName>$(Filename.Split('.')[1])</RepositoryName> | ||
| <UnifiedSymbolsLayout>$(ArtifactsTmpDir)Symbols</UnifiedSymbolsLayout> | ||
| <DestinationFolder>$(UnifiedSymbolsLayout)/$(RepositoryName)</DestinationFolder> | ||
| </PropertyGroup> | ||
|
|
||
| <MakeDir Directories="$(DestinationFolder)" /> | ||
| <Exec Command="tar -xzf %(SymbolsTarball.Identity) -C $(DestinationFolder)" | ||
| WorkingDirectory="$(SymbolsRoot)" /> | ||
|
|
||
| <Delete Files="%(SymbolsTarball.Identity)" /> | ||
| </Target> | ||
|
|
||
| <!-- After building, repackage symbols into a single tarball. --> | ||
| <Target Name="RepackageSymbols" | ||
| AfterTargets="Build" | ||
| DependsOnTargets=" | ||
| DetermineMicrosoftSourceBuildIntermediateInstallerVersion; | ||
| DiscoverSymbolsTarballs; | ||
| ExtractSymbolsTarballs"> | ||
| <PropertyGroup> | ||
| <UnifiedSymbolsTarball>$(OutputPath)dotnet-symbols-$(MicrosoftSourceBuildIntermediateInstallerVersion)-$(TargetRid).tar.gz</UnifiedSymbolsTarball> | ||
| </PropertyGroup> | ||
|
|
||
| <Exec Command="tar --numeric-owner -czf $(UnifiedSymbolsTarball) *" | ||
| WorkingDirectory="$(UnifiedSymbolsLayout)" /> | ||
|
|
||
| <Message Importance="High" Text="Packaged all symbols in '$(UnifiedSymbolsTarball)'" /> | ||
| </Target> | ||
|
|
||
| <!-- After building, create the sdk symbols tarball. --> | ||
| <Target Name="CreateSdkSymbolsTarball" | ||
| AfterTargets="Build" | ||
| DependsOnTargets="RepackageSymbols"> | ||
| <ItemGroup> | ||
| <SdkTarballItem Include="$(OutputPath)dotnet-sdk-*$(TarBallExtension)" | ||
| Exclude="$(OutputPath)dotnet-sdk-symbols-*$(TarBallExtension)" /> | ||
| </ItemGroup> | ||
|
|
||
| <PropertyGroup> | ||
| <SdkSymbolsLayout>$(ArtifactsTmpDir)SdkSymbols</SdkSymbolsLayout> | ||
| <SdkSymbolsTarball>$(OutputPath)dotnet-sdk-symbols-$(MicrosoftSourceBuildIntermediateInstallerVersion)-$(TargetRid).tar.gz</SdkSymbolsTarball> | ||
| <SdkLayout>$(ArtifactsTmpDir)Sdk</SdkLayout> | ||
| <SdkTarball>%(SdkTarballItem.Identity)</SdkTarball> | ||
| </PropertyGroup> | ||
|
|
||
| <MakeDir Directories="$(SdkLayout)" /> | ||
| <Exec Command="tar -xzf $(SdkTarball) -C $(SdkLayout)" | ||
| WorkingDirectory="$(OutputPath)" /> | ||
|
|
||
| <CreateSdkSymbolsLayout SdkLayoutPath="$(SdkLayout)" | ||
| AllSymbolsPath="$(UnifiedSymbolsLayout)" | ||
| SdkSymbolsLayoutPath="$(SdkSymbolsLayout)" | ||
| FailOnMissingPDBs="true" /> | ||
|
|
||
| <Exec Command="tar --numeric-owner -czf $(SdkSymbolsTarball) *" | ||
| WorkingDirectory="$(SdkSymbolsLayout)" /> | ||
|
|
||
| <Message Importance="High" Text="Packaged sdk symbols in '$(SdkSymbolsTarball)'" /> | ||
|
|
||
| <RemoveDir Directories="$(UnifiedSymbolsLayout)" /> | ||
| <RemoveDir Directories="$(SdkSymbolsLayout)" /> | ||
| <RemoveDir Directories="$(SdkLayout)" /> | ||
| </Target> | ||
|
|
||
| <!-- | ||
| Dev scenario: rewrite a prebuilt-report. This makes it easy to add data to an existing | ||
| prebuilt report without performing another full build. This doesn't reevalutate which packages | ||
|
|
@@ -104,7 +183,8 @@ | |
|
|
||
| <Target Name="RunSmokeTest"> | ||
| <ItemGroup> | ||
| <SdkTarballItem Include="$(SourceBuiltTarBallPath)**/dotnet-sdk*$(TarBallExtension)" /> | ||
| <SdkTarballItem Include="$(SourceBuiltTarBallPath)**/dotnet-sdk*$(TarBallExtension)" | ||
| Exclude="$(SourceBuiltTarBallPath)**/dotnet-sdk-symbols*$(TarBallExtension)" /> | ||
| <SourceBuiltArtifactsItem Include="$(SourceBuiltTarBallPath)**/Private.SourceBuilt.Artifacts.*$(TarBallExtension)" /> | ||
| </ItemGroup> | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
| // See the LICENSE file in the project root for more information. | ||
|
|
||
| using System; | ||
| using System.Collections; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.Reflection.Metadata; | ||
| using System.Reflection.PortableExecutable; | ||
| using Microsoft.Build.Framework; | ||
| using Microsoft.Build.Utilities; | ||
|
|
||
| namespace Microsoft.DotNet.Build.Tasks | ||
| { | ||
| // Creates a symbols layout that matches the SDK layout | ||
| public class CreateSdkSymbolsLayout : Task | ||
| { | ||
| /// <summary> | ||
| /// Path to SDK layout. | ||
| /// </summary> | ||
| [Required] | ||
| public string SdkLayoutPath { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Path to all source-built symbols, flat or with folder hierarchy. | ||
| /// </summary> | ||
| [Required] | ||
| public string AllSymbolsPath { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Path to SDK symbols layout - will be created if it doesn't exist. | ||
| /// </summary> | ||
| [Required] | ||
| public string SdkSymbolsLayoutPath { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// If true, fails the build if any PDBs are missing. | ||
| /// </summary> | ||
| public bool FailOnMissingPDBs { get; set; } | ||
|
|
||
| public override bool Execute() | ||
| { | ||
| IList<string> filesWithoutPDBs = GenerateSymbolsLayout(IndexAllSymbols()); | ||
| if (filesWithoutPDBs.Count > 0) | ||
| { | ||
| LogErrorOrWarning(FailOnMissingPDBs, $"Did not find PDBs for the following SDK files:"); | ||
| foreach (string file in filesWithoutPDBs) | ||
| { | ||
| LogErrorOrWarning(FailOnMissingPDBs, file); | ||
| } | ||
| } | ||
|
|
||
| return !Log.HasLoggedErrors; | ||
| } | ||
|
|
||
| private void LogErrorOrWarning(bool isError, string message) | ||
| { | ||
| if (FailOnMissingPDBs) | ||
| { | ||
| Log.LogError(message); | ||
| } | ||
| else | ||
| { | ||
| Log.LogWarning(message); | ||
| } | ||
| } | ||
|
|
||
| private IList<string> GenerateSymbolsLayout(Hashtable allPdbGuids) | ||
| { | ||
| List<string> filesWithoutPDBs = new List<string>(); | ||
|
|
||
| if (Directory.Exists(SdkSymbolsLayoutPath)) | ||
| { | ||
| Directory.Delete(SdkSymbolsLayoutPath, true); | ||
| } | ||
|
|
||
| foreach (string file in Directory.GetFiles(SdkLayoutPath, "*", SearchOption.AllDirectories)) | ||
| { | ||
| if (file.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) && | ||
| !file.EndsWith(".resources.dll", StringComparison.InvariantCultureIgnoreCase)) | ||
| { | ||
| string guid = string.Empty; | ||
| using var pdbStream = File.OpenRead(file); | ||
| using var peReader = new PEReader(pdbStream); | ||
| try | ||
| { | ||
| // Check if pdb is embedded | ||
| if (peReader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb)) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| var debugDirectory = peReader.ReadDebugDirectory().First(entry => entry.Type == DebugDirectoryEntryType.CodeView); | ||
| var codeViewData = peReader.ReadCodeViewDebugDirectoryData(debugDirectory); | ||
| guid = $"{codeViewData.Guid.ToString("N").Replace("-", string.Empty)}"; | ||
| } | ||
| catch (Exception e) when (e is BadImageFormatException || e is InvalidOperationException) | ||
| { | ||
| // Ignore binaries without debug info | ||
| continue; | ||
| } | ||
|
|
||
| if (guid != string.Empty) | ||
| { | ||
| if (!allPdbGuids.ContainsKey(guid)) | ||
| { | ||
| filesWithoutPDBs.Add(file.Substring(SdkLayoutPath.Length + 1)); | ||
| } | ||
| else | ||
| { | ||
| // Copy matching pdb to symbols path, preserving sdk binary's hierarchy | ||
| string sourcePath = (string)allPdbGuids[guid]!; | ||
| string destinationPath = | ||
| file.Replace(SdkLayoutPath, SdkSymbolsLayoutPath) | ||
| .Replace(Path.GetFileName(file), Path.GetFileName(sourcePath)); | ||
|
|
||
| Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)!); | ||
| File.Copy(sourcePath, destinationPath, true); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return filesWithoutPDBs; | ||
| } | ||
|
|
||
| public Hashtable IndexAllSymbols() | ||
| { | ||
| Hashtable allPdbGuids = new Hashtable(); | ||
|
|
||
| foreach (string file in Directory.GetFiles(AllSymbolsPath, "*.pdb", SearchOption.AllDirectories)) | ||
| { | ||
| using var pdbFileStream = File.OpenRead(file); | ||
| var metadataProvider = MetadataReaderProvider.FromPortablePdbStream(pdbFileStream); | ||
| var metadataReader = metadataProvider.GetMetadataReader(); | ||
| if (metadataReader.DebugMetadataHeader == null) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| var id = new BlobContentId(metadataReader.DebugMetadataHeader.Id); | ||
| string guid = $"{id.Guid:N}"; | ||
| if (!string.IsNullOrEmpty(guid) && !allPdbGuids.ContainsKey(guid)) | ||
| { | ||
| allPdbGuids.Add(guid, file); | ||
| } | ||
| } | ||
|
|
||
| return allPdbGuids; | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.