fsprojects / Paket

A dependency manager for .NET with support for NuGet packages and Git repositories.
https://fsprojects.github.io/Paket/
MIT License
2.02k stars 525 forks source link

Creating a package with .snupkg symbols fails with error NU5005 #3685

Open teo-tsirpanis opened 5 years ago

teo-tsirpanis commented 5 years ago

Repro steps

  1. Create the following project:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
  </PropertyGroup>
  <Import Project=".paket\Paket.Restore.targets" />
</Project>
  1. paket convert-from-nuget.

  2. dotnet pack

Expected behavior

A .snupkg file would be created alongside with its main .nupkg package file.

Actual behavior

C:\Users\teots\code\paket-bug\.paket\Paket.Restore.targets(304,5): error NU5005: Failed to build package. Ensure 'C:\Users\teots\code\paket-bug\obj\Debug\paket-bug.1.0.0.nuspec' includes source and symbol files. For help on building symbols package, visit https://docs.nuget.org/. [C:\Users\teots\code\paket-bug\paket-bug.csproj]

Additional information

I saw a paket-bug.1.0.0.symbols.nuspec file inside obj/Debug. Was Paket trying to create a legacy .symbols.nupkg file? Maybe my previous fix in #3636 was not enough.

ModernRonin commented 4 years ago

I hit the same problem. Is there any workaround I can use until this is fixed?

atlemann commented 3 years ago

I'm also getting the same issue. Not sure how to work around it. Tried with dotnet SDK 5.0.100 as well, but no luck'

ModernRonin commented 3 years ago

