Update runtime-configuration-file.md

This commit is contained in:
Andrew Stanton-Nurse 2016-03-01 09:12:54 -08:00 committed by Andrew Stanton-Nurse
parent 42a17b5d98
commit 8f4ab7ded7

View file

@ -10,21 +10,27 @@ There are two runtime configuration files for a particular application. Given a
* `MyApp.dll` - The managed assembly for `MyApp`, including an ECMA-compliant entry point token.
* `MyApp.exe` - A copy of the `corehost.exe` executable.
* `MyApp.config.json` - An **optional** configuration file containing runtime configuration settings.
* `MyApp.runtimeconfig.json` - An **optional** configuration file containing runtime configuration settings.
* `MyApp.deps.json` - A list of dependencies, as well as compilation context data and compilation dependencies. Not technically required, but required to use the servicing or package cache/shared package install features.
The `MyApp.runtimeconfig.json` is designed to be user-editable (in the case of an app consumer wanting to change various CLR runtime options for an app, much like the `MyApp.exe.config` XML file works in .NET 4.x today). However, the `MyApp.deps.json` file is designed to be processed by automated tools and should not be user-edited. Having the files as separate makes this clearer. We could use a different format for the deps file, but if we're already integrating a JSON parser into the host, it seems most appropriate to re-use that here. Also, there are diagnostic benefits to being able to read the `.deps.json` file in a simple text editor.
**IMPORTANT**: Portable Applications, i.e. those published without a specific RID, have some adjustments to this spec which is covered at the end.
## File format
The files are both JSON files stored in UTF-8 encoding. Below are sample files. Note that not all sections are required and some will be opt-in only (see below for more details). The `.config.json` file is completely optional, and in the `.deps.json` file, only the `runtimeTarget`, `targets` and `libraries` sections are required (and within the `targets` section, only the runtime-specific target is required).
The files are both JSON files stored in UTF-8 encoding. Below are sample files. Note that not all sections are required and some will be opt-in only (see below for more details). The `.runtimeconfig.json` file is completely optional, and in the `.deps.json` file, only the `runtimeTarget`, `targets` and `libraries` sections are required (and within the `targets` section, only the runtime-specific target is required).
### [appname].config.json
### [appname].runtimeconfig.json
```json
{
"runtimeConfig": {
"runtimeOptions": {
"gcServer": true,
"gcConcurrent": false
"gcConcurrent": false,
"framework": {
"name": "Microsoft.DotNetCore",
"version": "1.0.1"
}
}
}
```
@ -32,10 +38,7 @@ The files are both JSON files stored in UTF-8 encoding. Below are sample files.
### [appname].deps.json
```json
{
"runtimeTarget": {
"name": ".NETStandardApp,Version=v1.5/osx.10.10-x64",
"portable": false
},
"runtimeTarget": ".NETStandardApp,Version=v1.5/osx.10.10-x64",
"compilationOptions": {
"defines": [ "DEBUG" ]
},
@ -103,34 +106,26 @@ The files are both JSON files stored in UTF-8 encoding. Below are sample files.
"type": "package",
"sha512": "[base64 string]"
}
},
"runtimes": {
".NETStandardApp,Version=v1.5": {
"win7-x64": [ ],
"win7-x86": [ ],
"win8-x64": [ "win7-x64" ],
"win8-x86": [ "win7-x64" ],
"etc...": [ "etc..." ]
}
}
}
```
## Sections
### `runtimeConfig` Section (`.config.json`)
### `runtimeOptions` Section (`.runtimeconfig.json`)
This section is copied verbatim from an identical section in the input `project.json` file (with the exception of the `target` parameter which is generated by the compilation process). The `runtimeConfig` section specifies parameters to be provided to the runtime during initialization. Known parameters include:
* `gcServer` - Boolean indicating if the server GC should be used (Default: _TBD_). Note: This is designed to mirror the existing [app.config](https://msdn.microsoft.com/en-us/library/ms229357.aspx) setting)
* `gcConcurrent` - Boolean indicating if background garbage collection should be used (Default: _TBD_). Note: This is designed to mirror the existing [app.config](https://msdn.microsoft.com/en-us/library/yhwwzef8.aspx) setting).
* `framework` - Indicates the name and version of the shared framework to use when activating the application. The presence of this section indicates that the application is a portable app designed to use a shared redistributable framework.
* Others _TBD_
These settings are read by `corehost` to determine how to initialize the runtime. All versions of `corehost` **must ignore** settings in this section that they do not understand (thus allowing new settings to be added in later versions).
### `compilationOptions` Section (`.deps.json`)
This section is copied by storing the merged `compilationOptions` from the input `project.json`. The `project.json` can define three sets of compilation options: Global, Per-Configuration, and Per-Framework. However, the `runtime.config.json` is specific to a configuration and framework so there is only one merged section here.
This section is copied by storing the merged `compilationOptions` from the input `project.json`. The `project.json` can define three sets of compilation options: Global, Per-Configuration, and Per-Framework. However, the `[appname].runtimeconfig.json` is specific to a configuration and framework so there is only one merged section here.
The exact settings found here are specific to the compiler that produced the original application binary. Some example settings include: `defines`, `languageVersion` (C#/VB), `allowUnsafe` (C#), etc.
@ -176,7 +171,7 @@ When this project is built for `dnxcore50` in the `Debug` configuration, the out
### `runtimeTarget` Section (`.deps.json`)
This property contains the name of the target from `targets` that should be used by the runtime as well as a boolean indicating if this is a "portable" deployment, meaning there are runtime-specific assets within "subtargets" (see description of portable apps below) or if it is a "standalone" deployment meaning that all the assets are in a single target and published for a single RID. This is present to simplify `corehost` so that it does not have to parse or understand target names and the meaning thereof.
This property contains the name of the target from `targets` that should be used by the runtime. This is present to simplify `corehost` so that it does not have to parse or understand target names and the meaning thereof.
### `targets` Section (`.deps.json`)
@ -184,7 +179,7 @@ This section contains subsetted data from the input `project.lock.json`.
Each property under `targets` describes a "target", which is a collection of libraries required by the application when run or compiled in a certain framework and platform context. A target **must** specify a Framework name, and **may** specify a Runtime Identifier. Targets without Runtime Identifiers represent the dependencies and assets used for compiling the application for a particular framework. Targets with Runtime Identifiers represent the dependencies and assets used for running the application under a particular framework and on the platform defined by the Runtime Identifier. In the example above, the `.NETStandardApp,Version=v1.5` target lists the dependencies and assets used to compile the application for `dnxcore50`, and the `.NETStandardApp,Version=v1.5/osx.10.10-x64` target lists the dependencies and assets used to run the application on `dnxcore50` on a 64-bit Mac OS X 10.10 machine.
There will always be two targets in the `runtime.config.json` file: A compilation target, and a runtime target. The compilation target will be named with the framework name used for the compilation (`.NETStandardApp,Version=v1.5` in the example above). The runtime target will be named with the framework name and runtime identifier used to execute the application (`.NETStandardApp,Version=v1.5/osx.10.10-x64` in the example above). However, the runtime target will also be identified by name in the `runtimeOptions` section, so that `corehost` need not parse and understand target names.
There will always be two targets in the `[appname].runtimeconfig.json` file: A compilation target, and a runtime target. The compilation target will be named with the framework name used for the compilation (`.NETStandardApp,Version=v1.5` in the example above). The runtime target will be named with the framework name and runtime identifier used to execute the application (`.NETStandardApp,Version=v1.5/osx.10.10-x64` in the example above). However, the runtime target will also be identified by name in the `runtimeOptions` section, so that `corehost` need not parse and understand target names.
The content of each target property in the JSON is a JSON object. Each property of that JSON object represents a single dependency required by the application when compiled for/run on that target. The name of the property contains the ID and Version of the dependency in the form `[Id]/[Version]`. The content of the property is another JSON object containing metadata about the dependency.
@ -202,18 +197,12 @@ The `native` property of a dependency object lists the relative paths to Native
In compilation targets, the `runtime`, `resources` and `native` properties of a dependency are omitted, because they are not relevant to compilation. Similarly, in runtime targets, the `compile` property is omitted, because it is not relevant to runtime.
Only dependencies with a `type` value of `package` will have asset lists (`compile`, `runtime`, `resources`, `native`). Dependencies which are satisfied by projects will have all of their assets copied to the output directory, so they will not be listed in this file.
Only dependencies with a `type` value of `package` should be considered by `corehost`. There may be other items, used for other purposes (for example, Projects, Reference Assemblies, etc.
### `libraries` Section (`.deps.json`)
This section contains a union of all the dependencies found in the various targets, and contains common metadata for them. Specifically, it contains the `type`, as well as a boolean indicating if the library can be serviced (`serviceable`, only for `package`-typed libraries) and a SHA-512 hash of the package file (`sha512`, only for `package`-typed libraries.
**Open Question**: We could probably exclude projects from this set in order to reduce duplication. The main reason this is a separate section is because that's how the lock file is formatted and we want to try an keep this format the same if possible.
## `runtimes` Section
This section contains data gathered from the `runtime.json` files in packages during the restore process. It is used by the "portable" deployment model to encode the fallbacks through various RIDs. For example, `corehost` may detect that the current RID is `win8-x64`, due to running on Windows 8 in a 64-bit process. However, packages in the portable deployment model may provide assets for the `win7-x64` RID. In this case, `corehost` needs to know that `win8-x64` can load `win7-x64` assets. This data is encoded in the `runtimes` section of the deps file. The data is stored separately per Target Framework Moniker (though in practice, a `.deps.json` file will only ever have one entry; this is done simply to mirror the `project.lock.json` format). When running a particular target (as defined by `runtimeTarget`), where `portable` is set to `true`, only the `runtimes` entry matching that target name should be used.
## How the file is used
The file is read by two different components:
@ -230,22 +219,23 @@ Some of the sections in the `.deps.json` file contain data used for runtime comp
```json
{
"runtimeTarget": {
"name": ".NETStandardApp,Version=v1.5/osx.10.10-x64",
"portable": false
},
"targets": {
".NETStandardApp,Version=v1.5/osx.10.10-x64": {
"MyApp/1.0": {
"type": "project",
"dependencies": {
"AspNet.Mvc": "1.0.0"
}
},
"System.Foo/1.0.0": {
"type": "package",
"runtime": {
"lib/dnxcore50/System.Foo.dll": { }
}
},
"System.Banana/1.0.0": {
"type": "package",
"dependencies": {
"System.Foo": "1.0.0"
},
@ -273,7 +263,7 @@ Some of the sections in the `.deps.json` file contain data used for runtime comp
"System.Banana/1.0": {
"type": "package",
"sha512": "[base64 string]"
}
}
}
}
```
@ -282,7 +272,60 @@ Some of the sections in the `.deps.json` file contain data used for runtime comp
An application can be deployed in a "portable" deployment model. In this case, the RID-specific assets of packages are published within a folder structure that preserves the RID metadata. However, `corehost` does not use this folder structure, rather it reads data from the `.deps.json` file. Also, during deployment, the `.exe` file (`corehost` renamed) is not deployed.
In a `portable` target, the package entries may have an additional `subtargets` section detailing RID-specific assets. The `corehost` application should use this data, along with the current RID and the fallback data defined in the `runtimes` section to select one **and only one** "subtarget" out of each package individually. The most specific subtarget should always be selected. In practice, this means selecting the first RID shown on the appropriate line in `runtimes`. For example, given a package containing the following subtargets:
In the portable deployment model, the `*.runtimeConfig.json` file will contain the `runtimeOptions.framework` section:
```json
{
"runtimeOptions": {
"framework": {
"name": "NETCore.App",
"version": "1.0.1"
}
}
}
```
This data is used to locate the shared framework folder. The exact mechanics of which version are selected are defined elsewhere, but in general, it locates the shared runtime in the `shared` folder located beside it by using the relative path `shared/[runtimeOptions.framework.name]/[runtimeOptions.framework.version]`. Once it has applied any version roll-forward logic and come to a final path to the shared framework, it locates the `[runtimeOptions.framework.name].deps.json` file within that folder and loads it **first**.
Next, the deps file from the application is loaded and merged into this deps file (this is conceptual, the host implementation doesn't necessary have to directly merge the data ;)). Data from the app-local deps file trumps data from the shared framework.
The shared framework's deps file will also contain a `runtimes` section defining the fallback logic for all RIDs known to that shared framework. For example, a shared framework deps file installed into a Ubuntu machine may look something like the following:
```json
{
"runtimeTarget": {
"name": ".NETStandardApp,Version=v1.5",
"portable": false
},
"targets": {
".NETStandardApp,Version=v1.5": {
"System.Runtime/4.0.0": {
"runtime": "lib/netstandard1.5/System.Runtime.dll"
},
"... other libraries ...": {}
}
},
"libraries": {
"System.Runtime/4.0.0": {
"type": "package",
"serviceable": true,
"sha512": "[base64 string]"
},
"... other libraries ...": {}
},
"runtimes": {
"ubuntu.15.04-x64": [ "ubuntu.14.10-x64", "ubuntu.14.04-x64", "debian.8-x64", "linux-x64", "linux", "unix", "any", "base" ],
"ubuntu.14.10-x64": [ "ubuntu.14.04-x64", "debian.8-x64", "linux-x64", "linux", "unix", "any", "base" ],
"ubuntu.14.04-x64": [ "debian.8-x64", "linux-x64", "linux", "unix", "any", "base" ]
}
}
```
The host will have a RID embedded in it during compilation (for example, `win10-x64` for Windows 64-bit). It will look up the corresponding entry in the `runtimes` section to identify what the fallback list is for `win10-x64`. The fallbacks are identified from most-specific to least-specific. In the case of `win10-x64` and the example above, the fallback list is: `"win10-x64", "win10", "win81-x64", "win81", "win8-x64", "win8", "win7-x64", "win7", "win-x64", "win", "any", "base"` (note that an exact match on the RID itself is the first preference, followed by the first item in the fallback list, then the next item, and so on).
In the app-local deps file for a `portable` application, the package entries may have an additional `runtimeTargets` section detailing RID-specific assets. The `corehost` application should use this data, along with the current RID and the RID fallback data defined in the `runtimes` section of the shared framework deps file to select one **and only one** RID value out of each package individually. The most specific RID present within the package should always be selected.
Consider `corehost` built for `ubuntu.14.04-x64` and the following snippet from an app-local deps file (some sections removed for brevity).
```json
{
@ -292,61 +335,42 @@ In a `portable` target, the package entries may have an additional `subtargets`
"compile": {
"ref/netstandard1.5/System.Data.SqlClient.dll": {}
},
"subtargets": {
"runtime": {
"runtimes/unix/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "unix" },
"runtimes/win7-x64/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "win7-x64" },
"runtimes/win7-x86/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "win7-x86" }
"runtimeTargets": {
"runtimes/unix/lib/netstandard1.5/System.Data.SqlClient.dll": {
"assetType": "runtime",
"rid": "unix"
},
"native": {
"runtimes/win7-x64/native/sni.dll": { "rid": "win7-x64" },
"runtimes/win7-x86/native/sni.dll": { "rid": "win7-x86" }
"runtimes/win7-x64/lib/netstandard1.5/System.Data.SqlClient.dll": {
"assetType": "runtime",
"rid": "win7-x64"
},
"runtimes/win7-x86/lib/netstandard1.5/System.Data.SqlClient.dll": {
"assetType": "runtime",
"rid": "win7-x86"
},
"runtimes/win7-x64/native/sni.dll": {
"assetType": "native",
"rid": "win7-x64"
},
"runtimes/win7-x86/native/sni.dll": {
"assetType": "native",
"rid": "win7-x86"
}
}
}
}
},
"runtimes": {
".NETStandardApp,Version=v1.5": {
"win7-x64": [ ],
"win7-x86": [ ],
"win8-x64": [ "win7-x64" ],
"win8-x86": [ "win7-x86" ],
"win81-x64": [ "win7-x64" ],
"win81-x86": [ "win7-x86" ],
"win10-x64": [ "win7-x64" ],
"win10-x86": [ "win7-x86" ],
"osx.10.10-x64": [ "osx", "unix" ],
"osx.10.11-x64": [ "osx", "unix" ],
"rhel.7-x64": [ "linux-x64", "unix" ],
"rhel.7.1-x64": [ "linux-x64", "unix" ],
"rhel.7.2-x64": [ "linux-x64", "unix" ],
"rhel.7.3-x64": [ "linux-x64", "unix" ],
"centos.7-x64": [ "linux-x64", "unix" ],
"centos.7.1-x64": [ "linux-x64", "unix" ],
"debian.8-x64": [ "linux-x64", "unix" ],
"ubuntu.14.04-x64": [ "linux-x64", "unix" ],
"ubuntu.14.10-x64": [ "linux-x64", "unix" ],
"ubuntu.15.04-x64": [ "linux-x64", "unix" ],
"linuxmint.17-x64": [ "linux-x64", "unix" ],
"linuxmint.17.1-x64": [ "linux-x64", "unix" ],
"linuxmint.17.2-x64": [ "linux-x64", "unix" ],
"linuxmint.17.3-x64": [ "linux-x64", "unix" ]
}
}
}
```
(How the data in `runtimes` was generated is beyond the scope of this document, `dotnet-publish` and NuGet will work together to ensure the appropriate data is present).
When setting up the TPA and native library lists, it will do the following for the `System.Data.SqlClient` entry in the example above:
Consider `corehost` running on `debian.8-x64`. When setting up the TPA and native library lists, it will do the following for `System.Data.SqlClient`:
1. Add all entries from the root `runtime` and `native` sections (not present in the example). (Note: This is essentially the current behavior for the existing deps file format)
2. Add all appropriate entries from the `runtimeTargets` section, based on the `rid` property of each item:
1. Attempt to locate any item for the RID `ubuntu.14.04-x64`. If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists based on the `assetType` value (`runtime` for managed code, `native` for native code)
2. Reattempt the previous step using the first RID in the list provided by the list in the `runtimes."ubuntu.14.04-x64"` section of the shared framework deps file. If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists
3. Continue to reattempt the previous search for each RID in the list, from left to right until a match is found or the list is exhausted. Exhausting the list without finding an asset, when a `runtimeTargets` section is present is **not** an error, it simply indicates that there is no need for a runtime-specific asset for that package.
1. Add all entries from the root `runtime` and `native` sections (not present in the example). This is the current behavior
2. Add all appropriate entries from the `subtargets.runtime` and `subtargets.native` sections, based on the `rid` property of each item:
1. Attempt to locate any item (in both lists) for `debian.8-x64`. If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists
2. Reattempt the previous step using the first RID in the list provided by `runtimes.".NETStandardApp,Version=v1.5"."debian.8-x64"` (in this case `linux-x64`). If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists
3. Continue to reattempt the previous search for each RID in the list, from left to right until a match is found or the list is exhausted. Exhausting the list without finding an asset, when a `subtargets` section is present is **not** an error.
Note one important aspect about asset resolution: The resolution scope is **per-package**, **not per-application**, **nor per-asset**. For each individual package, the most appropriate RID is selected, and **all** assets taken from that package must match the selected RID exactly. For example, if a package provides both a `linux-x64` and a `unix` RID (in the `ubuntu.14.04-x64` example above), **only** the `linux-x64` asset would be selected for that package. However, if a different package provides only a `unix` RID, then the asset from the `unix` RID would be selected.
Note one important aspect about asset resolution: The resolution scope is **per-package**, **not per-application**, **nor per-asset**. For each individual package, the most appropriate RID is selected, and **all** assets taken from that package must match the selected RID exactly. For example, if a package provides both a `linux-x64` and a `unix` RID (in the `debian.8-x64` example above), **only** the `linux-x64` asset would be selected for that package. However, if a different package provides only a `unix` RID, then the asset from the `unix` RID would be selected.
The path to subtarget assets is resolved in the same way as normal assets with **one exception**. When searching app-local, rather than just looking for the simple file name in the app-local directory, subtarget assets are expected to be located in subdirectories matching their relative path information in the lock file. So the `native` `sni.dll` asset for `win7-x64` in the above example would be located at `APPROOT/runtimes/win7-x64/native/sni.dll`, rather than the normal app-local path of `APPROOT/sni.dll`
The path to a runtime-specific asset is resolved in the same way as a normal asset (first check Servicing, then Package Cache, App-Local, Global Packages Location, etc.) with **one exception**. When searching app-local, rather than just looking for the simple file name in the app-local directory, a runtime-specific asset is expected to be located in a subdirectory matching the relative path information for that asset in the lock file. So the `native` `sni.dll` asset for `win7-x64` in the `System.Data.SqlClient` example above would be located at `APPROOT/runtimes/win7-x64/native/sni.dll`, rather than the normal app-local path of `APPROOT/sni.dll`.