Skip to content
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

Add support for embedding C# source in portable pdb #12353

Merged
merged 4 commits into from
Aug 11, 2016

Conversation

nguerrera
Copy link
Contributor

@nguerrera nguerrera commented Jul 6, 2016

Implement #12625 for C# and portable PDBs. Native PDB and VB implementation to follow as separate change once this is approved.

Also fix #12814

@nguerrera nguerrera added the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Jul 6, 2016
@nguerrera nguerrera force-pushed the embed-source-in-pdb branch 3 times, most recently from f88dee0 to c044ec8 Compare July 7, 2016 17:20
@nguerrera nguerrera changed the title [WIP] Embed source in pdb Embed source in pdb Jul 7, 2016
@nguerrera nguerrera removed the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Jul 7, 2016
@nguerrera nguerrera changed the title Embed source in pdb Proposal: Embed source in pdb Jul 7, 2016
@tmat
Copy link
Member

tmat commented Jul 7, 2016

@tmat

@nguerrera
Copy link
Contributor Author

Reviewers: consider this PR a design proposal at this stage. I am scheduling a design review. All feedback is welcome, but you may want to hold off on reviewing the code details until that has taken place and been approved.

@nguerrera nguerrera added the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Jul 8, 2016
@nguerrera
Copy link
Contributor Author

Re-tagging as PR for personal review only. I will open a separate issue for the detailed proposal for design review and will be making updates to the proposal based on offline feedback.

@nguerrera nguerrera changed the title Proposal: Embed source in pdb [WIP] Embed source in pdb Jul 8, 2016
@nguerrera nguerrera changed the title [WIP] Embed source in pdb Embed source in pdb (WIP) Jul 8, 2016
/// <summary>
/// The source text to embed in the PDB. (If any, otherwise null.)
/// </summary>
public readonly SourceText EmbeddedText;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd name this EmbeddedTextOpt to emphasize it might be null.

@nguerrera nguerrera force-pushed the embed-source-in-pdb branch 2 times, most recently from dde8ac2 to 750d537 Compare July 19, 2016 00:22
@nguerrera nguerrera mentioned this pull request Jul 19, 2016
3 tasks
@nguerrera
Copy link
Contributor Author

I've moved all design notes to #12625 and updated them.

