-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Single file apps in .net 5 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
1 parent
6cf87fd
commit df6b2fb
Showing
7 changed files
with
458 additions
and
408 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,57 @@ | ||
# The Single-file Bundler | ||
|
||
### Requirements | ||
## Requirements | ||
|
||
Ideally, the bundler should be: | ||
|
||
* Able to embed any file required to run a .Net Core app -- managed assemblies, native binaries, configuration files, data files, etc. | ||
* Able to embed any file required to run a .NET Core app -- managed assemblies, native binaries, configuration files, data files, etc. | ||
* Able to generate cross-platform bundles (ex: publish a single-file for Linux target from Windows) | ||
* 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: | ||
|
||
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. | ||
* Append the managed app and its dependencies as a binary-blob at the end of the `AppHost` executable. This includes all files to be embedded located within the publish directory and any sub-directories. The path (relative to the bundle-root) of published files are noted in the bundle meta-data. | ||
* 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. | ||
|
||
### Further work | ||
The bundler should generate the correct format of single-file bundles based on the target framework. | ||
|
||
#### Codesign on Mac | ||
## Implementation | ||
|
||
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. | ||
The bundling tool is implemented as a library in the [Microsoft.NET.HostModel](https://www.nuget.org/packages/Microsoft.NET.HostModel/) package in the [runtime](https://github.com/dotnet/runtime) repo. | ||
|
||
* The bundler is located alongside the host components, since their implementations are closely related. | ||
* Separating the bundler (and other AppHost transformers in HostModel) implementation from SDK repo aligns with code ownership, and facilitates maintenance of the library. | ||
* The build targets/tasks that use the HostModel library are in the SDK repo. This facilitates the MSBuild tasks to be multi-targeted. It also helps generate localized error messages, since SDK repo has the localization infrastructure. | ||
|
||
## Limitations | ||
|
||
* 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. | ||
|
Oops, something went wrong.