dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.75k stars 1.07k forks source link

dotnet publish - way to remove pdb and other files #16975

Open saxenark opened 5 years ago

saxenark commented 5 years ago

Hi,

I am using dotnet publish to publish my dotnet core 2.2 web application. I notice that the published folder has several unrequired files, specifically .pdbs, .appsettings.Development, .runtimeconfig.dev etc.

Qn: Is there a way dotnet publish command can be made to exclude these files or would I have to delete these manually?

Thanks

scalablecory commented 5 years ago

@livarcocc @jeffschwMSFT

saxenark commented 5 years ago

Hi @scalablecory @livarcocc @jeffschwMSFT,

please let me know if there is a way to remove these unnecessary files during publish.

ducalai commented 4 years ago

Same question with dotnet core 3.1 web application. Any way to remove those unrequired files using command line parameters or .csproj PropertyGroup properties? DebugType=None and DebugSymbols=false seem to be ignored.

ducalai commented 4 years ago

Using Property group in .csproj with <DebugType>None</DebugType> and <DebugSymbols>false</DebugSymbols> must be done on each referenced .csproj to apply on each referenced assemblies.

Using dotnet publish parameters /p:DebugType=None /p:DebugSymbols=false apply on each referenced assemblies.

carlossanlop commented 4 years ago

@saxenark did the answer given by @ducalai solve your problem?

LevYas commented 3 years ago

I want to point at the inconsistency of how the parameters applied: I tried to specify

<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>

In my \PublishProfiles\FolderProfile.pubxml, it works only for the project you publish, not for references. I tried to do as @ducalai suggested - added publish parameters /p:DebugType=None /p:DebugSymbols=false and it worked for references too. BTW the same thing with -p:Configuration=Release

dotnet-issue-labeler[bot] commented 3 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ahdung commented 3 years ago

Issue still here.

AGlezB commented 3 years ago

I have the same issue as @ahdung. I want to exclude some massive XML docs from integrations with other services and only keep the API docs for Swashbuckle.

I believe the real issue is that <Content Update="XXXX" CopyToPublishDirectory="Never" /> doesn't work for files generated by the buid process.

See this:

    <ItemGroup>
        <Content Update="appsettings*.json" CopyToPublishDirectory="Never" />
        <Content Update="*.xml" CopyToPublishDirectory="Never" />
    </ItemGroup>

If you put that in your .pubxml file, only the `appsettings.json` files wil be excluded. As far as I'm concerned that is a bug because at the time of publishing there should be no difference in how you treat files in the build output folder.

lonix1 commented 2 years ago

The problem with the solution above is it's always excluded. But I need it excluded only for release builds. This works:

<PropertyGroup Condition="'$(Configuration)'=='Release'">
  <DebugSymbols>False</DebugSymbols>
  <DebugType>None</DebugType>
</PropertyGroup>
AGlezB commented 2 years ago

@jeffschwMSFT any progress on this? As of net7.0 we still cannot exclude certain files.

jeffschwMSFT commented 2 years ago

@agocke should this issue be in SDK or runtime?

agocke commented 2 years ago

SDK. The proposal as stands is some sort of property to affect all publish scenarios, which is core SDK logic.

sebastienros commented 1 year ago

Also interested in this feature for NativeAOT scenarios. Right now with a minimal api app the app is 25MB and the symbols 80MB (using StripSymbols on Linux). It's not obvious that you can get rid of the .dbg file if you care about the size (for most users I'd say). I would expect that these arguments would work on dotnet publish at least, and globally. Right now the .dbg file is still generated with these two arguments.

agocke commented 1 year ago

@sebastienros I think there might be two separate scenarios here, actually.

1) Produce no symbols at all, anywhere. 2) Don't produce symbols during publish, but do produce them for build.

I think (1) can be a Native AOT specific issue that we should respect <DebugSymbols>false</> and <DebugType>none</>. (2) is the new scenario as it would only affect publish scenarios.