With net5 and with putting <PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="1.0.0" PrivateAssets="All" /> into a Directory.Build.props file (so it doesn't interfere with paket) and removing this dependency from paket altogether, it works for me now.

maybe something to try @atlemann

atlemann commented 3 years ago

Ah thanks @ModernRonin I'll try that.

atlemann commented 3 years ago

Still doesn't work. Once I add <IncludeSymbols>true</IncludeSymbols> anywhere, it fails with the same error.

ModernRonin commented 3 years ago

Hmm, strange. Maybe some of the following helps?

in my Directory.Build.Props:

        <PublishRepositoryUrl>true</PublishRepositoryUrl>
        <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
        <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
        <SymbolPackageFormat>snupkg</SymbolPackageFormat>
        <DebugType>embedded</DebugType>
        <DebugSymbols>true</DebugSymbols>
        <EmbedAllSources>true</EmbedAllSources>
//...
    <ItemGroup Condition="'$(UsingMicrosoftNETSdk)' == 'true' and '$(IsPackable)' == 'true'">
        <PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="1.0.0" PrivateAssets="All" />
    </ItemGroup>
    <PropertyGroup Condition="'$(UsingMicrosoftNETSdk)' == 'true' AND '$(TF_BUILD)' == 'true'">
        <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
    </PropertyGroup>

my paket version is: 5.257.0 and I'm using net5, like you.

atlemann commented 3 years ago

Ok, looks like you are embedding the .pdb file in the NuGet package with the assemblies instead of creating a separate symbols NuGet package?

ModernRonin commented 3 years ago

@atlemann sorry for the late answer, but yes, that's what I do. meanwhile I've made changes (because I want to create one nuget with all projectreferences inside instead of each projectreference as a separate nuget), and now it looks like this:

in the .csproj of the project that gets packed as a nuget:

<PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <Description>...</Description>
    <Version>1.4.785</Version>
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
    <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
    <DebugType>embedded</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <EmbedAllSources>true</EmbedAllSources>
    <IsPackable>true</IsPackable>
</PropertyGroup>
<ItemGroup>
    <PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
    <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>

In directory.build.props at the solution level:

<PropertyGroup Condition="'$(UsingMicrosoftNETSdk)' == 'true'">
    <Company>our company</Company>
    <Authors>our team</Authors>
    <Copyright>Copyright © 2020 our company</Copyright>
    <WarningLevel>5</WarningLevel>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
    <PackageReference Include="NuGetizer" Version="0.5.0" />
</ItemGroup>

In paket.dependencies and paket.references no mention of either Microsoft.SourceLink.AzureRepos.Gitor NuGetizer.

And it works perfectly:

ModernRonin commented 3 years ago

of course, this all is skewed towards in-house usage. If you're aiming to publish a public nuget, this is maybe not ideal for you.

ModernRonin commented 3 years ago

all this being said, I'd still prefer a lot, if I could handle everything with paket, so also these two packages.

But on the other hand, I'm also not quite surprised that they require special handling. This is the one fundamental issue with paket: while it is still the far superior nuget client, in my opinion, even though the regular one by now handles transitive dependencies correctly, it will always suffer from being 3rd party - certain very nuget-intrinsics specific integrations like sourcelink/debug symbols or manipulation of the packaging like NuGetizer will be built by people not even aware of paket.

The best outcome really would be if paket's concepts were merged into the mainstream nuget mechanism, but I'm not holding my breath...

atlemann commented 3 years ago

Trying to look into how this all works. When IncludeSymbols is defined, a .nuspec and a separate .symbols.nuspec file iscreated, but it seems that to make a nupkg and a snupkg file, both the .dll's and the .pdb's should be listed in the same .nuspec file. If I copy all files references from both .nuspec files into a single one and use that in the PackTask, I get the two packages, nupkg with .dll and .xml if generated, and a snupkg with .pdb files.

atlemann commented 3 years ago

Hmm, when I run dotnet pack on a similar project which doesn't use Paket, I get a .nuspec and a .symbols.nuspec in the obj folder. So I guess that's correct. So, I guess some tricks must be done in Paket.Restore.targets to make this work.

atlemann commented 3 years ago

hmm, seems like completely removing PaketOverrideNuspec target just works, but then paket fix-nugets won't be run anymore which is a problem.

atlemann commented 3 years ago

I have no clue how this works with vanilla dotnet nuget, but when using the PackTask, specifying a .nuspec with all files including .pdb's is the only way I could make it create both packages.

It's not completely clear in the docs if it should be two separate nuspec files or just a single one: https://docs.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg#symbol-package-structure

atlemann commented 3 years ago

After some trial and error I found out how to make separate .nupkg and .snypkg packages with Paket.

According to the .NET docks, to create a separate symbols package, add the following to the project file:

<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>

But when doing dotnet pack I get the following error:

/home/atle/src/MyNuget/.paket/Paket.Restore.targets(317,5): error NU5005: Failed to build package. Ensure '/home/atle/src/MyNuget/src/MyFsNuget/obj/Debug/MyFsNuget.1.0.0.nuspec' includes source and symbol files. For help on building symbols package, visit https://docs.nuget.org/. [/home/atle/src/MyNuget/src/MyFsNuget/MyFsNuget.fsproj]

In order to make a .nupkg with a separate .snupkg for SourceLink, the .nuspec file should contain paths to both .dll and .pdb (and *.xml if you want docs). So if you create a .nuspec file with that you can do

dotnet pack src/MyFsNuget/ -p:NuspecFile=../../MyFsNuget.1.0.0.nuspec -o nuget

and both packages will be created. However, to avoid manually creating the .nuspec file, just add the following line to the project to add the .pdb files to the .nuspec created by dotnet.

<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

Now when you do:

dotnet pack path/to/MyProject

you can see the .pdb files being added to the path/to/MyProject/obj/Debug/MyProject.x.y.z.nuspec file and two separate packages will be built.

Note that the two separate packages will only be built if you have the

<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>

options. If not, the .pdb files will be added to the .nupgk package.

So this is an examlpe Directory.Build.props which enables this:

<Project>
  <PropertyGroup>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>

    <Description>Testing symbols</Description>
    <RepositoryUrl>https://github.com/atlemann/MyNuget</RepositoryUrl>
    <RepositoryType>git</RepositoryType>

    <PublishRepositoryUrl>true</PublishRepositoryUrl>

    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
  </PropertyGroup>
</Project>
kroppt commented 3 years ago

This workaround will not work for .NET Framework projects, because dotnet pack doesn't work, at least as far as I can tell.