private void AddEmbeddedFilesToCommandLine(CommandLineBuilderExtension commandLine)
{
// If there were no additional files passed in, don't add any /additionalfile: switches
// on the command-line.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what this comment is trying to convey. Perhaps it's stale?

@@ -143,18 +153,15 @@ internal SourceText ReadFileContent(CommandLineSourceFile file, IList<Diagnostic
/// <param name="diagnostics">Storage for diagnostics.</param>
/// <param name="normalizedFilePath">If given <paramref name="file"/> opens successfully, set to normalized absolute path of the file, null otherwise.</param>
/// <returns>File content or null on failure.</returns>
internal SourceText ReadFileContent(CommandLineSourceFile file, IList<DiagnosticInfo> diagnostics, out string normalizedFilePath)
internal SourceText TryReadFileContent(CommandLineSourceFile file, IList<DiagnosticInfo> diagnostics, out string normalizedFilePath)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was for consistency re: feeback to make analogous TryReadEmbeddedFileContent express it can fail and return null. But I neglected the overload without the normalizedFilePath. I will rename that too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@gafter
Copy link
Member

gafter commented Aug 9, 2016

I have a couple of general questions that I was too lazy to search for answers myself.

  1. If we embed source files, I hope we read the source files only once from the disk. Correct?
  2. Do we preserve the bytes of embedded files intact? Or do we perchance re-encode in, say, UTF-8 to help downstream tools?

@nguerrera
Copy link
Contributor Author

nguerrera commented Aug 9, 2016

  1. Correct. (*)
  2. We preserve the original bytes, which was a lot of implementation effort but deemed necessary. See Proposal: Embed sources in PDBs #12625 (comment) and follow up. Re-encoding is lossy in the general case.

(*) Caveat: if you spell source and /embed files differently on command line that happen to be the same physical file (e.g. casing difference, symbolic link, '.\foo' vs 'foo' etc. etc.), they will be processed as distinct files. We discussed that in design review quite a bit. I came to the review with a design that did not have this problem, but it had separate mechanisms for embedding-and-compiling a source file (such that path need not be repeated) vs. embedding an additional file. The room felt that we should have just one switch and one IEnumerable emit arg and it was worth the tradeoff of reading twice for the multiple spelling case.

@gafter
Copy link
Member

gafter commented Aug 10, 2016

LGTM

@@ -130,10 +140,10 @@ internal virtual MetadataReferenceResolver GetCommandLineMetadataReferenceResolv
/// <param name="file">Source file information.</param>
/// <param name="diagnostics">Storage for diagnostics.</param>
/// <returns>File content or null on failure.</returns>
internal SourceText ReadFileContent(CommandLineSourceFile file, IList<DiagnosticInfo> diagnostics)
internal SourceText TryReadFileContent(CommandLineSourceFile file, IList<DiagnosticInfo> diagnostics)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TryReadFileContent [](start = 28, length = 18)

We sometimes use the Opt suffix for methods that may return null instead of using the Try prefix (which is more common with the bool/out pattern). I don't have strong feelings about this, though.

Copy link
Contributor Author

@nguerrera nguerrera Aug 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there's a precedent for this pattern and it was @tmat's suggestion from his earlier review, I'm going to stick with Try

@@ -10,8 +10,11 @@ internal partial class SpecializedCollections
private partial class Empty
{
internal class Set<T> : Collection<T>, ISet<T>
#if COMPILERCORE
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These ifdefs are ugly but most expedient way to make progress against the feedback. I can fix it up by tweaking closed project to include IReadOnlySet.cs after this is merged.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which feedback? In general we should avoid all #ifdef in the compiler (and Roslyn in general). They contribute negatively to the maintenance and experience of the code base.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#12353 (diff)

I realize now that I don't need to wait for this to be merged to fix the issue. I can submit a PR ASAP to closed/ to pull in IReadOnlySet.cs, then remove these. Will do!

I fully agree about ifdefs!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR sent.

@agocke
Copy link
Member

agocke commented Aug 11, 2016

LGTM

@gafter gafter merged commit 17008be into dotnet:master Aug 11, 2016
@gafter gafter added this to the 2.0 (Preview 5) milestone Aug 11, 2016
@nguerrera nguerrera deleted the embed-source-in-pdb branch August 11, 2016 23:22
@rychlym
Copy link

rychlym commented Mar 11, 2019

Hi,
could be there added a feature, that in case the all sources are embedded inside of pdb, then Url is shrink to not show the same path at the beginning?
e.g.
lets' have sources inside of following path:
c:\users\my_private_account\some_other_private_ifnfo\project\src\subdir1\file1.cs
c:\users\my_private_account\some_other_private_ifnfo\project\src\subdir1\file2.cs
...
c:\users\my_private_account\some_other_private_ifnfo\project\src\subdir_n\file_m.cs

so finally it e.g. found, the all source path starts with e.g. c:\users\my_private_account\some_other_private_ifnfo\project\src
and that is to be cut off.
so the final Url (it is actually rather meant as the name in this case) of that files embed in the pdb are like:
subdir1\file1.cs
subdir1\file2.cs
...
subdir_n\file_m.cs

I can imagine, that the feature can be introduced by a new MSBuild property EmbedAllSourcesShrinkPath, or even as an default behavior in this case the EmbedAllSources property is
set to true.

I should note it is not a critical thing - as a kind of workaround I can use subst of the path, so I can get rid off some parts of path I would like to not expose.

@tmat
Copy link
Member

tmat commented Mar 11, 2019

We actually have such feature.

Add SourceRoot mapping to your project file like so:

  <ItemGroup>
    <SourceRoot Include="$(MSBuildProjectDirectory)\" MappedPath="/_/"/>
  </ItemGroup>

and compile with /p:Deterministic=true (only needed for projects that do not import Microsoft.Net.Sdk) and /p:ContinuousIntegrationBuild=true.

Note: you should only build with /p:ContinuousIntegrationBuild=true on CI server. If you trim the paths for your dev build, the debugger won't be able to find the source files when you F5 in VS.

I'd also recommend checking out Source Link. It does the SourceRoot mapping (and more) for you.

@rychlym
Copy link

rychlym commented Mar 15, 2019

@tmat
Thanks a lot - that your comment saved my time! It is also a good design, that the SourceRoot is in the ItemGroup, because I also needed to add $(LocalAppData), because of .NET Standard AssemblyAttibutes.cs file located there. (To be honest, I am not sure, whether the $(LocalAppData) works for different platforms (linux, ios) - there might be an other, more accurate property, but that seems to be a different topic...)
To your note to the debugging: I am not on the CI server yet (I am using just a local NuGet repository and build manually)
I understood from answers of a different discussion, that a NuGet package can be nicely debugged from a private repo (I mean on a different machine accessing that repo and not accessing the source code) if the package contains the pdb with embeded source code. It seems to need following only properties to be set
like:

<PublishRepositoryUrl>false</PublishRepositoryUrl>    
<DebugType>portable</DebugType>
<EmbedAllSources>true</EmbedAllSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

and it is pretty working for me for now (some of them might not bee needed but i haven't time to check properly one by one)
(I encountered some troubles in case of package dependent on .NET Framework 3.5, which seems not to copy the pdb from the package into bin/debug folder of the consumer app, but that is also another topic).

@tmat
Copy link
Member

tmat commented Mar 15, 2019

Glad it works for you.

because of .NET Standard AssemblyAttibutes.cs file located there.

Issue and a workaround is tracked by dotnet/msbuild#1479

on .NET Framework 3.5, which seems not to copy the pdb from the package into bin/debug folder of the consumer app

Tracked here: dotnet/sdk#1458

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Gargantuan source files can be silently treated as being much smaller
7 participants