Skip to content

Latest commit

 

History

History
138 lines (89 loc) · 5.96 KB

design_3_0.md

File metadata and controls

138 lines (89 loc) · 5.96 KB

Single-file Publish for .NET Core 3.0

Owner Swaroop Sridhar

The design of single-file apps in .NET Core 3.0.

Introduction

In .NET Core 3.0 implements Stage 1 (described in the staging document) support for single-file apps.

Build System Interface

Publishing to a single file can be triggered by adding the following property to an application's project file:

<PropertyGroup>
    <PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>    
  • The PublishSingleFile property applies to both framework dependent and self-contained publish operations.
  • The PublishSingleFile property applies to platform-specific builds with respect to a given runtime-identifier. The output of the build is a native binary for the specified platform. When PublishSingleFile is set to true, it is an error to leave RuntimeIdentifier undefined, or to set UseAppHost to false.
  • Setting the PublishSingleFileproperty causes the managed app, managed dependencies, platform-specific native dependencies, configurations, etc. (basically the contents of the publish directory when dotnet publish is run without setting the property) to be embedded within the native apphost.

By default, the symbol files are not embedded within the single-file, but remain as separate files in the publish directory. This includes both the IL .pdb file, and the native .ni.pdb / app.guid.map files generated by ready-to-run compiler. Setting the following property causes the symbol files to be included in the single-file.

<PropertyGroup>
    <IncludeSymbolsInSingleFile>true</IncludeSymbolsInSingleFile>
</PropertyGroup>

Certain files can be explicitly excluded from being embedded in the single-file by setting following meta-data:

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

For example, to place some files in the publish directory but not bundle them in the single-file:

<ItemGroup>
    <Content Update="*.xml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </Content>
  </ItemGroup>

The Bundler

The bundler is a tool that embeds the managed app and its dependencies into the native AppHost executable, as described here. The bundle layout in .NET Core 3.x is described below.

Bundle Layout (ver 1.0)
AppHost
(Bundle-Marker)
Embedded Files
app.dll
app.deps.json
app.runtimeconfig.json
dependency.dll
...
Bundle Header
1.0 (Version #)
#Number of Embedded Files
Bundle-ID
Bundle Manifest
For each bundled file:
Location (Offset, Size)
Type :IL, ReadyToRun, other (This information is not used in 3.0)

The Host

On Startup, the AppHost checks if it has embedded files. If so, it

  • Memory maps the entire bundle file.
  • Checks if the contents are already extracted to the extraction location (described below)
    • If all files are intact in the extraction location, the execution continues reusing the extracted files.
    • If not, extract out the missing components
  • If an extraction is not available, the host extracts the embedded files to disk as explained in this document.
  • Invokes the runtime (through other host components).

Extraction Location

For a single-file app, the extraction directory is <base>/<app>/<bundle-id>

  • <base> is

    • DOTNET_BUNDLE_EXTRACT_BASE_DIR environment variable, if set.
    • If not, defaults to:
      • Windows: %TEMP%\.net
      • Unix:
        • ${TMPDIR}/.net/${UID} if ${TMPDIR} is set; otherwise,
        • /var/tmp/.net/${UID} if /var/tmp exists, and is writable; otherwise,
        • /tmp/.net/${UID} if /tmp exists, and is writable; otherwise fail.
  • <app> is the name of the single-exe binary

  • <bundle-id> is a unique Bundle-identifier.

API Impact

Most of the app development can be agnostic to whether the app is published as single-file or not. However, the parts of the app that deal with physical locations of files need to be aware of the single-file packaging.

  • Assembly.Location: Returns the actual location within the extraction-location.
  • AppContext.BaseDirectory: Returns the extraction directory, the location where app.dll resides.

User Experience

To summarize, here's the overall experience for creating a HelloWorld single-file app

  • Create a new HelloWorld app: HelloWorld$ dotnet new console

Framework Dependent HelloWorld

  • Normal publish: dotnet publish

    • Publish directory contains the host HelloWorld.exe , the app HelloWorld.dll, configuration files HelloWorld.deps.json, HelloWorld.runtimeconfig.json, and the PDB-file HelloWorld.pdb.
  • Single-file publish: dotnet publish -r win10-x64 --self-contained=false /p:PublishSingleFile=true

    • Publish directory contains: HelloWorld.exe HelloWorld.pdb

    • HelloWorld.dll, HelloWorld.deps.json, and HelloWorld.runtimeconfig.json are embedded within HelloWorld.exe.

  • Run: HelloWorld.exe

    • The app runs completely from the single-file, without the need for intermediate extraction to file.

Self-Contained HelloWorld

  • Normal publish: dotnet publish -r win10-x64

    • Publish directory contains 221 files including the host, the app, configuration files, the PDB-file and the runtime.
  • Single-file publish: dotnet publish -r win10-x64 /p:PublishSingleFile=true

    • Publish directory contains: HelloWorld.exe HelloWorld.pdb
    • The remaining 219 files are embedded within the host HelloWorld.exe.
  • Run: HelloWorld.exe

    • On first run, the 219 embedded files will be extracted to disk at startup.
    • Subsequent runs of the app will reuse the extraction, without incurring startup overhead.

Debugging

No difference is expected with respect to debugging and analysis of apps.