nick
nick

Reputation: 11

Can't figure out how to include the source code into the nuget package that gets generated

I have several projects in a solution that i want to be packaged to be used as libraries in other solutions. The goal is to make development and debugging seamless, as if it was all in the same solution.

Specifically, I want to be able to ctrl + click on something from the library and be able to view the original source code and not the decompiled code.

I am using PackageReference to include the libraries to the application. What I have noticed is that when I unzip either the nupkg or snupkg, there is no source files anywhere. On that note, I have searched all over the internet and found conflicting things about where the source files go in the nupkg. I have seen mentions of the following folders in the nupkg: lib, src, content, and contentFiles. Which one should actually contain the source code?

When I unzip the nupkg (or snupkg) the only things I have in it are _rels, lib, package, [Content_Types].xml, and PROJECTNAME.nuspec.

I see that the lib folder contains the dll and the pdb file but no source code. Furthermore, I noticed that the snupkg file is considerably smaller than the nupkg file which I find to be counter intuitive.

I have tried packaging using msbuild -t:pack msbuild -t:pack -IncludeSource=true nuget pack nuget pack -IncludeSource=true and also building with visual studio but to no avail.

Here is my vbproj file

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{C64FB67B-64D0-4607-AE35-A21888FE79A2}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>ROOTNAMESPACE_HERE</RootNamespace>
    <AssemblyName>PACKAGE_NAME_HERE.ROOTNAMESPACE_HERE</AssemblyName>
    <FileAlignment>512</FileAlignment>
    <MyType>Windows</MyType>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <Deterministic>true</Deterministic>
    <SccProjectName>SAK</SccProjectName>
    <SccLocalPath>SAK</SccLocalPath>
    <SccAuxPath>SAK</SccAuxPath>
    <SccProvider>SAK</SccProvider>
    <TargetFrameworkProfile />
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <version>1.0.0</version>
    <RepositoryType>git</RepositoryType>
    <Authors>COMPANY_HERE</Authors>
    <BuildInParallel>false</BuildInParallel>
    <EmbedUntrackedSources>true</EmbedUntrackedSources>
    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
    <IncludeSource>true</IncludeSource>
    <PackageId>PACKAGE_NAME_HERE.ROOTNAMESPACE_HERE</PackageId>
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
    <EmbedUntrackedSources>true</EmbedUntrackedSources>
    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
  </PropertyGroup>
  
  ...
  ...
  ...
  
    <ItemGroup>
    <PackageReference Include="NuGet.Build.Tasks.Pack" Version="6.4.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
  </ItemGroup>
  
  

I have also tried using a nuspec file as well but still no success. I am using .net framework 4.8

I have spent the last 3 days banging my head against the wall over this and haven't been able to figure it out. I have googling non-stop and have even been using ChatGPT to help me try and trouble shoot and no matter what I try I cant get it to work.

Any help would be greatly appreciated!

Upvotes: 1

Views: 785

Answers (1)

svenhuebner
svenhuebner

Reputation: 382

It sounds like you want to publish nuget packages with SourceLink activated. SourceLink will add metadata to the packaged assemblies that contains hints about where the original code from which the package was build can be found, e. g. a GIT repository URL and the particular commit SHA. The Visual Studio Debugger during debugging will read the metadata and thus be able to download the source from the repository and show it to you. This will be the original source like you wanted.

See the docs at https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/sourcelink.

What you have to do is add SourceLink as a package dependency to the project from which the package will be built. For github and an SDK-style project it looks like this:

<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>

<!-- alternatively, using the new GlobalPackageReference element -->
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />

Since you seem to be using the old project format, you may need to do it differently. Visual Studio will most likely do the right thing for you when adding the package through the package manager UI. Note that this is a build-time dependency only and will not add any libraries.

SourceLink by default will only do its job when some MSBuild properties are set. More on that below.

This is a snippet I use (again, SDK-style) to have SourceLink active on every release build:

<PropertyGroup>
  <!-- ugly workaround because MSBuild apparently cannot set a bool property from the result of an evaluated expression -->
  <TreatAsOfficialBuild>false</TreatAsOfficialBuild>
  <!-- Abuse "Release" config as trigger for SourceLink, because I don't want to type -p:ContinuousIntegrationBuild every time
       This should work as long as we do not locally debug release builds from commits that have not been pushed to github yet -->
  <TreatAsOfficialBuild Condition="'$(Configuration)' == 'Release'">true</TreatAsOfficialBuild>

  <PublishRepositoryUrl>$(TreatAsOfficialBuild)</PublishRepositoryUrl>
  <EmbedUntrackedSources>true</EmbedUntrackedSources>
  <ContinuousIntegrationBuild>$(TreatAsOfficialBuild)</ContinuousIntegrationBuild>
  <DeterministicSourcePaths>$(TreatAsOfficialBuild)</DeterministicSourcePaths>
</PropertyGroup>

For the debugger to be able to download the source, the package must have been built from a commit that is available on the remote repo.

I trust you already know that you may not be able to debug into that source with breakpoints if the build you are debugging is optimized like in a "Release" build.

If you want to be able to debug through every line of the package's original source, you would have to build that package without optimization (like in a "Debug" build). For SourceLink to be active on debug builds too, you would need to adapt the criteria for the TreatAsOfficialBuild property accordingly.

Upvotes: 1

Related Questions