/flags/dotnet-cli/dotnet-publish-single-file
dotnet publish -p:PublishSingleFile=true: publish one executable file
- tool
- .NET CLI
- command
- dotnet publish
- flag
- -p:PublishSingleFile=true
- default
- false (the app is published as many files)
dotnet publish -r linux-x64 -p:PublishSingleFile=true bundles the application and its managed dependencies into one executable next to (optionally) a .pdb. It is an MSBuild property rather than a dedicated CLI option, so it is passed with -p: and can also live in the project file. The bundle is built for one runtime identifier (RID), so pass -r; add --self-contained to bundle the .NET runtime too, so the file runs on machines without .NET.
Normal and single-file publish
dotnet new console -o app > /dev/null && cd app
dotnet publish -r linux-x64 -o multi -v q -nologo > /dev/null 2>&1
dotnet publish -r linux-x64 -p:PublishSingleFile=true -o single -v q -nologo > /dev/null 2>&1
echo "--- normal"
ls multi
echo "--- PublishSingleFile=true"
ls singleOutput
--- normal app app.deps.json app.dll app.pdb app.runtimeconfig.json --- PublishSingleFile=true app app.pdb
The normal publish writes app.dll, the launcher, the dependency manifest and the runtime configuration; the single-file publish leaves only the executable and its symbols. app is the Linux launcher with the application bundled inside; on Windows targets it is app.exe.
Related properties
| Property or option | Effect |
|---|---|
| -p:PublishSingleFile=true | Bundle the app into one executable for the given RID |
| --self-contained | Include the .NET runtime in the bundle |
| -p:IncludeNativeLibrariesForSelfExtract=true | Also bundle native libraries (extracted at start-up) |
| -p:EnableCompressionInSingleFile=true | Compress bundled assemblies (self-contained only) |
| -p:DebugType=embedded | Embed symbols so no .pdb is written next to the file |
| -p:PublishTrimmed=true | Trim unused code to shrink self-contained bundles |
In the project file
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>With these properties a plain dotnet publish produces the single file. Keep them in a separate publish profile (Properties/PublishProfiles/*.pubxml) if developers should not get them on every publish.
Pitfalls
Assembly.LocationandAssembly.GetFilereturn empty values inside a bundle; code that builds paths from them breaks. The SDK warns about such calls (IL3000) during publish.- Native libraries (SQLite, image codecs) stay next to the executable unless
IncludeNativeLibrariesForSelfExtractis set, so the output may still be more than one file. - A framework-dependent single file still needs the right runtime installed; for a truly standalone file combine it with --self-contained.
- The file is built for one RID; publish separately for Windows, Linux and macOS.
FAQ
Why does PublishSingleFile require a runtime identifier?
The single file is a native executable (apphost) for one operating system and CPU, with the app bundled inside. Older SDKs refused to publish a single file without -r; the .NET 10 SDK falls back to the RID of the machine running the build, which is rarely the server you deploy to. Always pass -r explicitly.
Why is Assembly.Location empty in a single-file app?
Assemblies are loaded from inside the bundle, not from files, so Assembly.Location returns an empty string. Use AppContext.BaseDirectory for the folder of the executable.
Is the single file self-contained?
Only if you also pass --self-contained. Otherwise it is a framework-dependent single file that still needs the .NET runtime installed on the target machine.