Broadly though, I don't see how this would help the goal of informing users that they don't need to carry around the .dbg file. This seems like basically the same UX as .pdb files and I think the current expectation is that users know that they don't need to copy the PDB file around.

sebastienros commented 1 year ago

Agreed. I want 2) here.

HughWarrington commented 1 year ago

If you are experiencing all kinds of junk files in your publish output directory, it may be because you have set <PublishDir> and <PublishUrl> to the same value in your .pubxml profile. This apparent bug has been reported to Microsoft here.

6bee commented 1 year ago

adding the following PropertyGroup to the .pubxml seems to have solved the issue for me:

  <PropertyGroup>
    <DebugType>none</DebugType>
    <GenerateDocumentationFile>false</GenerateDocumentationFile>
    <AllowedReferenceRelatedFileExtensions>none</AllowedReferenceRelatedFileExtensions>
    <NoWarn>$(NoWarn);SA0001</NoWarn>
  </PropertyGroup>

Update [2023-08-21]: Setting these properties within .pubxml only works when performing publish from within Visual Studio. For command line dotnet publish, DebugType needs to be specified as command line parameter to take effect:

dotnet publish -p DebugType=none
marcpopMSFT commented 1 year ago

Since this was filed, the publish is down to a minimum set (exe, dll, runtimeconfig, deps, and pdb). pdb can be disabled with DebugType. Marking fixed. PublishDocumentationFile can also be used to disable publish for that particular file. https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#publishdocumentationfile

NCLnclNCL commented 1 year ago

Vì điều này đã được gửi, xuất bản được giảm xuống mức tối thiểu (exe, dll, runtimeconfig, deps và pdb). pdb có thể bị tắt bằng DebugType. Đánh dấu cố định. PublishDocumentationFile cũng có thể được sử dụng để tắt xuất bản cho tệp cụ thể đó. https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#publishdocumentationfile

if i use p:DebugType=None it will cannot build native aot

dobsa commented 1 year ago

In my team we do store PDB files to symbol server. So I want to generate PDBs. At the same time we want to create Docker container with the application files, and this container must not contain PDB's (for security and size concerns). Nobody here demonstrated how that can be done AFAU.

lonix1 commented 1 year ago

@dobsa You want to create a .snupkg using dotnet pack --include-symbols

6bee commented 1 year ago

In my team we do store PDB files to symbol server. So I want to generate PDBs. At the same time we want to create Docker container with the application files, and this container must not contain PDB's (for security and size concerns). Nobody here demonstrated how that can be done AFAU.

You may also specify the following properties, for PDB files to be included in extra symbols package (.snupkg):

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

See https://learn.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg for more info.

dobsa commented 1 year ago

@dobsa You want to create a .snupkg using dotnet pack --include-symbols

I don't really mind how and where the symbols end up, as long as they are not present in the publish directory.

dobsa commented 1 year ago

In my team we do store PDB files to symbol server. So I want to generate PDBs. At the same time we want to create Docker container with the application files, and this container must not contain PDB's (for security and size concerns). Nobody here demonstrated how that can be done AFAU.

You may also specify the following properties, for PDB files to be included in extra symbols package (.snupkg):

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

See https://learn.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg for more info.

May be we do something wrong, but we build a Linux executable and put the content of publish folder into Docker container. This publish folder seems to always contain the PDBs if we generated them. Sure I can delete *.pdb afterwards when building the conainer. But more reasonable option would be to have an option to skip copying them.

6bee commented 1 year ago

May be we do something wrong, but we build a Linux executable and put the content of publish folder into Docker container. This publish folder seems to always contain the PDBs if we generated them. Sure I can delete *.pdb afterwards when building the conainer. But more reasonable option would be to have an option to skip copying them.

Thanks for clarifying. In this case you might want to specify DebugType=none as a command line argument when performing dotnet publish as a separate build step:

dotnet publish -p DebugType=none
AGlezB commented 1 year ago

Was there a problem with the ExcludeFoldersFromDeployment and ExcludeFilesFromDeployment in .pubxml files? I think this issue began because those are not supported by dotnet publish. Maybe bringing those back would make this issue go away.

dobsa commented 1 year ago

May be we do something wrong, but we build a Linux executable and put the content of publish folder into Docker container. This publish folder seems to always contain the PDBs if we generated them. Sure I can delete *.pdb afterwards when building the conainer. But more reasonable option would be to have an option to skip copying them.

Thanks for clarifying. In this case you might want to specify DebugType=none as a command line argument when performing dotnet publish as a separate build step:

dotnet publish -p DebugType=none

Thanks for the tip. With this option, some PDBs are gone. But some are still left. Interesting.

Actually it seems that only the PDBs of the project I am publishing are skipped. But this project has many project dependencies. And pdbs from those other projects are just copied over for whatever mysterious reason.

dobsa commented 1 year ago

Was there a problem with the ExcludeFoldersFromDeployment and ExcludeFilesFromDeployment in .pubxml files? I think this issue began because those are not supported by dotnet publish. Maybe bringing those back would make this issue go away.

It seems similar as above. Only PDBs from the project being published are skipped. PDBs from dependent projects are copied over.

dobsa commented 1 year ago

IMO this issue should be re-opened. There is no way to skip copying PDB files into publish folder once they were generated. The only thing that worked for me was to delete them once they were copied, using .pubxml file:

  <Target Name="DeleteFiles" AfterTargets="Publish">
    <ItemGroup>
        <FilesToDelete Include="$(PublishDir)*.pdb"/>
    </ItemGroup>
    <Delete Files="@(FilesToDelete)">
    <Output
        TaskParameter="DeletedFiles"
        ItemName="FilesDeleted"/>
    </Delete>
    <Message Text="Deleted PDB files: @(FilesDeleted)" Importance="high" />
</Target>
dobsa commented 1 year ago

To clarify final bit: we build everything in one step. And invoke dotnet publish with --no-build argument only to publish things that have been already built in another step. And for this reason none of the solutions suggested here work. Except for the last one suggested by me: let dotnet copy all that crap, and delete it afterwards.

totpero commented 1 year ago

I want to point at the inconsistency of how the parameters applied: I tried to specify

<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>

In my \PublishProfiles\FolderProfile.pubxml, it works only for the project you publish, not for references. I tried to do as @ducalai suggested - added publish parameters /p:DebugType=None /p:DebugSymbols=false and it worked for references too. BTW the same thing with -p:Configuration=Release

When I try this and I but this two lines in my .pubxml file I get this error:

https://stackoverflow.com/questions/77071059/the-debug-type-specified-in-the-dependency-context-could-be-parsed-asp-core-er/77071060#77071060

LevYas commented 10 months ago

This should be reopened indeed. dotnet publish command-line args -p:DebugType=None -p:DebugSymbols=false started working only for the main project, PDBs from other projects are still included, bloating the package.

ahdung commented 8 months ago

@marcpopMSFT Why you guys close it??? Issue still here.

marcpopMSFT commented 8 months ago

Triage: @richaverma1 can you have your team set up a repro of this and provide a binlog? It should be a project that depends on another project and sets -p:DebugType=None -p:DebugSymbols=false during the publish but the dependent are still being picked up.

AGlezB commented 8 months ago

Triage: @richaverma1 can you have your team set up a repro of this and provide a binlog? It should be a project that depends on another project and sets -p:DebugType=None -p:DebugSymbols=false during the publish but the dependent are still being picked up.

It's not about debug symbols but other files that might be included in the project but we don't want to deploy. appsettings.json is a main example of that. web.config for web apis.

The point is we can do that with .NET Framework projects but not with .NET ones because publication using .pubxml files doesn't support it.

marcpopMSFT commented 8 months ago

So the options provided correctly remove the pdbs but there is a desire for a solution for other files as well? We'll sync in triage next week on this. From our vendor testing, setting those properties in individual project files affects only those projects but setting it on the command line as suggested, does affect all projects which matches AGlezB commented.

AGlezB commented 8 months ago

