Skip to content

Commit

Permalink
Single file apps in .net 5
Browse files Browse the repository at this point in the history
This change updates the design for single-file apps support, with upcoming changes in .net 5.
The .net core 3 design is summarized in design_3_0.md
  • Loading branch information
swaroop-sridhar committed Feb 5, 2020
1 parent c2ce556 commit fb69d53
Show file tree
Hide file tree
Showing 6 changed files with 464 additions and 409 deletions.
57 changes: 28 additions & 29 deletions accepted/single-file/bundler.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# The Single-file Bundler

### Requirements
## Requirements

Ideally, the bundler should be:

Expand All @@ -9,46 +9,45 @@ Ideally, the bundler should be:
* Deterministic (generate the exact same single-file on multiple runs)
* Amenable to post-processing (ex: signing tools)

### Bundle Transformation
## Bundle Layout

Given a .net core app published with respect to a specific runtime, the bundler transforms the `AppHost` binary to a single-file bundle by:
| Bundle Layout (ver 2.0) |
| ------------------------------------------------------------ |
| **AppHost**<br />`(Bundle-Marker)` |
| **Embedded Files**<br />`app.dll` <br />`app.deps.json`<br />`app.runtimeconfig.json`<br />`dependency.managed.dll`<br />`...`<br /> |
| **Bundle Header** <br />`2.0` (Version #)<br /> `#Number of Embedded Files`<br />`Bundle-ID` <br />`Needs Extraction?`<br />`deps.json file location (offset, size)`, if any.<br />`runtimeconfig.json file location (size,offset)`, if any. |
| **Bundle Manifest**<br />For each bundled file:<br /> `Location (Offset, Size)`<br /> `Type: IL, ReadyToRun, deps.json, runtimeconfig.json`, or `other` (extract) |

* Appending the managed app and its dependencies as a binary-blob at the end of the `AppHost` executable.
* Writing meta-data to identify the binary as a single-file bundle, and a manifest of the embedded files.
### Bundle Marker

#### Bundle Layout
Every `AppHost` has a static variable that identifies the location of the single-file header (if any). By default, this value is zero, which indicates that the `AppHost` is not a bundle. The bundler tool rewrites this value with the location of the bundle header.

The bundling tool will append the following contents to the `AppHost` binary:
Using a special marker for recognizing bundle-header (instead of simply writing the header at the end of the file) enables compatibility with other post-processing tools (such as `signtool`) which require their own content to be at the end of the file.

* The actual files to be published into the single file (including the managed app)
* A bundle header containing:
* The bundler tool version
* A bundle identifier: which is a *path-compatible* cryptographically strong name.
* This identifier is used to distinguish bundles for different versions of the same app.
* This identifier is used as part of the bundle extraction mechanism as described in [this document](extract.md).
* Currently, a new bundle identifier is generated for each bundle transformation.
In future, the bundle identifiers should be generated by hashing the contents of the bundle -- so that bundle transformation is deterministic.
* Offset of the bundle manifest
### Bundle Identifier

* A bundle manifest that describes:
* The location of embeded files (offset and size)
* The type of the embedded files: MSIL assemblies, ready-to-run assemblies, configuration files (ex: `app.deps.json` `app.runtimeconfig.json`), or others.
The bundle identifier is a *path-compatible* cryptographically strong name.

Every `AppHost` has a static variable that identifies the location of the single-file header (if any).
By default, this value is zero, which indicates that the `AppHost` is not a bundle.
The bundler tool rewrites this value with the location of the bundle header.
This ensures that the bundle-header is not position constrained (ex: at the end of the file), so that tools like `signtool` can post-process the bundle file.
* This identifier is used to distinguish bundles for different versions of the same app.
* This identifier is used as part of the bundle extraction mechanism as described in [this document](extract.md).
* A new bundle identifier is generated for each bundle transformation.

### Implementation
## Bundle Transformation

The bundler should ideally be located close to the core-host, since their implementation is closely related. Therefore, the bundler will be implemented in the `core-setup` repo.
Given a .net core app published with respect to a specific runtime, the bundler transforms the `AppHost` binary to a single-file bundle through the following actions:

* Append the managed app and its dependencies as a binary-blob at the end of the `AppHost` executable.
* Write meta-data headers and manifest that help locate the contents of the bundle.
* Set the bundle-indicator in the `AppHost` to the offset of the bundle-header.

## Implementation

The bundling tool is implemented as a library in the [Microsoft.NET.HostModel](https://www.nuget.org/packages/Microsoft.NET.HostModel/) package. This library is used by the SDK in order to publish a .net core app as a single-file.

### Further work
The bundler should generate the correct format of single-file bundles based on the target framework.

#### Codesign on Mac
## Limitations

Codesign tool on mac-os performs strict consistency checks, and cannot tolerate the additional files appended at the end of the `AppHost` executable.
[Further work](https://github.com/dotnet/core-setup/issues/7065) is necessary to update the binary headers to make the bundle file compatible for signing.
* Currently, a new bundle identifier is generated for each bundle transformation. In future, the bundle identifiers should be generated by hashing the contents of the bundle -- so that bundle transformation is deterministic.
* `Codesign` tool on mac-os performs strict consistency checks, and cannot tolerate the additional files appended at the end of the `AppHost` executable. [Further work](https://github.com/dotnet/core-setup/issues/7065) is necessary to update the binary headers to make the bundle file compatible for signing.

Loading

0 comments on commit fb69d53

Please sign in to comment.