mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-10 10:00:57 +09:00
Improvements to CoreCLR Building, Debugging, and Testing Documentation (#75569)
* Quality Week 2022: The First Step to a Better Documentation. * Removed the Markdown Extension's additional development tags. * Removed redundant stuff. * Removed redundant stuff. * Removed guide testing versions to avoid confusion that they would be the only supported versions. * Addressed some Powershell comments, added a pointer to a yaml with links to other .NET sibling repos, and did a couple mini-corrections. Still got a few comments to address... * Fixed a ';:' with Powershell's syntax. * Addressed review comments: Redaction improvements, localization url's, improved code snippets, added info on individual subsets building configurations, changed COMPlus for DOTNET, and other misc improvements. * Addressed remaining comments. * Addressed some last comments regarding corerun, and the subset flags in the build scripts. Co-authored-by: Ivan Diaz <bluehorizon186@gmail.com>
This commit is contained in:
parent
cecdf891a4
commit
6811cc4dcb
29 changed files with 1811 additions and 1467 deletions
|
@ -1,43 +1,284 @@
|
|||
# Running Tests
|
||||
# Building and Running CoreCLR Tests
|
||||
|
||||
Details on test metadata can be found in [test-configuration.md](test-configuration.md).
|
||||
* [Requirements](#requirements)
|
||||
* [Overview](#overview)
|
||||
* [Building the Core_Root](#building-the-core_root)
|
||||
* [Building the Tests](#building-the-tests)
|
||||
* [Building an Individual Test](#building-an-individual-test)
|
||||
* [Building a Test Directory](#building-a-test-directory)
|
||||
* [Building a Test Subtree](#building-a-test-subtree)
|
||||
* [Building C++/CLI Native Test Components Against the Live Ref Assemblies](#building-ccli-native-test-components-against-the-live-ref-assemblies)
|
||||
* [Test Priorities](#test-priorities)
|
||||
* [Running the Tests](#running-the-tests)
|
||||
* [Running Individual Tests](#running-individual-tests)
|
||||
* [Tests Without a Main Method](#tests-without-a-main-method)
|
||||
* [PAL Tests (MacOS and Linux only)](#pal-tests-macos-and-linux-only)
|
||||
* [Building PAL Tests](#building-pal-tests)
|
||||
* [Running PAL Tests](#running-pal-tests)
|
||||
* [Modifying Tests](#modifying-tests)
|
||||
* [Investigating Test Failures](#investigating-test-failures)
|
||||
|
||||
## Build All Tests
|
||||
This guide will walk you through building and running the CoreCLR tests. These are located within the `src/tests` subtree of the runtime repo.
|
||||
|
||||
1) Build the CoreCLR product
|
||||
* [Unix](../../building/coreclr/linux-instructions.md)
|
||||
* [macOS](../../building/coreclr/osx-instructions.md)
|
||||
* [Windows](../../building/coreclr/README.md)
|
||||
2) [Build the libraries](../../building/libraries/README.md) in Release configuration. Pass the configuration of CoreCLR you just built to the build script (e.g. `-runtimeconfiguration debug`).
|
||||
3) From the root directory run the following command:
|
||||
* Non-Windows - `src/tests/build.sh`
|
||||
* Windows - `src\tests\build.cmd`
|
||||
* Supply `-h` for usage flags
|
||||
## Requirements
|
||||
|
||||
### Test priority
|
||||
In order to build CoreCLR tests, you will need to have built the runtime and the libraries (that is, _clr_ and _libs_ subsets). You can find more detailed instructions per platform in their dedicated docs:
|
||||
|
||||
The CoreCLR tests have two priorities, 0 and 1. The priority 0 tests run by default on all pull requests (PRs), while the priority 1 tests run in outerloop CI runs.
|
||||
* [Windows](/docs/workflow/building/coreclr/windows-instructions.md)
|
||||
* [MacOS](/docs/workflow/building/coreclr/macos-instructions.md)
|
||||
* [Linux](/docs/workflow/building/coreclr/linux-instructions.md)
|
||||
|
||||
### Examples
|
||||
For CoreCLR testing purposes, it is more than enough to simply build the _libs_ subset, as far as it concerns the libraries. If you want to know more in-depth about them, they have their own [libraries dedicated docs section](/docs/workflow/building/libraries/README.md).
|
||||
|
||||
* Build all tests priority 1 and higher
|
||||
* `build.cmd -priority=1`
|
||||
* `build.sh -priority1`
|
||||
## Overview
|
||||
|
||||
## Build Individual Test
|
||||
As mentioned in the introduction, all test-building work is done from the `src/tests` folder, so we will consider that our starting point for the rest of this guide.
|
||||
|
||||
Note: CoreCLR must be built prior to building an individual test. See the first step, above, for building all tests.
|
||||
Building the tests can be as simple as calling the build script without any arguments. This will by default look for a _Debug_ built runtime and _Release_ built libraries. However, by passing the appropriate flags, you can define which configurations you want to use. For example, let's suppose you have a _Checked_ runtime with _Debug_ libraries:
|
||||
|
||||
* Native Test: Build the generated CMake projects
|
||||
* Projects are auto-generated when the `build.sh`/`build.cmd` script is run
|
||||
* It is possible to explicitly run only the native test build with `build.sh/cmd skipmanaged`
|
||||
* Managed Test: Invoke `dotnet build` on the project directly. `dotnet` can be the `dotnet.sh` or `dotnet.cmd` script in the repo root.
|
||||
```
|
||||
<runtime-repo-root>/dotnet.sh build <runtime-repo-root>/src/tests/<path-to-project> -c <configuration>
|
||||
```
|
||||
* To build managed test projects with dependencies on native test projects, the native test project must first be built.
|
||||
```bash
|
||||
./src/tests/build.sh checked /p:LibrariesConfiguration=Debug
|
||||
```
|
||||
|
||||
## Additional Documents
|
||||
Note that for the libraries configuration, we are passing the argument directly to MSBuild instead of the build script, hence the `/p:LibrariesConfiguration` flag. Also, make sure you use the correct syntax depending on our platform. The _cmd_ script takes the arguments by placing, while the _sh_ script requires them to be with a hyphen.
|
||||
|
||||
* [Windows](windows-test-instructions.md)
|
||||
* [Non-Windows](unix-test-instructions.md)
|
||||
**NOTE**: Building the whole test suite is a very lengthy process, so it is highly recommended you build individual tests, and/or test subtrees as you need them, to make your workflow more efficient. This is explained in detail later on in this doc.
|
||||
|
||||
## Building the Core_Root
|
||||
|
||||
The Core_Root folder is some sort of "dev-easy-to-use full build" of the product. It contains the built runtime binaries, as well as the library packages required to run tests. It is required that you build the libraries subset (`--subset libs`) before this command can be run.
|
||||
|
||||
Note that, as mentioned in the section above, running the tests build script by default searches the libraries in _Release_ mode, regardless of the runtime configuration you specify. If you built your libraries in another configuration, then you have to pass down the appropriate flag `/p:LibrariesConfiguration=<your_config>`.
|
||||
|
||||
The simplest command to generate the _Core\_Root_ from the repository's root path is the following:
|
||||
|
||||
```cmd
|
||||
.\src\tests\build.cmd generatelayoutonly
|
||||
```
|
||||
|
||||
This example assumes you built CoreCLR on _Debug_ mode and the Libraries on _Release_ mode, hence no additional flags are needed. After the build is complete, you will be able to find the output in the `artifacts/tests/coreclr/<OS>.<arch>.<configuration>/Tests/Core_Root` folder.
|
||||
|
||||
## Building the Tests
|
||||
|
||||
The following subsections will explain how to segment the test suite according to your needs. There are three main scopes of building tests:
|
||||
|
||||
* Individual Test
|
||||
* Full Directory
|
||||
* Entire Subtree
|
||||
|
||||
When no set is specified, almost the whole test suite (`src/tests`) is built.
|
||||
|
||||
One of the most important attributes tests have is their **priority**. By default, only those tests with _Priority 0_ are built, regardless of whether it's an individual one, a directory, or a subtree, unless otherwise specified with the `-priority` flag. More info on this in [its dedicated section](#test-priorities). Regardless of which subset you build, all the outputs will be placed in `artifacts/tests/coreclr/<OS>.<arch>.<configuration>`.
|
||||
|
||||
**NOTE**: Some tests have native components to them. It is highly recommended you build all of those prior to attempting to build any managed test in the following sections, as it's not a very costly or lengthy process:
|
||||
|
||||
```cmd
|
||||
.\src\tests\build.cmd skipmanaged
|
||||
```
|
||||
|
||||
### Building an Individual Test
|
||||
|
||||
To build an individual test, you have to pass the `-test` flag along with the path to the test's `csproj` file to the build script. You can select more than one by repeating the `-test` flag. For example, let's try building a couple JIT tests:
|
||||
|
||||
On Windows:
|
||||
|
||||
```cmd
|
||||
.\src\tests\build.cmd test JIT\Intrinsics\MathRoundDouble_ro.csproj test JIT\Intrinsics\MathFloorDouble_ro.csproj
|
||||
```
|
||||
|
||||
On MacOS and Linux:
|
||||
|
||||
```bash
|
||||
./src/tests/build.sh -test:JIT/Intrinsics/MathRoundDouble_ro.csproj -test:JIT/Intrinsics/MathFloorDouble_ro.csproj
|
||||
```
|
||||
|
||||
Alternatively, you can call _build_ directly using the `dotnet.cmd/dotnet.sh` script at the root of the repo and pass all arguments directly yourself:
|
||||
|
||||
```bash
|
||||
./dotnet.sh build -c <Your Configuration> src/tests/path/to/test/csproj
|
||||
```
|
||||
|
||||
### Building a Test Directory
|
||||
|
||||
To build all the tests contained in an individual directory, you have to pass the `-dir` flag along with the directory's path to the build script. Just like with individual tests, you can select more than one by repeating the `-dir` flag. For example, let's try a couple of folders in the JIT subtree:
|
||||
|
||||
On Windows:
|
||||
|
||||
```cmd
|
||||
.\src\tests\build.cmd dir JIT\Methodical\Arrays\lcs dir JIT\Methodical\cctor\misc\Desktop
|
||||
```
|
||||
|
||||
On MacOS and Linux:
|
||||
|
||||
```bash
|
||||
./src/tests/build.sh -dir:JIT/Methodical/Arrays/lcs -dir:JIT/Methodical/cctor/misc/Desktop
|
||||
```
|
||||
|
||||
### Building a Test Subtree
|
||||
|
||||
To build a whole subtree, you have to pass the path to the root of the subtree you want with the `-tree` flag. Just like with any other subset, you can select more than one by repeating the `-tree` flag. For example, let's try building all the base services exceptions, and methodical JIT tests:
|
||||
|
||||
On Windows:
|
||||
|
||||
```cmd
|
||||
.\src\tests\build.cmd tree baseservices\exceptions tree JIT\Methodical
|
||||
```
|
||||
|
||||
On MacOS and Linux:
|
||||
|
||||
```bash
|
||||
./src/tests/build.sh -tree:baseservices/exceptions -tree:JIT/Methodical
|
||||
```
|
||||
|
||||
### Building C++/CLI Native Test Components Against the Live Ref Assemblies
|
||||
|
||||
By default, the _C++/CLI_ native test components build against the _ref pack_ from the SDK specified in the `global.json` file in the root of the repository. To build these components against the _ref assemblies_ produced in the build, pass the `-cmakeargs -DCPP_CLI_LIVE_REF_ASSEMBLIES=1` parameters to the test build. For example:
|
||||
|
||||
```bash
|
||||
./src/tests/build.sh skipmanaged -cmakeargs -DCPP_CLI_LIVE_REF_ASSEMBLIES=1
|
||||
```
|
||||
|
||||
### Test Priorities
|
||||
|
||||
As mentioned earlier in this guide, each test has a priority number assigned to them, and only tests with _Priority 0_ are built by default.
|
||||
|
||||
Now, here is where things get a little complicated. Test priority filtering is orthogonal to specifying test subsets. This means that even if when specifying tests, directories, and/or subtrees, you have to explicitly provide the priority if the test(s) of interest are not priority 0. Otherwise, the build will skip them.
|
||||
|
||||
Another very important thing to keep in mind, is that priorities are accumulative. This means that if for example, you pass `-priority=1` to the build script, all priority 0 _AND_ priority 1 tests get built.
|
||||
|
||||
Let's take one of the examples used in the previous subsections. Assume you want to build all _JIT Methodical Div_ tests, including both _pri0_ and _pri1_. This is how the command-line would look:
|
||||
|
||||
On Windows:
|
||||
|
||||
```cmd
|
||||
.\src\tests\build.cmd dir JIT\Methodical\divrem\div -priority=1
|
||||
```
|
||||
|
||||
On MacOS and Linux:
|
||||
|
||||
```bash
|
||||
./src/tests/build.sh -dir:JIT/Methodical/divrem/div -priority1
|
||||
```
|
||||
|
||||
**NOTE**: Yes, you're seeing it right. The `priority` flag is a bit different between the Windows and MacOS/Linux scripts.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
The simplest way to run in-bundle the tests you've built is by using the `run.cmd/run.sh` script after you've worked with `build.cmd/build.sh`. The running script takes flags very similarly to the build one. Let's suppose you have a _Checked_ runtime you want to test on an _x64_ machine. You'd run all your built tests with the following command-line:
|
||||
|
||||
```cmd
|
||||
.\src\tests\run.cmd x64 checked
|
||||
```
|
||||
|
||||
The `run.cmd/run.sh` scripts also have a number of flags you can pass to set specific conditions and environment variables, such as _JIT Stress_, _GC Stress_, and so on. Run it with only any one of the help flags for more details.
|
||||
|
||||
Once your tests are done running, a report will be generated with all the results under the `artifacts/log` folder, and will be named `TestRun_<Arch>_<Configuration>.html`. The tests that failed will be listed in a file called `TestRunResults_<OS>_<Arch>_<Configuration>.err`.
|
||||
|
||||
For individual test results and outputs, those are written in a `Reports` folder within the test root's directory (`artifacts/tests/coreclr/<OS>.<Arch>.<Configuration>`). For example, the results for the _JIT Intrinsics Math Round Double_ test shown in [Building an Individual Test](#building-an-individual-test), would be placed in `artifacts/tests/coreclr/<OS>.<Arch>.<Configuration>/Reports/JIT/Intrinsics/MathRoundDouble_ro`.
|
||||
|
||||
### Running Individual Tests
|
||||
|
||||
After you've built one (or more) tests, the way to run them is by calling the generated `cmd/sh` script alongside them. These scripts take three optional arguments:
|
||||
|
||||
* `-debug`: Receives the path of a debugger to run the test under in.
|
||||
* `-env`: Path to a _.env_ file to specify environment variables to be set for the test. More info about _dotenv_ can be found in [their repo](https://github.com/motdotla/dotenv).
|
||||
* -coreroot: The path to the Core_Root you wish to use. Note that this flag is mandatory unless you have the `CORE_ROOT` environment variable set. Then, you can omit it and the script will use that one.
|
||||
|
||||
If this list of parameters feels familiar, it's because it's virtually the same as the arguments that `corerun` receives. More info on `corerun` in its [how-to-use doc](/docs/workflow/testing/using-corerun-and-coreroot.md).
|
||||
|
||||
These scripts have a couple more hidden functionalities, which can be activated by setting their environment variables prior to running the script:
|
||||
|
||||
* Run with Crossgen2: `RunCrossGen2=1`
|
||||
* Build and run as composite: `CompositeBuildMode=1`. Note that this one depends on `RunCrossGen2` being set.
|
||||
|
||||
Let's run one of the Intrinsics tests as an example:
|
||||
|
||||
On Windows Command Prompt:
|
||||
|
||||
```cmd
|
||||
set CORE_ROOT=<repo_root>\artifacts\tests\coreclr\windows.<Arch>.<Configuration>\Tests\Core_Root
|
||||
cd path\to\JIT\Intrinsics\MathRoundDouble_ro
|
||||
.\MathRoundDouble_ro.cmd
|
||||
```
|
||||
|
||||
On MacOS/Linux:
|
||||
|
||||
```bash
|
||||
export CORE_ROOT=<repo_root>/artifacts/tests/coreclr/<OS>.<Arch>.<Configuration>/Tests/Core_Root
|
||||
cd path/to/JIT/Intrinsics/MathRoundDouble_ro
|
||||
./MathRoundDouble_ro.sh
|
||||
```
|
||||
|
||||
On Powershell:
|
||||
|
||||
```powershell
|
||||
$Env:CORE_ROOT = '<repo_root>\artifacts\tests\coreclr\windows.<Arch>.<Configuration>\Tests\Core_Root'
|
||||
cd path\to\JIT\Intrinsics\MathRoundDouble_ro
|
||||
.\MathRoundDouble_ro.cmd
|
||||
```
|
||||
|
||||
Alternatively, instead of setting the _CORE\_ROOT_ environment variable, you can specify it directly to the test's script via the `-coreroot` flag, as mentioned at the beginning of this section:
|
||||
|
||||
On Windows:
|
||||
|
||||
```cmd
|
||||
cd path\to\JIT\Intrinsics\MathRoundDouble_ro
|
||||
.\MathRoundDouble_ro.cmd -coreroot <repo_root>\artifacts\tests\coreclr\windows.<Arch>.<Configuration>\Tests\Core_Root
|
||||
```
|
||||
|
||||
On MacOS/Linux:
|
||||
|
||||
```bash
|
||||
cd path/to/JIT/Intrinsics/MathRoundDouble_ro
|
||||
./MathRoundDouble_ro.sh -coreroot=<repo_root>/artifacts/tests/coreclr/<OS>.<Arch>.<Configuration>/Tests/Core_Root
|
||||
```
|
||||
|
||||
#### Tests Without a Main Method
|
||||
|
||||
Guide on how to run tests without a `Main()` Method coming soon!
|
||||
|
||||
### PAL Tests (MacOS and Linux only)
|
||||
|
||||
The PAL layer tests are exclusive to Unix-based operating systems. This section will go on how to work with them.
|
||||
|
||||
#### Building PAL Tests
|
||||
|
||||
Firstly, build them by passing the `paltests` subset to the main build script of the repo:
|
||||
|
||||
```bash
|
||||
./build.sh -s clr.paltests
|
||||
```
|
||||
|
||||
#### Running PAL Tests
|
||||
|
||||
Once you're done building them, you can run them all either including or excluding the disabled tests:
|
||||
|
||||
_Including Disabled Tests:_
|
||||
|
||||
```bash
|
||||
./src/coreclr/pal/tests/palsuite/runpaltests.sh artifacts/bin/coreclr/<OS>.<Arch>.<Configuration>/paltests
|
||||
```
|
||||
|
||||
_Excluding Disabled Tests:_
|
||||
|
||||
```bash
|
||||
cd artifacts/bin/coreclr/<OS>.<Arch>.<Configuration>
|
||||
./paltests/runpaltests.sh paltests
|
||||
```
|
||||
|
||||
In order to run only specific tests, edit `paltestlist.txt` in under `src/coreclr/pal/tests/palsuite`, and adjust it to your needs (don't check in those changes though). The test(s) results will be output to `/tmp/PalTestOutput/default/pal_tests.xml`.
|
||||
|
||||
To disable tests in the CI, edit `src/coreclr/pal/tests/palsuite/issues.targets` accordingly.
|
||||
|
||||
## Modifying Tests
|
||||
|
||||
If you need to edit any given test's source code, simply make your changes and rebuild the test project. Then, you can re-run it as needed following the instructions detailed in the sections above.
|
||||
|
||||
## Investigating Test Failures
|
||||
|
||||
Upon completing a test run with `run.sh/run.cmd`, you may find one or more tests failing. If this is the case, there will be additional files detailing the failures in each test's `Reports` folder (see [Running the Tests](#running-the-tests) for more info regarding reports). There are 2 main files of interest:
|
||||
|
||||
* `<Test>.output.txt`: Contains all the information logged by the test.
|
||||
* `<Test>.error.txt`: Contains all the information reported by _CoreRun_ when the test process crashed.
|
||||
|
||||
The test's report will also contain the test command exactly as it run it, so you can investigate it further, either by running the app in the way you see fit and/or as the [Running Individual Tests](#running-individual-tests) details.
|
||||
|
|
|
@ -1,39 +1,36 @@
|
|||
# Testing Workloads
|
||||
|
||||
* [Multiple runtime packs](#multiple-runtime-packs)
|
||||
* [Limitations](#limitations)
|
||||
|
||||
Workloads based on packages in `artifacts` can be installed, and used for testing.
|
||||
|
||||
- This is done by installing a specified SDK version (`$(SdkVersionForWorkloadTesting)`) in `artifacts/bin/dotnet-workload`.
|
||||
- Then the manifest for the workload in `@(WorkloadIdForTesting)` is installed
|
||||
- Then workload packs are installed
|
||||
- packs, or manifests not generated by `runtime`, are restored from nuget
|
||||
|
||||
- The SDK is installed by `ProvisionSdkForWorkloadTesting` target
|
||||
- and the workload is installed by `InstallWorkloadUsingArtifacts` target, using the `InstallWorkloadFromArtifacts` task
|
||||
|
||||
- `@(WorkloadIdForTesting)`:
|
||||
* This is done by installing a specified SDK version (`$(SdkVersionForWorkloadTesting)`) in `artifacts/bin/dotnet-workload`.
|
||||
* Then the manifest for the workload in `@(WorkloadIdForTesting)` is installed
|
||||
* Then workload packs are installed
|
||||
* Packs or manifests not generated by `runtime`, are restored from nuget
|
||||
* The SDK is installed by `ProvisionSdkForWorkloadTesting` target and the workload is installed by `InstallWorkloadUsingArtifacts` target, using the `InstallWorkloadFromArtifacts` task `@(WorkloadIdForTesting)`:
|
||||
|
||||
Example for wasm:
|
||||
|
||||
```xml
|
||||
<WorkloadIdForTesting Include="wasm-tools"
|
||||
Name="microsoft.net.workload.mono.toolchain"
|
||||
ManifestName="Microsoft.NET.Workload.Mono.ToolChain"
|
||||
Version="$(PackageVersion)"
|
||||
VersionBand="$(SdkBandVersion)" />
|
||||
<WorkloadIdForTesting Include="wasm-tools"
|
||||
Name="microsoft.net.workload.mono.toolchain"
|
||||
ManifestName="Microsoft.NET.Workload.Mono.ToolChain"
|
||||
Version="$(PackageVersion)"
|
||||
VersionBand="$(SdkBandVersion)" />
|
||||
```
|
||||
|
||||
- Currently, this is used only by `src/mono/wasm/Wasm.Build.Tests`
|
||||
Currently, this is used only by `src/tests/BuildWasmApps/Wasm.Build.Tests`
|
||||
|
||||
## Multiple runtime packs
|
||||
|
||||
The workload depends on three runtime packs - single threaded, multithreaded, and for perf tracing. If you have a local
|
||||
runtime build, for say multithreaded, then the workload install will fail because of missing runtime pack nugets for
|
||||
the other two variants.
|
||||
The workload depends on three runtime packs - single threaded, multithreaded, and for perf tracing. If you have a local runtime build, for say multithreaded, then the workload install will fail because of missing runtime pack nugets for the other two variants.
|
||||
|
||||
For non-CI builds, we build the same runtime pack nuget but with the different expected names. So, essentially you get all
|
||||
the expected nugets, but they are all the same except for the name.
|
||||
For non-CI builds, we build the same runtime pack nuget but with the different expected names. So, essentially you get all the expected nugets, but they are all the same except for the name.
|
||||
|
||||
If you have all the nugets available, and want to avoid the above behavior then set `WasmSkipMissingRuntimeBuild=true`.
|
||||
|
||||
## Limitations:
|
||||
## Limitations
|
||||
|
||||
- The cross compiler package is built manually from the `InstallWorkloadUsingArtifacts` target
|
||||
The cross compiler package is built manually from the `InstallWorkloadUsingArtifacts` target.
|
||||
|
|
142
docs/workflow/testing/using-corerun-and-coreroot.md
Normal file
142
docs/workflow/testing/using-corerun-and-coreroot.md
Normal file
|
@ -0,0 +1,142 @@
|
|||
# Using Corerun To Run a .NET Application
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [The CoreRun](#the-corerun)
|
||||
* [Running Apps with CoreRun](#running-apps-with-corerun)
|
||||
* [Using CoreRun with the class library from the shared system-wide .NET installation](#using-corerun-with-the-class-library-from-the-shared-system-wide-net-installation)
|
||||
* [Using CoreRun to Execute a Published Self-Contained Application](#using-corerun-to-execute-a-published-self-contained-application)
|
||||
* [The Core_Root](#the-core_root)
|
||||
* [Additional CoreRun Options](#additional-corerun-options)
|
||||
|
||||
This guide will walk you through using the Corerun and Core_Root your own build from the runtime repo for testing, running apps, and so on. This doc assumes you've already built at least the _clr_ subset of the repo, and have the binaries under `artifacts/bin/coreclr/<OS>.<arch>.<configuration>`. If this is not your case, the [CoreCLR building docs](/docs/workflow/building/coreclr/README.md) have detailed instructions on how to get these artifacts.
|
||||
|
||||
## Introduction
|
||||
|
||||
To run a .NET app with the runtime you've built, you will need a _host_ program that will load the runtime, as well as all the other .NET libraries that your application might need. There are three main ways to go about this:
|
||||
|
||||
* Use your machine's installed .NET SDK and replace the necessary binaries in a self-contained app.
|
||||
* Use your build's _Dev Shipping Packages_ to run your app.
|
||||
* Use the _CoreRun_ host generated as part of your build's artifacts.
|
||||
|
||||
This guide focuses on the third of the bullet points described above. For the other two, we have docs dedicated to them:
|
||||
|
||||
* [Using your build with your machine's installed SDK](using-your-build-with-installed-sdk.md)
|
||||
* [Using your build's dev shipping packages](using-dev-shipping-packages.md)
|
||||
|
||||
## The CoreRun
|
||||
|
||||
The `corerun` binary is designed to be a platform agnostic tool for quick testing of a locally built .NET runtime. It helps facilitate .NET runtime development and investigation of test failures. This method is the most recommended one when you are making lots of changes that you want to keep continually testing and debugging, since it's the fastest way to apply them.
|
||||
|
||||
`Corerun` does not know about NuGet at all. It just needs to find the .NET runtime, `coreclr.dll`, `libcoreclr.dylib`, or `libcoreclr.so` depending on your platform, and any class library assemblies like for example, `System.Runtime.dll`, `System.IO.dll`, and so on.
|
||||
|
||||
`Corerun` achieves these goals by using heuristics in the following order:
|
||||
|
||||
1. Check if the user passed the `--clr-path` argument.
|
||||
2. Check if the `CORE_ROOT` environment variable is defined.
|
||||
3. Check if the .NET runtime binary is in the same directory as the `corerun` binary.
|
||||
|
||||
Regardless of which method is used to discover the .NET runtime binary, its location is used to also find all of the base class library assemblies. Additional directories can be included in the set of class library assemblies by defining the `CORE_LIBRARIES` environment variable.
|
||||
|
||||
The above heuristics can be used in a number of ways, providing you with multiple options to test using your `corerun`.
|
||||
|
||||
### Running Apps with CoreRun
|
||||
|
||||
In the following subsections, we will describe how to run any apps you might create, but using your built runtime instead of the one installed on your machine.
|
||||
|
||||
#### Using CoreRun with the class library from the shared system-wide .NET installation
|
||||
|
||||
For this example, let's create a simple _Hello World_ app:
|
||||
|
||||
```cmd
|
||||
mkdir HelloWorld && cd HelloWorld
|
||||
dotnet new console
|
||||
dotnet build
|
||||
```
|
||||
|
||||
Now, instead of running our app the usual way, we will use our newly built `corerun` to execute it using our build of the runtime. For this, we will follow the steps denoted below:
|
||||
|
||||
* First we will add the `Core_Root` folder to the `PATH` environment variable for ease of use. Note that you can always skip this step and fully qualify the name instead.
|
||||
* This example assumes you built on the _Debug_ configuration for the _x64_ architecture. Make sure you adjust the path accordingly to your kind of build.
|
||||
* Then, we also need the libraries. Since we only built the runtime, we will tell `corerun` to use the ones shipped with .NET's default installation on your machine.
|
||||
* This example assumes your default .NET installation's version is called "_7.0.0_". Same deal as with your runtime build path, adjust to the version you have installed on your machine.
|
||||
* Afterwards, we can finally run our app.
|
||||
|
||||
On Windows Command Prompt:
|
||||
|
||||
```cmd
|
||||
set PATH=%PATH%;<repo_root>\artifacts\bin\coreclr\windows.x64.Debug
|
||||
set CORE_LIBRARIES=%ProgramFiles%\dotnet\shared\Microsoft.NETCore.App\7.0.0
|
||||
corerun HelloWorld.dll
|
||||
```
|
||||
|
||||
On MacOS and Linux:
|
||||
|
||||
```bash
|
||||
# Change osx to linux if you're on a Linux machine.
|
||||
export PATH="$PATH:<repo_root>/artifacts/bin/coreclr/osx.x64.Debug"
|
||||
export CORE_LIBRARIES="/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.0"
|
||||
corerun HelloWorld.dll
|
||||
```
|
||||
|
||||
On Powershell:
|
||||
|
||||
```powershell
|
||||
# Note the '+=' since we're appending to the already existing PATH variable.
|
||||
# Also, replace the ';' with ':' if on Linux or MacOS.
|
||||
$Env:PATH += ';<repo_root>\artifacts\bin\coreclr\windows.x64.Debug'
|
||||
$Env:CORE_LIBRARIES = %ProgramFiles%\dotnet\shared\Microsoft.NETCore.App\7.0.0
|
||||
corerun HelloWorld.dll
|
||||
```
|
||||
|
||||
Once you set the `PATH` and `CORE_LIBRARIES` environment variables, when you issue `corerun HelloWorld.dll` following the snippets above, `corerun` now knows where to get the assemblies it needs. Note that this setup only has to be done once, as long as you stay in the same terminal instance. After a rebuild with more changes you might make, you can simply rerun `corerun` directly to run your application. The stage is set for it to work as expected.
|
||||
|
||||
#### Using CoreRun to Execute a Published Self-Contained Application
|
||||
|
||||
When an application is published as self-contained (`dotnet publish --self-contained`), it deploys all the class libraries needed as well. Thus if you simply change the `CORE_LIBRARIES` defined in the previous section to point at that publication directory, then the effect will be that your `corerun` will be getting all that libraries' code from your deployed application.
|
||||
|
||||
## The Core_Root
|
||||
|
||||
The test build script (`src/tests/build.cmd` or `src/tests/build.sh`) sets up a directory where it gathers the CoreCLR that has just been built with the pieces of the class libraries that the tests need. It places these binaries in the directory `artifacts/tests/coreclr/<OS>.<Arch>.<Configuration>/Tests/Core_Root`. Note that the test building process is a lengthy one, so it is recommended to only generate the Core_Root with the `-generatelayoutonly` flag to the tests build script, and build individual tests and/or test trees as you need them.
|
||||
|
||||
**NOTE**: In order to generate the Core_Root, you must also have built the libraries beforehand with `-subset libs`. More details in the [testing CoreCLR doc](/docs/workflow/testing/coreclr/testing.md).
|
||||
|
||||
Once you have your Core_Root, it's just a matter of calling it directly or adding it to your `PATH` environment variable, and you're ready to run your apps with it.
|
||||
|
||||
On Windows Command Prompt:
|
||||
|
||||
```cmd
|
||||
set PATH=%PATH%;<repo_root>\artifacts\tests\coreclr\windows.x64.Debug\Tests\Core_Root
|
||||
corerun HelloWorld.dll
|
||||
```
|
||||
|
||||
On MacOS and Linux:
|
||||
|
||||
```bash
|
||||
# Change linux to osx if you're on a MacOS machine.
|
||||
export PATH="$PATH:<repo_root>/artifacts/tests/coreclr/linux.x64.Debug/Tests/Core_Root"
|
||||
corerun HelloWorld.dll
|
||||
```
|
||||
|
||||
On Powershell:
|
||||
|
||||
```powershell
|
||||
# Note the '+=' since we're appending to the already existing PATH variable.
|
||||
# Also, replace the ';' with ':' if on Linux or MacOS.
|
||||
$Env:PATH += ';<repo_root>\artifacts\tests\coreclr\windows.x64.Debug\Tests\Core_Root'
|
||||
.\corerun HelloWorld.dll
|
||||
```
|
||||
|
||||
The advantage of generating the Core_Root, instead of sticking to the _corerun_ from the _clr_ build, is that you can also test and debug libraries at the same time.
|
||||
|
||||
### Additional CoreRun Options
|
||||
|
||||
The `corerun` binary has a few optional command-line arguments described when issuing `corerun --help`:
|
||||
|
||||
* `--clr-path <PATH>`: Pass the location of Core_Root on the command line. You can omit this flag if either the `corerun` you're using is within the Core_Root folder, or you have set the Core_Root's path by means of the `CORE_ROOT` environment variable.
|
||||
* Example: `corerun --clr-path /path/to/core_root HelloWorld.dll`
|
||||
* `--property <PROPERTY>`: Supply a property to pass to the .NET runtime during initialization.
|
||||
* Example: `corerun --property System.GC.Concurrent=true HelloWorld.dll`
|
||||
* `--debug`: Wait for a debugger to attach prior to loading the .NET runtime.
|
||||
* Example: `corerun --debug HelloWorld.dll`
|
||||
* `--env`: Pass the path to a `.env` file to specify environment variables for the test run. More info about `dotenv` can be found in [their repo](https://github.com/motdotla/dotenv).
|
||||
* For example, `corerun --env gcstress.env HelloWorld.dll`
|
|
@ -1,103 +0,0 @@
|
|||
|
||||
# Using `corerun` To Run a .NET Application
|
||||
|
||||
The page [Using your .NET Runtime Build with dotnet cli](../using-dotnet-cli.md) gives detailed instructions on using the standard
|
||||
command line host (that is, `dotnet.exe` or `dotnet`), and SDK to run an application with a local build of the
|
||||
.NET Runtime. This is the preferred mechanism for you to officially deploy
|
||||
your changes to other people since dotnet.exe and NuGet ensure that you end up with a consistent
|
||||
set of binaries that can work together.
|
||||
|
||||
However, packing and unpacking the runtime binaries adds extra steps to the deployment process. When
|
||||
working in a tight edit-build-debug loop, these extra steps become cumbersome.
|
||||
|
||||
For this tight edit-build-debug loop, there is a simplified alternative to `dotnet` called `corerun` which
|
||||
does not know about NuGet at all. It just needs to find the .NET runtime (for example, `coreclr.dll`)
|
||||
and any class library assemblies (for example, `System.Runtime.dll`, `System.IO.dll`, etc).
|
||||
|
||||
It does this using heuristics in the following order:
|
||||
|
||||
1. Check if the user passed the `--clr-path` argument.
|
||||
1. Check if the `CORE_ROOT` environment variable is defined.
|
||||
1. Check if the .NET runtime binary is in the same directory as the `corerun` binary.
|
||||
|
||||
Regardless of which method is used to discover the .NET runtime binary, its location is used to discover
|
||||
both the .NET runtime binary and all base class library assemblies. Additional directories can be included
|
||||
in the set of class library assemblies by defining the `CORE_LIBRARIES` environment variable.
|
||||
|
||||
The above heuristics can be used in a number of ways.
|
||||
|
||||
## Getting the class library from the shared system-wide runtime
|
||||
|
||||
Consider that you already have a .NET application assembly called `HelloWorld.dll` and wish to run it.
|
||||
You could make such an assembly by using an officially installed .NET runtime with `dotnet new` and `dotnet build` in a `HelloWorld` directory.
|
||||
|
||||
If you execute the following on Windows, the `HelloWorld` assembly will be run.
|
||||
|
||||
```cmd
|
||||
set PATH=%PATH%;<repo_root>\artifacts\tests\coreclr\windows.x64.Debug\Tests\Core_Root\
|
||||
set CORE_LIBRARIES=%ProgramFiles%\dotnet\shared\Microsoft.NETCore.App\1.0.0
|
||||
|
||||
corerun HelloWorld.dll
|
||||
```
|
||||
|
||||
On non-Windows platforms, setting environment variables is different but the logic is identical. For example, on macOS use `/usr/local/share` for `%ProgramFiles%`.
|
||||
|
||||
The `<repo_root>` represents the base of your dotnet/runtime repository. The first line puts the build output directory
|
||||
(your OS, architecture, and buildType may be different) and thus the `corerun` binary on your path.
|
||||
The second line tells `corerun` where to find class library assemblies. In this case we tell it to find them where
|
||||
the installation of `dotnet` placed its copy. The version number in the path may be different depending on what
|
||||
is currently installed on your system.
|
||||
|
||||
Thus when you run `corerun HelloWorld.dll`, `corerun` knows where to get the assemblies it needs.
|
||||
Once you set the path and `CORE_LIBRARIES` environment variable, after a rebuild you can simply use
|
||||
`corerun` to run your application – you don't have to move any binaries around.
|
||||
|
||||
## Using `corerun` to Execute a Published Application
|
||||
|
||||
When `dotnet publish` publishes an application, it deploys all the class libraries needed as well.
|
||||
Thus if you simply change the `CORE_LIBRARIES` definition in the previous instructions to point at
|
||||
that publication directory, but run the `corerun` from your build output, the effect will be that you
|
||||
run your new runtime getting all the other code needed from that deployed application. This is
|
||||
very convenient because you don't need to modify the deployed application in order to test
|
||||
your new runtime.
|
||||
|
||||
## How CoreCLR Tests use `corerun`
|
||||
|
||||
The test build script (`src/tests/build.cmd` or `src/tests/build.sh`) sets up a directory where it
|
||||
gathers the CoreCLR that has just been built with the pieces of the class library that tests need.
|
||||
It places this runtime in the directory
|
||||
`artifacts\tests\coreclr\<OS>.<Arch>.<BuildType>\Tests\Core_Root`
|
||||
starting at the repository root. The way the tests are expected to work is that you can set the environment
|
||||
variable `CORE_ROOT` to this directory – you don't have to set `CORE_LIBRARIES` since the test environment has copied all base class libraries assemblies to this `Core_Root` directory – and you can run any test. For example, after building the tests
|
||||
(running `src\tests\build` from the repository base), you can do the following on Windows to set up an environment where `corerun` can run any test.
|
||||
|
||||
```cmd
|
||||
set PATH=%PATH%;<repo_root>\artifacts\Product\windows.x64.Debug
|
||||
set CORE_ROOT=<repo_root>\artifacts\tests\coreclr\windows.x64.Debug\Tests\Core_Root
|
||||
```
|
||||
For example, the following runs the finalizeio test on Windows.
|
||||
|
||||
```cmd
|
||||
corerun artifacts\tests\coreclr\windows.x64.Debug\GC\Features\Finalizer\finalizeio\finalizeio\finalizeio.dll
|
||||
```
|
||||
|
||||
## Additional `corerun` options
|
||||
|
||||
The `corerun` binary is designed to be a platform agnostic tool for quick testing of a locally built .NET runtime.
|
||||
This means the `corerun` binary must be able to feasibly exercise any scenario the official `dotnet` binary is capable
|
||||
of. It must also be able to help facilitate .NET runtime development and investigation of test failures.
|
||||
See `corerun --help` for additional details.
|
||||
|
||||
**Options**
|
||||
|
||||
`--clr-path <PATH>` - Pass the location of Core Root on the command line.
|
||||
- For example, `corerun --clr-path /usr/scratch/private_build HelloWorld.dll`
|
||||
|
||||
`--property <PROPERTY>` - Supply a property to pass to the .NET runtime during initialization.
|
||||
- For example, `corerun --property System.GC.Concurrent=true HelloWorld.dll`
|
||||
|
||||
`--debug` - Wait for a debugger to attach prior to loading the .NET runtime.
|
||||
- For example, `corerun --debug HelloWorld.dll`
|
||||
|
||||
`--env` - Pass the path to a file in the [`dotenv`](https://github.com/motdotla/dotenv) format to specify environment variables for the test run.
|
||||
- For example, `corerun --env gcstress.env HelloWorld.dll`.
|
145
docs/workflow/testing/using-dev-shipping-packages.md
Normal file
145
docs/workflow/testing/using-dev-shipping-packages.md
Normal file
|
@ -0,0 +1,145 @@
|
|||
# Using your build's Shipping Packages with the .NET SDK
|
||||
|
||||
* [Requirements](#requirements)
|
||||
* [Build the Shipping Packages](#build-the-shipping-packages)
|
||||
* [Acquire the latest development .NET SDK](#acquire-the-latest-development-net-sdk)
|
||||
* [Creating and running the app with your build](#creating-and-running-the-app-with-your-build)
|
||||
* [Create and Configure the App](#create-and-configure-the-app)
|
||||
* [Write a small test](#write-a-small-test)
|
||||
* [Publish and Run the App](#publish-and-run-the-app)
|
||||
* [Making Changes and Consuming Updated Packages](#making-changes-and-consuming-updated-packages)
|
||||
|
||||
This guide will walk you through using the shipping packages of your own build from the runtime repo for testing, running apps, and so on. This is the lengthiest but most end-user-like of all the CoreCLR testing methods.
|
||||
|
||||
This guided focuses on this scenario, but we also have detailed docs on the other ways of testing:
|
||||
|
||||
* [Using your build with your machine's installed SDK](using-your-build-with-installed-sdk.md)
|
||||
* [Using CoreRun and CoreRoot](using-corerun-and-coreroot.md)
|
||||
|
||||
## Requirements
|
||||
|
||||
The following subsections will describe the requirements you will need to have ready in advance, and how to prepare them.
|
||||
|
||||
### Build the Shipping Packages
|
||||
|
||||
The shipping packages are comprised of four subsets of the runtime repo: Clr, Libraries, Packs, and the Host. So, to build all of those, issue the following command from the root of the repo:
|
||||
|
||||
For Windows:
|
||||
|
||||
```cmd
|
||||
.\build.cmd -s clr+libs+packs+host
|
||||
```
|
||||
|
||||
For MacOS and Linux:
|
||||
|
||||
```bash
|
||||
./build.sh -s clr+libs+packs+host
|
||||
```
|
||||
|
||||
This will place several installers, Nuget packages, compressed archives, and other files within `artifacts/packages/<configuration>/Shipping`. You could actually install your built runtime to your machine using the installers here, but that's not recommended.
|
||||
|
||||
### Acquire the latest development .NET SDK
|
||||
|
||||
The [installer repo](https://github.com/dotnet/installer) has downloads to all nightly builds for all the currently supported platforms. Find the one that matches your machine and download it.
|
||||
|
||||
To setup the nightly SDK, you can either install it to your machine or use a portable build. If you downloaded the _installer_, then just follow the usual installation instructions, and you're done.
|
||||
|
||||
To use a portable build (recommended way), first extract somewhere the _zip/tar.gz_ you downloaded at the beginning of this section. Then, you can either add the path where you extracted it to your `PATH` environment variable, or always fully qualify the path to the `dotnet` you extracted (e.g. `/path/to/nightly/build/dotnet`).
|
||||
|
||||
After setting up the new dotnet you can verify you are using the newer version by issuing the `dotnet --version` command on it. At the time of writing, the version ought to be equal or greater than `8.0.100-*`.
|
||||
|
||||
## Creating and running the app with your build
|
||||
|
||||
Now that you have your environment set up, let's get the test app prepared.
|
||||
|
||||
### Create and Configure the App
|
||||
|
||||
First, create a simple console app like you usually do:
|
||||
|
||||
```bash
|
||||
mkdir HelloWorld && cd HelloWorld
|
||||
dotnet new console
|
||||
```
|
||||
|
||||
**NOTE**: Make sure you're using the nightly SDK you downloaded in the previous step.
|
||||
|
||||
Next, we have to somehow tell the SDK that our built NuGet packages exist, and that we want to use them. For this purpose, we will create a `NuGet.Config` file within our app's folder with the `dotnet new nugetconfig` command.
|
||||
|
||||
This config file will require a handful of modifications to work as we need it to. Firstly, create a folder where you'll want Nuget to cache its stuff locally for this experiment. We will call it `LocalNugetCache` in this example. Then, edit your config file with the new stuff:
|
||||
|
||||
```xml
|
||||
<configuration>
|
||||
|
||||
<config>
|
||||
<!-- Set the "value" here to the folder you will be using for your local Nuget cache. -->
|
||||
<add key="globalPackagesFolder" value="Path/To/LocalNugetCache" />
|
||||
</config>
|
||||
|
||||
<packageSources>
|
||||
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
|
||||
<clear />
|
||||
|
||||
<!-- Any packages that might be required, but not present in your build, will have to be taken from the latest NuGet feed. -->
|
||||
<!-- More info on: https://github.com/dotnet/installer#installers-and-binaries -->
|
||||
<add key="dotnet8" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json" />
|
||||
|
||||
<!-- Set this path to where your Shipping Artifacts are located. Note that we are assuming a 'Debug' build in this example. -->
|
||||
<add key="local runtime" value="Path/To/Runtime/artifacts/packages/Debug/Shipping" />
|
||||
</packageSources>
|
||||
|
||||
</configuration>
|
||||
```
|
||||
|
||||
Once we have your `NuGet.Config` file ready, we have to make our project aware that we will be using a different runtime. Add the following to the `csproj` file of your app:
|
||||
|
||||
```xml
|
||||
<ItemGroup>
|
||||
<!-- At the time of writing, '8.0.0-dev' is the version of the runtime repo's shipping packages. -->
|
||||
<FrameworkReference Update="Microsoft.NETCore.App" RuntimeFrameworkVersion="8.0.0-dev" />
|
||||
</ItemGroup>
|
||||
```
|
||||
|
||||
If you're unsure of what version your packages are, it is included as part of their filenames. For example, pick the `nupkg` file that will be used with your app from your shipping folder (`artifacts/packages/<configuration>/Shipping`). It's name is something like `Microsoft.NETCore.App.Runtime.win-x64.8.0.0-dev.nupkg`, depending on the current version and your target platform.
|
||||
|
||||
### Write a small test
|
||||
|
||||
For illustration purposes, we will have our app print the version of the runtime in this example:
|
||||
|
||||
```csharp
|
||||
using System.Diagnostics;
|
||||
|
||||
var coreAssemblyInfo = FileVersionInfo.GetVersionInfo(typeof(object).Assembly.Location);
|
||||
Console.WriteLine($"Hello World from .NET {coreAssemblyInfo.ProductVersion}.");
|
||||
Console.WriteLine($"The location of System.Private.CoreLib.dll is '{typeof(object).Assembly.Location}'");
|
||||
```
|
||||
|
||||
### Publish and Run the App
|
||||
|
||||
The following command will build and publish your app:
|
||||
|
||||
```cmd
|
||||
dotnet publish -r win-x64
|
||||
```
|
||||
|
||||
Adjust the `win-x64` to match your machine's OS and architecture.
|
||||
|
||||
Running this little app should yield an output like the following:
|
||||
|
||||
```text
|
||||
Hello World from .NET 8.0.0-dev
|
||||
The location of System.Private.CoreLib.dll is '/path/to/your/app/bin/Debug/net7.0/win-x64/publish/System.Private.CoreLib.dll'
|
||||
```
|
||||
|
||||
You might be wondering why it says `net7.0` if we are using an `8.0.0` SDK. At the time of writing, we are still preparing all that's needed to fully migrate development to .NET 8. In the not so distant future, the path should be `net8.0` as you might expect, and this doc will be updated accordingly.
|
||||
|
||||
## Making Changes and Consuming Updated Packages
|
||||
|
||||
You've now successfully tested your runtime build. However, more likely than not, you will be making further changes that you'll want to test. The issue here is you can't simply build the repo again and have it work. This is because of the _NuGet Cache_ mentioned earlier. Since the version number doesn't change locally, NuGet doesn't realize changes have been made and thus uses its cached version. To get around this, we have to get rid of such cache. That's why we set a local one using the `globalPackagesFolder` in the `nuget.config` file we created.
|
||||
|
||||
So the steps to apply and test changes are the following:
|
||||
|
||||
1. Build the runtime again like you did in the "[Build the Shipping Packages section](#build-the-shipping-packages)". Note that if you only make changes to CoreCLR _(clr)_ or the libraries _(libs)_, you can omit the other in the build command.
|
||||
2. Delete the local NuGet cache.
|
||||
3. Publish and run your app again.
|
||||
|
||||
Now your app will be using the updated package.
|
166
docs/workflow/testing/using-your-build-with-installed-sdk.md
Normal file
166
docs/workflow/testing/using-your-build-with-installed-sdk.md
Normal file
|
@ -0,0 +1,166 @@
|
|||
# Using your .NET Runtime Build with the Installed SDK
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Acquire the latest development .NET SDK](#acquire-the-latest-development-net-sdk)
|
||||
* [Create a sample self-contained application](#create-a-sample-self-contained-application)
|
||||
* [Publish your App](#publish-your-app)
|
||||
* [Update CoreCLR and System.Private.CoreLib.dll with your build](#update-coreclr-and-systemprivatecorelibdll-with-your-build)
|
||||
* [Confirm that the app used your new runtime (Optional)](#confirm-that-the-app-used-your-new-runtime-optional)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* [If it's not using your copied binaries](#if-its-not-using-your-copied-binaries)
|
||||
* [If you get a consistency check assertion failure](#if-you-get-a-consistency-check-assertion-failure)
|
||||
* [If you get a JIT load error](#if-you-get-a-jit-load-error)
|
||||
|
||||
This guide will walk you through using your own build from the runtime repo for testing, running apps, and so on. This doc assumes you've already built at least the _clr_ subset of the repo, and have the binaries under `artifacts/bin/coreclr/<OS>.<arch>.<configuration>`. If this is not your case, the [CoreCLR building docs](/docs/workflow/building/coreclr/README.md) have detailed instructions on how to get these artifacts.
|
||||
|
||||
## Introduction
|
||||
|
||||
To run a .NET app with the runtime you've built, you will need a _host_ program that will load the runtime, as well as all the other .NET libraries that your application might need. There are three main ways to go about this:
|
||||
|
||||
* Use your machine's installed .NET SDK and replace the necessary binaries in a self-contained app.
|
||||
* Use your build's _Dev Shipping Packages_ to run your app.
|
||||
* Use the _CoreRun_ host generated as part of your build's artifacts.
|
||||
|
||||
This guide focuses on the first of the bullet points described above. For the other two, we have docs dedicated to them:
|
||||
|
||||
* [Using your build's dev shipping packages](using-dev-shipping-packages.md)
|
||||
* [Using CoreRun and CoreRoot](using-corerun-and-coreroot.md)
|
||||
|
||||
**NOTE**: It's unlikely, but it's possible that the officially released version of `dotnet` may not be compatible with the live repository. If this happens to you, then unfortunately, you will be limited to either installing a nightly build on your machine (not that recommended), or use another of the methods described above to test your build. This is because this method requires a _self-contained_ app, and the portable builds do not support this at the present time.
|
||||
|
||||
### Acquire the latest development .NET SDK
|
||||
|
||||
The [installer repo](https://github.com/dotnet/installer) has downloads to all nightly builds for all the currently supported platforms. Find the one that matches your machine and download it.
|
||||
|
||||
To setup the nightly SDK, you can either install it to your machine or use a portable build. If you downloaded the _installer_, then just follow the usual installation instructions, and you're done.
|
||||
|
||||
To use a portable build (check the note above though), first extract somewhere the _zip/tar.gz_ you downloaded at the beginning of this section. Then, you can either add the path where you extracted it to your `PATH` environment variable, or always fully qualify the path to the `dotnet` you extracted (e.g. `/path/to/nightly/build/dotnet`).
|
||||
|
||||
After setting up dotnet you can verify you are using the newer version by issuing the `dotnet --version` command on it. At the time of writing, the version must be equal or greater than `8.0.100-*`.
|
||||
|
||||
<!-- TODO: It feels like this link may or may not be more appropriate elsewhere. Need to dig deeper into the documentation, so leaving it here for the time being. -->
|
||||
For another small walkthrough see [Dogfooding .NET SDK](https://github.com/dotnet/runtime/blob/main/docs/project/dogfooding.md).
|
||||
|
||||
## Create a sample self-contained application
|
||||
|
||||
First things first. We need a sample app to test our runtime build on. Let's create a quick 'Hello World' app for this example.
|
||||
|
||||
```cmd
|
||||
mkdir HelloWorld
|
||||
cd HelloWorld
|
||||
dotnet new console
|
||||
```
|
||||
|
||||
In order to run with your local changes, the application needs to be self-contained, as opposed to running on the installed shared framework. In order to do that, you will need a `RuntimeIdentifier` for your project. You can specify it directly in the command-line later on, or you can write it in your app's `.csproj` file:
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
...
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
We are using Windows x64 for this example. Make sure you set it to the platform and configuration you have your build in. The codenames for the most common OS's are:
|
||||
|
||||
* _Windows_: `win`
|
||||
* _MacOS_: `osx`
|
||||
* _Linux_: `linux`
|
||||
|
||||
For example, if we were testing a MacOS ARM64 build, our `RuntimeIdentifier` would be `osx-arm64`.
|
||||
|
||||
### Publish your App
|
||||
|
||||
Now is the time to build and publish. This step will trigger _restore_ and _build_.
|
||||
|
||||
```cmd
|
||||
dotnet publish --self-contained
|
||||
```
|
||||
|
||||
**NOTE:** If publish fails to restore runtime packages, then you'll need to configure custom NuGet feeds. This is a side-effect of using a dogfood .NET SDK: Its dependencies are not yet on the regular NuGet feed. To configure this, you have to:
|
||||
|
||||
1. Run the command `dotnet new nugetconfig`
|
||||
2. Go to the newly created `NuGet.Config` file and replace the content with the following template:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
|
||||
<clear />
|
||||
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="dotnet8" value="https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet8/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
After you publish successfully, you will find all the binaries needed to run your application under `bin\Debug\net7.0\win-x64\publish`. You might be wondering why `net7.0` if we are using an `8.0.100` SDK. At the time of writing, we are still preparing all that's needed to fully migrate development to .NET 8. In the not so distant future, the path should be `net8.0` as you might expect, and this doc will be updated accordingly.
|
||||
|
||||
**But we are not done yet, you need to replace the published runtime files with the files from your local build!**
|
||||
|
||||
## Update CoreCLR and System.Private.CoreLib.dll with your build
|
||||
|
||||
The publishing step described above creates a directory that has all the files necessary to run your app, including the CoreCLR runtime and the required libraries. Out of all these binaries, there are three notable ones that will contain any changes you make to the runtime:
|
||||
|
||||
* `coreclr.dll (windows)/libcoreclr.dylib (macos)/libcoreclr.so (linux)`: Most modifications (with the exception of the JIT compiler and tools) that are C++ code update this binary.
|
||||
* `System.Private.CoreLib.dll`: If you modified managed C# code, it will end up here.
|
||||
* `clrjit.dll`: The JIT compiler. It is also required you copy this one to your published app.
|
||||
|
||||
Now, here comes the main deal to test your build. Once you have your self-contained app published, and CoreCLR built, you will replace the binaries listed above with the generated artifacts. Copy them from `artifacts/bin/coreclr/<OS>.<arch>.<configuration>/` to your app's publication directory, which by default is `your-app-folder/bin/<configuration>/net7.0/<os-code>-<arch>/publish`.
|
||||
|
||||
In our previous example this would be:
|
||||
|
||||
* From: `artifacts/bin/coreclr/windows.x64.Debug/`
|
||||
* To: `HelloWorld/bin/Debug/net7.0/win-x64/publish/`
|
||||
|
||||
## Confirm that the app used your new runtime (Optional)
|
||||
|
||||
Congratulations, you have successfully used your newly built runtime.
|
||||
|
||||
If you want to further ensure this is indeed the case before delving into more complex experiments and testing, you can run the following piece of code in your app:
|
||||
|
||||
```csharp
|
||||
using System.Diagnostics;
|
||||
|
||||
var coreAssemblyInfo = FileVersionInfo.GetVersionInfo(typeof(object).Assembly.Location);
|
||||
Console.WriteLine($"Core Runtime Info: {coreAssemblyInfo.ProductVersion}");
|
||||
Console.WriteLine($"System.Private.CoreLib.dll is located at: {typeof(object).Assembly.Location}");
|
||||
```
|
||||
|
||||
That should tell you the version, and which user and machine built the assembly, as well as the _commit hash_ of the code at the time of building:
|
||||
|
||||
```text
|
||||
Core Runtime Info: 8.0.0-dev
|
||||
System.Private.CoreLib.dll is located at: /path/to/your/app/bin/Debug/net7.0/win-x64/publish/System.Private.CoreLib.dll
|
||||
```
|
||||
|
||||
What you are looking for here is that the core runtime used is labelled as `-dev`. This means it is indeed using the one you built in the runtime repo. Also, ensure that the picked _System.Private.CoreLib.dll_ is indeed the one in your `publish` folder.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Here are a few very common errors you might encounter, and how to fix them.
|
||||
|
||||
### If it's not using your copied binaries
|
||||
|
||||
Make sure you are running the executable directly.
|
||||
|
||||
```cmd
|
||||
.\bin\Debug\net7.0\win-x64\publish\HelloWorld.exe
|
||||
```
|
||||
|
||||
If you use `dotnet run` it will overwrite your custom binaries before executing the app.
|
||||
|
||||
### If you get a consistency check assertion failure
|
||||
|
||||
This failure happens when you only copy `coreclr`, but not `System.Private.Corelib.dll` as well.
|
||||
|
||||
```text
|
||||
Assert failure(PID 13452 [0x0000348c], Thread: 10784 [0x2a20]): Consistency check failed: AV in clr at this callstack:
|
||||
```
|
||||
|
||||
### If you get a JIT load error
|
||||
|
||||
If you forget to also copy `clrjit.dll`, you will get the following error message:
|
||||
|
||||
```text
|
||||
Fatal error. Failed to load JIT compiler.
|
||||
```
|
|
@ -1,167 +0,0 @@
|
|||
|
||||
# Using your .NET Runtime Build
|
||||
|
||||
We assume that you have successfully built the repository and thus have files of the form
|
||||
```
|
||||
~/runtime/artifacts/bin/coreclr/<OS>.<arch>.<flavor>/
|
||||
```
|
||||
|
||||
To run your newly built .NET Runtime in addition to the application itself, you will need
|
||||
a 'host' program that will load the Runtime as well as all the other .NET libraries
|
||||
code that your application needs. The easiest way to get all this other stuff is to simply use the
|
||||
standard 'dotnet' host that installs with .NET SDK.
|
||||
|
||||
The released version of 'dotnet' tool may not be compatible with the live repository. The following steps
|
||||
assume use of a dogfood build of the .NET SDK.
|
||||
|
||||
## Acquire the latest development .NET SDK
|
||||
|
||||
- [Win 64-bit Latest](https://aka.ms/dotnet/6.0/daily/dotnet-sdk-win-x64.zip)
|
||||
- [macOS 64-bit Latest](https://aka.ms/dotnet/6.0/daily/dotnet-sdk-osx-x64.tar.gz)
|
||||
- [Others](https://github.com/dotnet/installer#installers-and-binaries)
|
||||
|
||||
To setup the SDK download the zip and extract it somewhere and add the root folder to your [path](../requirements/windows-requirements.md#adding-to-the-default-path-variable)
|
||||
or always fully qualify the path to dotnet in the root of this folder for all the instructions in this document.
|
||||
|
||||
After setting up dotnet you can verify you are using the newer version by:
|
||||
|
||||
`dotnet --info` -- the version should be greater than 3.0.0-*
|
||||
|
||||
For another small walkthrough see [Dogfooding .NET SDK](https://github.com/dotnet/runtime/blob/main/docs/project/dogfooding.md).
|
||||
|
||||
## Create sample self-contained application
|
||||
|
||||
At this point, you can create a new 'Hello World' program in the standard way.
|
||||
|
||||
```cmd
|
||||
mkdir HelloWorld
|
||||
cd HelloWorld
|
||||
dotnet new console
|
||||
```
|
||||
|
||||
### Change project to be self-contained
|
||||
|
||||
In order to update with your local changes, the application needs to be self-contained, as opposed to running on the
|
||||
shared framework. In order to do that you will need to add a `RuntimeIdentifier` to your project.
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
...
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
```
|
||||
For Windows you will want `win-x64`, for macOS `osx-x64` and `linux-x64` for Linux.
|
||||
|
||||
### Publish
|
||||
|
||||
Now is the time to publish. The publish step will trigger restore and build. You can iterate on build by calling `dotnet build` as
|
||||
needed.
|
||||
|
||||
```cmd
|
||||
dotnet publish
|
||||
```
|
||||
|
||||
**Note:** If publish fails to restore runtime packages you need to configure custom NuGet feeds. This is because you are using a dogfood .NET SDK: its dependencies are not yet on the regular NuGet feed. To do so you have to:
|
||||
|
||||
1. run `dotnet new nugetconfig`
|
||||
2. go to the `NuGet.Config` file and replace the content with:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
|
||||
<clear />
|
||||
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="dotnet6" value="https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet6/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
After you publish you will find you all the binaries needed to run your application under `bin\Debug\netcoreapp3.0\win-x64\publish\`.
|
||||
|
||||
```
|
||||
.\bin\Debug\netcoreapp3.0\win-x64\publish\HelloWorld.exe
|
||||
```
|
||||
|
||||
**But we are not done yet, you need to replace the published runtime files with the files from your local build!**
|
||||
|
||||
## Update CoreCLR from raw binary output
|
||||
|
||||
Updating CoreCLR from raw binary output is easier for quick one-off testing which is what this set of instructions
|
||||
outline but for consuming in a real .NET application you should use the nuget package instructions below.
|
||||
|
||||
The 'dotnet publish' step above creates a directory that has all the files necessary to run your app
|
||||
including the CoreCLR and the parts of CoreFX that were needed. You can use this fact to skip some steps if
|
||||
you wish to update the DLLs. For example typically when you update CoreCLR you end up updating one of two DLLs
|
||||
|
||||
* coreclr.dll - Most modifications (with the exception of the JIT compiler and tools) that are C++ code update
|
||||
this DLL.
|
||||
* System.Private.CoreLib.dll - If you modified C# it will end up here.
|
||||
|
||||
Thus after making a change and building, you can simply copy the updated binary from the `artifacts\bin\coreclr\<OS>.<arch>.<flavor>`
|
||||
directory to your publication directory (e.g. `helloWorld\bin\Debug\netcoreapp3.0\win-x64\publish`) to quickly
|
||||
deploy your new bits. In a lot of cases it is easiest to just copy everything from here to your publication directory.
|
||||
|
||||
You can build just the .NET Library part of the build by doing (debug, for release add 'release' qualifier)
|
||||
(on Linux / OSX us ./build.sh)
|
||||
```cmd
|
||||
.\build skiptests skipnative
|
||||
```
|
||||
Which builds System.Private.CoreLib.dll if you modify C# code. If you wish to only compile the coreclr.dll you can do
|
||||
```cmd
|
||||
.\build skiptests skipmscorlib
|
||||
```
|
||||
Note that this technique does not work on .NET Apps that have not been published (that is you have not created
|
||||
a directory with all DLLs needed to run the all) That is because the runtime is either fetched from the system-wide
|
||||
location that dotnet.exe installed, OR it is fetched from the local nuget package cache (which is where your
|
||||
build was put when you did a 'dotnet restore' and had a dependency on your particular runtime). In theory you
|
||||
could update these locations in place, but that is not recommended since they are shared more widely.
|
||||
|
||||
## (Optional) Confirm that the app used your new runtime
|
||||
|
||||
Congratulations, you have successfully used your newly built runtime.
|
||||
|
||||
As a hint you could add some code like:
|
||||
```
|
||||
var coreAssemblyInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(object).Assembly.Location);
|
||||
Console.WriteLine($"Hello World from Core {coreAssemblyInfo.ProductVersion}");
|
||||
Console.WriteLine($"The location is {typeof(object).Assembly.Location}");
|
||||
```
|
||||
|
||||
That should tell you the version and which user and machine build the assembly as well as the commit hash of the code
|
||||
at the time of building:
|
||||
|
||||
```
|
||||
Hello World from Core 4.6.26210.0 @BuiltBy: adsitnik-MININT-O513E3V @SrcCode: https://github.com/dotnet/runtime/tree/3d6da797d1f7dc47d5934189787a4e8006ab3a04
|
||||
The location is C:\coreclr\helloWorld\bin\Debug\netcoreapp3.0\win-x64\publish\System.Private.CoreLib.dll
|
||||
```
|
||||
|
||||
### If it's not using your copied binary
|
||||
|
||||
Make sure you are running the exe directly. If you use `dotnet run` it will overwrite your custom binaries before executing the app:
|
||||
|
||||
```
|
||||
.\bin\Debug\netcoreapp3.0\win-x64\publish\HelloWorld.exe
|
||||
```
|
||||
|
||||
### If you get a consistency check assertion failure
|
||||
|
||||
Something like this happens if you copied coreclr.dll but not System.Private.Corelib.dll as well.
|
||||
|
||||
```
|
||||
Assert failure(PID 13452 [0x0000348c], Thread: 10784 [0x2a20]): Consistency check failed: AV in clr at this callstack:
|
||||
```
|
||||
|
||||
## Using .NET SDK to run your .NET Application
|
||||
|
||||
If you don't like the idea of copying files manually you can follow [these instructions](../using-dotnet-cli.md) to use dotnet cli to do this for you.
|
||||
However the steps described here are the simplest and most commonly used by runtime developers for ad-hoc testing.
|
||||
|
||||
## Using CoreRun to run your .NET Application
|
||||
|
||||
Generally using dotnet.exe tool to run your .NET application is the preferred mechanism to run .NET Apps.
|
||||
However there is a simpler 'host' for .NET applications called 'CoreRun' that can also be used. The value
|
||||
of this host is that it is simpler (in particular it knows nothing about NuGet), but precisely because of this
|
||||
it can be harder to use (since you are responsible for insuring all the dependencies you need are gather together)
|
||||
See [Using CoreRun To Run .NET Application](using-corerun.md) for more.
|
Loading…
Add table
Add a link
Reference in a new issue