So the options provided correctly remove the pdbs but there is a desire for a solution for other files as well? We'll sync in triage next week on this. From our vendor testing, setting those properties in individual project files affects only those projects but setting it on the command line as suggested, does affect all projects which matches AGlezB commented.

To be clear the main issue for me is that .pubxml has a syntax to specify files to exclude but in on only works for certain files. Here is an extract from a publish profile from one of our Web Api projects:

  <!-- Esto es para que no incluya archivos innecesarios al publicar -->
  <ItemGroup>
    <Content Update="appsettings*.json" CopyToPublishDirectory="Never" />
    <!--
        Esto no funciona todavía con .NET Core
        https://github.com/dotnet/sdk/issues/16975

        <Content Update="*.xml" CopyToPublishDirectory="Never" />
        <Content Update="*.pdb" CopyToPublishDirectory="Never" />
        <Content Update="PrecisionApi.xml" CopyToPublishDirectory="PreserveNewest" />
        -->
  </ItemGroup>

The translation for the comments is:

  <!-- To exclude unnecesary files on publish -->
  <ItemGroup>
    <!-- This isn't working on .NET Core yet -->
  </ItemGroup>

The meaning of the settings is: we don't want any appsettings*.json or .xml (dll documentation) or .pdb files but we do want the PrecisionApi.xml file because that one populates the Swagger UI documentation.

Of those the only one that works is the appsettings*.json one because the file are already included in the project. The other files are generated by the build process and the publish process doesn't recognize them which is why those are commented out and I'm keeping an eye on this issue.

Ideally all four would work, which is to say I'd like to be able to write the rules in the .pubxml, commit the file to source control and forget about it. Command line is convenient but it's secondary to making the publish profile work.

baronfel commented 7 months ago

We investigated a bit and think you will need a custom target to accomplish this in a consistent manner. The reason for this is that your pubxml file is being read during project evaluation, but many of the items you want to customize are only available during build execution - they are created during the build. By definition, you must use targets to interact with these kinds of items.

I think a good place to start investigating would be the DefaultCopyToPublishDirectoryMetadata target - this target in the SDK is responsible for defining how the Content/etc items are marked for copying to publish directories. If you create a target that has BeforeTargets="DefaultCopyToPublishDirectoryMetadata" then you should be able to detect any of the PDBs and other files you want to remove and set their metadata to not be copied.

You can investigate your builds in detail using the MSBuild Structured Log Viewer tool.

levicki commented 1 month ago

There's also a problem that when you build a project which includes a NuGet package (for example HtmlAgilityPack) the build process copies HtmlAgilityPack.pdb to Release folder even if my release build is configured to have no PDB files of its own. I presume that PDB file would also end up in Publish folder but for me Publish to local folder is broken in VS 2022 like for many others so I can't test at the moment.

I don't see a way around that, is there any?

LevYas commented 1 month ago

@levicki publish target to remove all .pdb's works like a charm:

<Project>
...
    <!-- Unfortunately, command-line args -p:DebugType=None -p:DebugSymbols=false started working only for the main project,
        PDBs from other projects are still included. Looks like this is the most reliable way to remove PDBs.
        Source https://github.com/dotnet/sdk/issues/16975#issuecomment-1689291544 -->
    <Target Name="DeleteFiles" AfterTargets="Publish">
        <ItemGroup>
            <FilesToDelete Include="$(PublishDir)*.pdb;"/>
        </ItemGroup>
        <Delete Files="@(FilesToDelete)">
            <Output
                TaskParameter="DeletedFiles"
                ItemName="FilesDeleted"/>
        </Delete>
        <Message Text="Deleted PDB files: @(FilesDeleted)" Importance="high" />
    </Target>
</Project>
levicki commented 1 month ago

@levicki publish target to remove all .pdb's works like a charm:

...

If the Publish worked for me that might have been acceptable, but then again it is still a cludgey workaround because it is not avoiding generating, writing, and then deleting potentially large number of files thus decreasing your SSD lifespan and wasting CPU cycles unnecessarily.