Skip to content

Explicit Microsoft.SourceLink.GitHub PackageReference silently disables SourceLink on .NET 8+ SDKs #1652

Description

@thomhurst

Summary

On SDKs that bundle SourceLink as implicit SDKs (.NET 8+), adding an explicit <PackageReference Include=\"Microsoft.SourceLink.GitHub\" PrivateAssets=\"all\" /> silently disables SourceLink rather than enabling or replacing it. Build succeeds with no warnings, but resulting packages have:

  • No SourceLink JSON in the PDB
  • No PathMap normalization (paths remain non-deterministic)
  • Reproducible debug entry is still set, so the PE looks deterministic by header, but embedded source paths are not mapped

The docs (both the README and many blog posts/templates) still instruct users to add this package. On a modern SDK, following that guidance breaks SourceLink.

Environment

  • .NET SDK: 10.0.202 (also confirmed in 11.0.100-preview.2)
  • Microsoft.SourceLink.GitHub NuGet package: 10.0.202
  • Central Package Management via Directory.Packages.props with GlobalPackageReference
  • Strong-named, multi-targeted library (netstandard2.0;net8.0;net9.0;net10.0)

Reproduction

Directory.Packages.props:

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>
  <ItemGroup>
    <GlobalPackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"10.0.202\" PrivateAssets=\"all\" />
  </ItemGroup>
</Project>

Directory.Build.props:

<Project>
  <PropertyGroup>
    <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
    <EmbedUntrackedSources>true</EmbedUntrackedSources>
  </PropertyGroup>
</Project>

Then dotnet build -c Release. Inspect the produced PDB — no SourceLink custom debug information entry (CC110556-A091-4D38-9FEC-25AB9A351A6A), no obj/*/*.sourcelink.json file.

Root cause trace

  1. NuGet restores Microsoft.SourceLink.GitHub directly and imports its build/Microsoft.SourceLink.GitHub.props/.targets.
  2. Its transitive deps (Microsoft.SourceLink.Common, Microsoft.Build.Tasks.Git) resolve in project.assets.json as \"buildTransitive/_._\": {} — the empty-assets marker — because developmentDependency=true packages don't flow their build assets through a PrivateAssets=all parent. Common's InitializeSourceControlInformation.targets / Microsoft.SourceLink.Common.targets never get imported via NuGet.
  3. NuGet still generates the PkgMicrosoft_SourceLink_Common path property (from restore), even though its build assets are _._.
  4. The SDK-bundled Microsoft.NET.Sdk.SourceLink.props contains:
    <SuppressImplicitGitSourceLink Condition=\"'$(PkgMicrosoft_SourceLink_Common)' != ''\">true</SuppressImplicitGitSourceLink>
    <ImportGroup Condition=\"'$(SuppressImplicitGitSourceLink)' != 'true'\">
      <Import Project=\"...\Microsoft.Build.Tasks.Git\build\Microsoft.Build.Tasks.Git.props\" />
      <Import Project=\"...\Microsoft.SourceLink.Common\build\Microsoft.SourceLink.Common.props\" />
      <Import Project=\"...\Microsoft.SourceLink.GitHub\build\Microsoft.SourceLink.GitHub.props\" />
      ...
    </ImportGroup>
    Because PkgMicrosoft_SourceLink_Common is now set, SuppressImplicitGitSourceLink=true fires → SDK's bundled Common and Microsoft.Build.Tasks.Git imports are skipped.

Net result: GitHub.targets is imported alone, without the LocateRepository task or the InitializeSourceControlInformationFromSourceControlManager target. @(SourceRoot) is never populated → _GenerateSourceLinkFile does nothing → /sourcelink: switch is never passed to csc → no SourceLink CDI in PDB → paths are not PathMap-normalized.

Full preprocess (msbuild -pp) and PE-debug-directory verification available in thomhurst/TUnit#5579.

Fix that worked for us

Remove the explicit Microsoft.SourceLink.GitHub PackageReference entirely. The SDK then auto-imports Common + Build.Tasks.Git + GitHub from $(DotnetRoot)/sdk/<ver>/Sdks/Microsoft.SourceLink.*, and everything works.

Suggested improvements

Any one of these would have made this far easier to diagnose:

  1. Docs: Update the README to say "on .NET SDK 8+, don't add Microsoft.SourceLink.GitHub — it's implicit; add it only for older SDKs or custom hosts."
  2. Warning: Have Microsoft.SourceLink.GitHub.targets emit a warning if it's imported but Microsoft.SourceLink.Common.targets hasn't been imported (detectable by a well-known property set in Common's targets). This would catch the buildTransitive/_._ scenario.
  3. Suppression condition: Narrow the SDK's SuppressImplicitGitSourceLink check so it only fires when Common's build assets actually imported, not merely when the Pkg* path property is set (since NuGet sets that even for _._ assets).

Happy to contribute a docs PR if helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions