diff --git a/.editorconfig b/.editorconfig
index ed6489d6699f..851c0ee99c18 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -200,7 +200,8 @@ dotnet_diagnostic.CA1836.severity = warning
# Use 'Environment.ProcessPath'
dotnet_diagnostic.CA1839.severity = warning
# Do not call ToImmutableCollection on an ImmutableCollection value
-dotnet_diagnostic.CA2009.severity = warning
+# Temporarily disable to avoid regression in preview 1, revert back to warning when start using preview 2
+dotnet_diagnostic.CA2009.severity = none
# Avoid infinite recursion
dotnet_diagnostic.CA2011.severity = warning
# Initialize value type static fields inline
diff --git a/.github/fabricbot.json b/.github/fabricbot.json
index 8a67a4dbfcec..5850444abcec 100644
--- a/.github/fabricbot.json
+++ b/.github/fabricbot.json
@@ -208,6 +208,87 @@
}
]
}
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "breaking-change"
+ }
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "actions": [
+ {
+ "name": "addLabel",
+ "parameters": {
+ "label": "needs-breaking-change-doc-created"
+ }
+ },
+ {
+ "name": "addReply",
+ "parameters": {
+ "comment": "Added `needs-breaking-change-doc-created` label because this issue has the `breaking-change` label. \n\n1. [ ] Create and link to this issue a matching issue in the dotnet/docs repo using the [breaking change documentation template](https://aka.ms/dotnet/docs/new-breaking-change-issue), then remove this `needs-breaking-change-doc-created` label.\n\nTagging @dotnet/compat for awareness of the breaking change."
+ }
+ }
+ ],
+ "taskName": "Add breaking change doc label to issue"
+ },
+ "disabled": false
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "breaking-change"
+ }
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "actions": [
+ {
+ "name": "addLabel",
+ "parameters": {
+ "label": "needs-breaking-change-doc-created"
+ }
+ },
+ {
+ "name": "addReply",
+ "parameters": {
+ "comment": "Added `needs-breaking-change-doc-created` label because this PR has the `breaking-change` label. \n\nWhen you commit this breaking change:\n\n1. [ ] Create and link to this PR and the issue a matching issue in the dotnet/docs repo using the [breaking change documentation template](https://aka.ms/dotnet/docs/new-breaking-change-issue), then remove this `needs-breaking-change-doc-created` label.\n2. [ ] Ask a committer to mail the `.NET Breaking Change Notification` DL.\n\nTagging @dotnet/compat for awareness of the breaking change."
+ }
+ }
+ ],
+ "taskName": "Add breaking change doc label to PR"
+ },
+ "disabled": false
}
],
"userGroups": []
diff --git a/.vsts-ci.yml b/.vsts-ci.yml
index 0c49e755af6c..4d06ce3385dd 100644
--- a/.vsts-ci.yml
+++ b/.vsts-ci.yml
@@ -3,7 +3,7 @@ trigger:
branches:
include:
- main
- - release/7.0.3xx
+ - release/7.0.4xx
- internal/release/*
- exp/*
@@ -96,7 +96,7 @@ stages:
parameters:
platform:
name: 'Managed'
- container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7'
+ container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8'
- ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}:
- template: /eng/build.yml
parameters:
@@ -146,7 +146,7 @@ stages:
name: $(DncEngInternalBuildPool)
demands: ImageOverride -equals 1es-ubuntu-2204
${{ if eq(variables['System.TeamProject'], 'public') }}:
- helixTargetQueue: 'ubuntu.2204.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-amd64'
+ helixTargetQueue: ubuntu.2204.amd64.open
${{ if ne(variables['System.TeamProject'], 'public') }}:
helixTargetQueue: Ubuntu.2204.Amd64
strategy:
diff --git a/CODEOWNERS b/CODEOWNERS
index d97954a4eb18..96c8621f1d2e 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -26,6 +26,9 @@
/src/Assets/TestPackages/PackageLibraryTransitiveDependency/ @dotnet/aspnet-blazor-eng
/src/src/Assets/TestProjects/Razor*/ @dotnet/aspnet-blazor-eng
+# Area-Wasm
+/src/WasmSdk @lewing @radical @pavelsavara @maraf
+
# Area-Format
/src/Cli/dotnet/commands/dotnet-format @jmarolf @JoeRobich
/src/Tests/dotnet-format.Tests @jmarolf @JoeRobich
@@ -66,20 +69,26 @@
/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ClickOnce.targets @sujitnayak
# Area-Watch
-/src/Assets/TestProjects/Watch*/ @tmat @arkalyanms
-/src/Tests/dotnet-watch.Tests/ @tmat @arkalyanms
+/src/Assets/TestProjects/Watch*/ @tmat @arkalyanms @dotnet/roslyn-ide
+/src/Tests/dotnet-watch.Tests/ @tmat @arkalyanms @dotnet/roslyn-ide
/src/Tests/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/ @dotnet/aspnet-blazor-eng
-/src/BuiltInTools/* @tmat @arkalyanms
+/src/BuiltInTools/* @tmat @arkalyanms @dotnet/roslyn-ide
/src/BuiltInTools/BrowserRefresh @dotnet/aspnet-blazor-eng
# ApiCompat tools owned by runtime team
# Area-ApiCompat
-/src/ApiCompat/ @dotnet/area-infrastructure-libraries
-/src/Tests/Microsoft.DotNet.ApiCompatibility*/ @dotnet/area-infrastructure-libraries
-/src/Tests/Microsoft.DotNet.ApiCompat*/ @dotnet/area-infrastructure-libraries
-/src/Tests/Microsoft.DotNet.PackageValidation*/ @dotnet/area-infrastructure-libraries
+/src/ApiCompat/ @ericstj @dotnet/area-infrastructure-libraries @joperezr
+/src/Tests/Microsoft.DotNet.ApiCompatibility*/ @ericstj @dotnet/area-infrastructure-libraries @joperezr
+/src/Tests/Microsoft.DotNet.ApiCompat*/ @ericstj @dotnet/area-infrastructure-libraries @joperezr
+/src/Tests/Microsoft.DotNet.PackageValidation*/ @ericstj @dotnet/area-infrastructure-libraries @joperezr
# Area-GenAPI
/src/GenAPI/ @andriipatsula @dotnet/area-infrastructure-libraries
/src/Tests/Microsoft.DotNet.GenAPI/ @andriipatsula @dotnet/area-infrastructure-libraries
/src/Microsoft.DotNet.ApiSymbolExtensions/ @andriipatsula @dotnet/area-infrastructure-libraries
+
+# Area: dotnet containers
+/src/Cli/Containers @dotnet/sdk-container-builds-maintainers
+/src/Tests/containerize.UnitTests @dotnet/sdk-container-builds-maintainers
+/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests @dotnet/sdk-container-builds-maintainers
+/src/Tests/Microsoft.NET.Build.Containers.UnitTests @dotnet/sdk-container-builds-maintainers
diff --git a/Directory.Build.props b/Directory.Build.props
index 01df765884d4..12d6e4548d04 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -23,6 +23,9 @@
$(NoWarn);NU1701
+
+ $(NoWarn);CA2009
true
true
diff --git a/README.md b/README.md
index 88e01f449eac..4ec85183861d 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,10 @@ Please see the [Pull Request Timeline Guide](documentation/project-docs/SDK-PR-g
With the SDK repository being the home for many different areas, we've started trying to label incoming issues for the area they are related to using `Area-` labels. Then we rely on the [codeowners](https://github.com/dotnet/sdk/blob/main/CODEOWNERS) to manage and triages issues in their areas. Feel free to contact the owners listed in that file if you're not getting a response on a particular issue or PR. Please try to label new issues as that'll help us route them faster.
+For issues related to the central SDK team, typically they are assigned out to a team member in the first half of each week. Then each member is asked to review and mark those needing further discussion as "needs team triage" and otherwise setting a milestone for the issue. Backlog means we will consider it in the future if there is more feedback. Discussion means we have asked for more information from the filer. All other milestones indicate our best estimate for when a fix will be targeted for noting that not all issues will get fixed. If you are not getting a quick response on an issue assigned to a team member, please ping them.
+
+The example query used for triage of .NET SDK issues can be viewed [here](https://github.com/dotnet/sdk/issues?q=is%3Aissue+is%3Aopen+-label%3AArea-NuGet+-label%3AArea-format+-label%3AArea-implicitusings+-label%3AArea-SourceBuild+-label%3AArea-Host+-label%3AArea-NativeAOT+-label%3AArea-readytorun+-label%3AArea-websdk+-label%3AArea-watch+-label%3AArea-illink+-label%3AArea-aspnetcore+-label%3AArea-compatibility+-label%3A%22Area-dotnet+test%22+-label%3AArea-FSharp+-label%3AArea-GenAPI+-label%3AArea-ApiCompat+label%3Auntriaged+no%3Amilestone+no%3Aassignee+)
+
For PRs, we assign a reviewer once a week on Wednesday, looking only at PRs that are green in the build. If you are contributing:
* Get the PR green.
diff --git a/build/RunTestsOnHelix.cmd b/build/RunTestsOnHelix.cmd
index 6ae683f70871..cff44809ee2b 100644
--- a/build/RunTestsOnHelix.cmd
+++ b/build/RunTestsOnHelix.cmd
@@ -30,6 +30,7 @@ dotnet new --debug:ephemeral-hive
REM We downloaded a special zip of files to the .nuget folder so add that as a source
dotnet nuget list source --configfile %TestExecutionDirectory%\nuget.config
+PowerShell -ExecutionPolicy ByPass "dotnet nuget locals all -l | ForEach-Object { $_.Split(' ')[1]} | Where-Object{$_ -like '*cache'} | Get-ChildItem -Recurse -File -Filter '*.dat' | Measure"
dotnet nuget add source %DOTNET_ROOT%\.nuget --configfile %TestExecutionDirectory%\nuget.config
dotnet nuget remove source dotnet6-transport --configfile %TestExecutionDirectory%\nuget.config
diff --git a/containers.slnf b/containers.slnf
new file mode 100644
index 000000000000..a11c0fd22a92
--- /dev/null
+++ b/containers.slnf
@@ -0,0 +1,16 @@
+{
+ "solution": {
+ "path": "sdk.sln",
+ "projects": [
+ "src\\Cli\\Microsoft.DotNet.Cli.Utils\\Microsoft.DotNet.Cli.Utils.csproj",
+ "src\\Cli\\Microsoft.DotNet.InternalAbstractions\\Microsoft.DotNet.InternalAbstractions.csproj",
+ "src\\Containers\\Microsoft.NET.Build.Containers\\Microsoft.NET.Build.Containers.csproj",
+ "src\\Containers\\containerize\\containerize.csproj",
+ "src\\Containers\\packaging\\package.csproj",
+ "src\\Tests\\Microsoft.NET.Build.Containers.IntegrationTests\\Microsoft.NET.Build.Containers.IntegrationTests.csproj",
+ "src\\Tests\\Microsoft.NET.Build.Containers.UnitTests\\Microsoft.NET.Build.Containers.UnitTests.csproj",
+ "src\\Tests\\Microsoft.NET.TestFramework\\Microsoft.NET.TestFramework.csproj",
+ "src\\Tests\\containerize.UnitTests\\containerize.UnitTests.csproj"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/documentation/specs/runtime-configuration-file.md b/documentation/specs/runtime-configuration-file.md
index 73e2ff4aa642..b7b63c5f4fca 100644
--- a/documentation/specs/runtime-configuration-file.md
+++ b/documentation/specs/runtime-configuration-file.md
@@ -127,15 +127,16 @@ The files are both JSON files stored in UTF-8 encoding. Below are sample files.
This section is created when building a project. Settings include:
* `configProperties` - Indicates configuration properties to configure the runtime and the framework
- * Examples:
- * Full list of [configuration properties](https://github.com/dotnet/docs/blob/main/docs/core/run-time-config/index.md) for CoreCLR.
+ * Examples:
+ * Full list of [configuration properties](https://github.com/dotnet/docs/blob/main/docs/core/runtime-config/index.md) for CoreCLR.
* `System.GC.Server` (old: `gcServer`) - Boolean indicating if the server GC should be used (Default: `true`).
* `System.GC.Concurrent` (old: `gcConcurrent`) - Boolean indicating if background garbage collection should be used.
-* `framework` - Indicates the `name`, `version`, and other properties of the shared framework to use when activating the application including `applyPathes` and `rollForwardOnNoCandidateFx`. The presence of this section (or another framework in the new `frameworks` section) indicates that the application is a framework-dependent app.
-* `applyPatches` - When `false`, the most compatible framework version previously found is used. When `applyPatches` is unspecified or `true`, the framework from either the same or a higher version that differs only by the patch field will be used. See [roll-forward-on-no-candidate documentation](https://github.com/dotnet/core-setup/blob/main/Documentation/design-docs/roll-forward-on-no-candidate-fx.md) for more information.
-* `rollForwardOnNoCandidateFx` - Determines roll-forward behavior. Only applies to `production` releases. Values: 0(Off), 1 (roll forward on [minor] or [patch]), 2 (Roll forward on [major], [minor] or [patch])
- See [roll-forward-on-no-candidate documentation](https://github.com/dotnet/core-setup/blob/main/Documentation/design-docs/roll-forward-on-no-candidate-fx.md) for more information.
-* `frameworks` - This is an optional array added in 3.0 that allows multiple frameworks to be specified. The `name`, `version`, `applyPatches` and `rollForwardOnNoCandidateFx` properties are available. The `framework` section is no longer necessary in 3.0, but if present is treated as if it was the first framework in the `frameworks` section. The presence of frameworks in this section (or the `framework` section) indicates that the application is a framework-dependent app. See the notes at the end of this document for more information.
+* `framework` - Indicates the `name`, `version`, and other properties of the shared framework to use when activating the application including `applyPatches` and `rollForwardOnNoCandidateFx`. The presence of this section (or another framework in the new `frameworks` section) indicates that the application is a framework-dependent app.
+* `rollForward` - Introduced in .NET Core 3.0. Determines roll-forward behavior. Values: `LatestPatch`, `Minor`, `Major`, `LatestMinor`, `LatestMajor`, `Disable`. See [high-level design](https://github.com/dotnet/designs/blob/main/accepted/2019/runtime-binding.md#rollforward) and [detailed design](https://github.com/dotnet/runtime/blob/main/docs/design/features/framework-version-resolution.md) for more information.
+* `applyPatches` - **Deprecated in favor of `rollForward`**, please use `rollForward` property instead. When `false`, the most compatible framework version previously found is used. When `applyPatches` is unspecified or `true`, the framework from either the same or a higher version that differs only by the patch field will be used. See [roll-forward-on-no-candidate documentation](https://github.com/dotnet/runtime/blob/main/docs/design/features/roll-forward-on-no-candidate-fx.md) for more information.
+* `rollForwardOnNoCandidateFx` - **Deprecated in favor of `rollForward`**, please use `rollForward` property instead - Determines roll-forward behavior. Only applies to `production` releases. Values: 0(Off), 1 (roll forward on [minor] or [patch]), 2 (Roll forward on [major], [minor] or [patch])
+ See [roll-forward-on-no-candidate documentation](https://github.com/dotnet/runtime/blob/main/docs/design/features/roll-forward-on-no-candidate-fx.md) for more information.
+* `frameworks` - This is an optional array added in 3.0 that allows multiple frameworks to be specified. The `name`, `version`, `rollForward` (.NET Core 3.0 +), `applyPatches` (deprecated) and `rollForwardOnNoCandidateFx` (deprecated) properties are available. The `framework` section is no longer necessary in 3.0, but if present is treated as if it was the first framework in the `frameworks` section. The presence of frameworks in this section (or the `framework` section) indicates that the application is a framework-dependent app. See the notes at the end of this document for more information.
* `additionalProbingPaths` - Optional property which specifies additional paths to consider when looking for dependencies. The value is either a single string, or an array of strings.
* `tfm` - Optional string value which specifies the Target Framework Moniker.
@@ -143,7 +144,7 @@ These settings are read by host (apphost or dotnet executable) to determine how
### `compilationOptions` Section (`.deps.json`)
-This section is created during build from the project's settings. The exact settings found here are specific to the compiler that produced the original application binary. Some example settings include: `defines`, `languageVersion` (e.g. the version of C# or VB), `allowUnsafe` (a C# option), etc.
+This section is created during build from the project's settings. The exact settings found here are specific to the compiler that produced the original application binary. Some example settings include: `defines`, `languageVersion` (e.g. the version of C# or VB), `allowUnsafe` (a C# option), etc.
This section is ignored by the runtime host. It is only potentially used by the application itself.
### `runtimeTarget` Section (`.deps.json`)
@@ -152,8 +153,8 @@ This property contains the name of the target from `targets` that should be used
### `targets` Section (`.deps.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 which are platform agnostic. These targets can also represent dependencies and assets which are 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 `.NETCoreApp,Version=v2.1` target lists the dependencies and assets used to run and compile the application for `netcoreapp2.1`.
+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 which are platform agnostic. These targets can also represent dependencies and assets which are 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 `.NETCoreApp,Version=v2.1` target lists the dependencies and assets used to run and compile the application for `netcoreapp2.1`.
If the app was published specifically for 64-bit Mac OS X 10.10 machine, it would also contain a target `.NETCoreApp,Version=v2.1/osx.10.10-x64` which would list the dependencies and assets used to run the application on that specific platform.
There will always at least one target in the `[appname].deps.json` file: the platform neutral list of runtime and compilation dependencies. In cases of a platform specific application there would be two targets: a compilation target, and a runtime target. The compilation target will be named with the framework name used for the compilation (`.NETCoreApp,Version=v2.1` in the example above). The runtime target will be named with the framework name and runtime identifier used to execute the application (`.NETCoreApp,Version=v2.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 the host does not need to parse and understand target names.
@@ -205,7 +206,7 @@ This section is only present in the root framework's (so `Microsoft.NETCore.App`
The file is read by two different components:
-* The host uses it to determine what to place on the TPA and Native Library Search Path lists, as well as what runtime settings to apply (GC type, etc.).
+* The host uses it to determine what to place on the TPA and Native Library Search Path lists, as well as what runtime settings to apply (GC type, etc.).
* `Microsoft.Extensions.DependencyModel` uses it to allow a running managed application to query various data about it's dependencies. For example:
* To find all dependencies that depend on a particular package (used by ASP.NET MVC and other plugin-based systems to identify assemblies that should be searched for possible plugin implementations)
* To determine the reference assemblies used by the application when it was compiled in order to allow runtime compilation to use the same reference assemblies (used by ASP.NET Razor to compile views)
@@ -213,12 +214,12 @@ The file is read by two different components:
## Opt-In Compilation Data
-Some of the sections in the `.deps.json` file contain data used for runtime compilation. This data is not provided in the file by default. Instead, an MSBuild property `PreserveCompilationContext` must be set to `true` (typically in the project file) in order to ensure this data is added. Without this setting, the `compilationOptions` will not be present in the file, and the `targets` section will contain only the runtime dependencies.
+Some of the sections in the `.deps.json` file contain data used for runtime compilation. This data is not provided in the file by default. Instead, an MSBuild property `PreserveCompilationContext` must be set to `true` (typically in the project file) in order to ensure this data is added. Without this setting, the `compilationOptions` will not be present in the file, and the `targets` section will contain only the runtime dependencies.
Note that ASP.NET projects (those using `Microsoft.NET.Sdk.Web` SDK) has this property set to `true` by default.
## Framework-dependent Deployment Model
-An application can be deployed in a "framework-dependent" deployment model. In this case, the RID-specific assets of packages are published within a folder structure that preserves the RID metadata. However the host does not use this folder structure, rather it reads data from the `.deps.json` file.
+An application can be deployed in a "framework-dependent" deployment model. In this case, the RID-specific assets of packages are published within a folder structure that preserves the RID metadata. However the host does not use this folder structure, rather it reads data from the `.deps.json` file.
In the framework-dependent deployment model, the `*.runtimeConfig.json` file will contain the `runtimeOptions.framework` section:
@@ -356,46 +357,46 @@ In addition to specifying a dependency on more than one framework, the `framewor
Overriding a value is always "most restrictive". This means if `applyPatches` is already `false` in a lower-level framework, then it cannot be changed to `true`. For `rollForwardOnNoCandidateFx` the value 0=off is the most restrictive, then 1=minor\patch, then 2=major\minor\patch. For `version`, the highest version requested will be used.
-As an example of overriding settings, assume the following framework layering:
-- Application
-- Microsoft.AspNetCore.All
-- Microsoft.AspNetCore.App
-- Microsoft.NetCore.App
+As an example of overriding settings, assume the following framework layering:
+- Application
+- Microsoft.AspNetCore.All
+- Microsoft.AspNetCore.App
+- Microsoft.NetCore.App
-Except for Microsoft.NetCore.App (since it does not have a lower-level framework), each layer has a runtimeconfig.json setting specifying a single lower-layer framework's `name`, `version` and optional `rollForwardOnNoCandidateFx` and `applyPatches`.
+Except for Microsoft.NetCore.App (since it does not have a lower-level framework), each layer has a runtimeconfig.json setting specifying a single lower-layer framework's `name`, `version` and optional `rollForwardOnNoCandidateFx` and `applyPatches`.
-The normal hierarchy processing for most knobs, such as `rollForwardOnNoCandidateFx`:
- - a) Default value determined by the framework (e.g. roll-forward on [Minor])
- - b) Environment variable override (e.g. `DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX`)
- - c) Each layer's `runtimeOptions` override setting in its runtimeconfig.json, starting with app (e.g. `rollForwardOnNoCandidateFx`). Lower layers can override this.
+The normal hierarchy processing for most knobs, such as `rollForwardOnNoCandidateFx`:
+ - a) Default value determined by the framework (e.g. roll-forward on [Minor])
+ - b) Environment variable override (e.g. `DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX`)
+ - c) Each layer's `runtimeOptions` override setting in its runtimeconfig.json, starting with app (e.g. `rollForwardOnNoCandidateFx`). Lower layers can override this.
- d) The app's `frameworks` section in `[appname].runtimeconfig.json` which allows knobs per-framework.
- - e) A `--` command line value such as `--roll-forward-on-no-candidate-fx`
-
-In a hypothetical example, `Microsoft.AspNetCore.App` references version `2.2.0` of `Microsoft.NetCore.App` in `Microsoft.AspNetCore.App.runtimeconfig.json`:
-```json
-{
- "runtimeOptions": {
- "framework": {
- "name": "Microsoft.NetCore.App",
- "version": "2.2.0"
- },
- }
-}
+ - e) A `--` command line value such as `--roll-forward-on-no-candidate-fx`
+
+In a hypothetical example, `Microsoft.AspNetCore.App` references version `2.2.0` of `Microsoft.NetCore.App` in `Microsoft.AspNetCore.App.runtimeconfig.json`:
+```json
+{
+ "runtimeOptions": {
+ "framework": {
+ "name": "Microsoft.NetCore.App",
+ "version": "2.2.0"
+ },
+ }
+}
```
-However, if the app requires the newer version `2.2.1` of `Microsoft.NetCore.App`, then mechanism `d` is used. An example of the `frameworks` section for mechanism `d` in the app's `runtimeconfig.json`:
-```json
-{
- "runtimeOptions": {
- "framework": {
- "name": "Microsoft.AspNetCore.All",
- "version": "1.0.1"
- },
- "frameworks": [
- {
- "name": "Microsoft.AspNetCore.App",
+However, if the app requires the newer version `2.2.1` of `Microsoft.NetCore.App`, then mechanism `d` is used. An example of the `frameworks` section for mechanism `d` in the app's `runtimeconfig.json`:
+```json
+{
+ "runtimeOptions": {
+ "framework": {
+ "name": "Microsoft.AspNetCore.All",
+ "version": "1.0.1"
+ },
+ "frameworks": [
+ {
+ "name": "Microsoft.AspNetCore.App",
"version": "2.2.1",
- }
- ]
- }
-}
+ }
+ ]
+ }
+}
```
diff --git a/eng/Signing.props b/eng/Signing.props
index ef28b93907fe..5ad662051f2e 100644
--- a/eng/Signing.props
+++ b/eng/Signing.props
@@ -51,6 +51,7 @@
+
diff --git a/eng/SourceBuild.props b/eng/SourceBuild.props
index 61b9a9137083..5c9a2ccd8ba2 100644
--- a/eng/SourceBuild.props
+++ b/eng/SourceBuild.props
@@ -3,7 +3,9 @@
sdk
true
+ true
+
$(InnerBuildArgs) /p:Projects="$(InnerSourceBuildRepoRoot)\source-build.slnf"
diff --git a/eng/SourceBuildPrebuiltBaseline.xml b/eng/SourceBuildPrebuiltBaseline.xml
index c1b6dfbf0538..cdb0272805a2 100644
--- a/eng/SourceBuildPrebuiltBaseline.xml
+++ b/eng/SourceBuildPrebuiltBaseline.xml
@@ -1,5 +1,24 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 962acdd64907..b0cb4e0c9160 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,248 +1,255 @@
-
+
https://github.com/dotnet/templating
- 5ff28f5739bef80d0a30923b05f3f49d5d47541c
+ 5b21b87bf343ae53f68b4839a8fa2782cc97bd2e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
+
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/msbuild
- f93b24b5a88a37a3b6b122c7f65f910fcc2ba2f0
+ ac3f5ad89f3f04d080986607d504a838ed622fb9
+
-
+
https://github.com/dotnet/msbuild
- f93b24b5a88a37a3b6b122c7f65f910fcc2ba2f0
+ ac3f5ad89f3f04d080986607d504a838ed622fb9
-
+
+ https://github.com/dotnet/msbuild
+ ac3f5ad89f3f04d080986607d504a838ed622fb9
+
+
https://github.com/dotnet/fsharp
- 0b0c07d12f64502d28312d679a966b3f2285244e
+ 858e2df9631a385cbddef62eeb424f9b3071b031
-
+
https://github.com/dotnet/fsharp
- 0b0c07d12f64502d28312d679a966b3f2285244e
+ 858e2df9631a385cbddef62eeb424f9b3071b031
-
+
https://github.com/dotnet/format
- 2cb3e68c6b9a966114572fd63f2a20d2cb54a288
-
+ b63163320777cc2c0ac4cf6b0acdbdd1cef308b2
+
-
+
https://github.com/dotnet/roslyn
- 7347efa598bc5e34086f6c1078f1c0e864400d29
+ ef625f3b960594fcb3f902af88ad7c90df656516
-
+
https://github.com/dotnet/roslyn
- 7347efa598bc5e34086f6c1078f1c0e864400d29
+ ef625f3b960594fcb3f902af88ad7c90df656516
-
+
https://github.com/dotnet/roslyn
- 7347efa598bc5e34086f6c1078f1c0e864400d29
+ ef625f3b960594fcb3f902af88ad7c90df656516
-
+
https://github.com/dotnet/roslyn
- 7347efa598bc5e34086f6c1078f1c0e864400d29
+ ef625f3b960594fcb3f902af88ad7c90df656516
-
+
https://github.com/dotnet/roslyn
- 7347efa598bc5e34086f6c1078f1c0e864400d29
+ ef625f3b960594fcb3f902af88ad7c90df656516
-
+
https://github.com/dotnet/roslyn
- 7347efa598bc5e34086f6c1078f1c0e864400d29
+ ef625f3b960594fcb3f902af88ad7c90df656516
-
+
https://github.com/dotnet/roslyn
- 7347efa598bc5e34086f6c1078f1c0e864400d29
+ ef625f3b960594fcb3f902af88ad7c90df656516
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/nuget/nuget.client
- 00375a7dfc2e2687c95ada0a0d24b570dc807d5d
+ 87ce6f59e9cf4f5a32d7ba16f537b6b791d9fcc6
-
+
https://github.com/microsoft/vstest
- 3990c633bcf933291f40d44c0b7586c3a6e89d55
+ 10eebba738292e0154358aeb5cc7e108dbe2067f
+
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
https://github.com/dotnet/linker
c790896f128957acd2999208f44f09ae1e826c8c
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/windowsdesktop
- 7514f9bc0755cdb942b1426c99e57abb129f6f43
+ 938425561491e90c260f46a5d3d0b1648f4bfc24
-
+
https://github.com/dotnet/windowsdesktop
- 7514f9bc0755cdb942b1426c99e57abb129f6f43
+ 938425561491e90c260f46a5d3d0b1648f4bfc24
-
+
https://github.com/dotnet/windowsdesktop
- 7514f9bc0755cdb942b1426c99e57abb129f6f43
+ 938425561491e90c260f46a5d3d0b1648f4bfc24
-
+
https://github.com/dotnet/windowsdesktop
- 7514f9bc0755cdb942b1426c99e57abb129f6f43
+ 938425561491e90c260f46a5d3d0b1648f4bfc24
-
+
https://github.com/dotnet/wpf
- c37ab558d3aebf3bfe0038c86e8a4be78d09e03c
+ e098ba7853201aeb520fee813a440875a513c46b
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/razor
- cd9273ff529ec2103c054c0620870d977c08e0a9
+ 105a50d1a4d64236e8a7a8a1d898fa261914efe7
-
- https://github.com/dotnet/razor
- cd9273ff529ec2103c054c0620870d977c08e0a9
-
-
+
https://github.com/dotnet/razor
- cd9273ff529ec2103c054c0620870d977c08e0a9
+ 105a50d1a4d64236e8a7a8a1d898fa261914efe7
-
+
https://github.com/dotnet/razor
- cd9273ff529ec2103c054c0620870d977c08e0a9
+ 105a50d1a4d64236e8a7a8a1d898fa261914efe7
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
-
+
https://github.com/dotnet/aspnetcore
- ce8e0ce086b0be93d25b985e1c4cdf3fe6d7bc21
+ b8646ba5d46058ac28da434e7f9393c505e85601
https://github.com/dotnet/xdt
9a1c3e1b7f0c8763d4c96e593961a61a72679a7b
-
+
https://github.com/dotnet/roslyn-analyzers
- 50f62a926806bc75f294b5f738bc6694e0941361
+ 3e168a5398d6220a3d6dd6eff080c5ed4eeee876
-
+
https://github.com/dotnet/roslyn-analyzers
- 50f62a926806bc75f294b5f738bc6694e0941361
+ 3e168a5398d6220a3d6dd6eff080c5ed4eeee876
+
+
+ https://github.com/dotnet/roslyn-analyzers
+ 3e168a5398d6220a3d6dd6eff080c5ed4eeee876
@@ -254,37 +261,78 @@
8374d5fca634a93458c84414b1604c12f765d1ab
-
+
https://github.com/dotnet/source-build-externals
- 54b1cf7905203a71e6883d2a3b8ea61d487cefdb
+ 834923aef31d157aec19a2b99d5494cea29dcc9e
+
+ https://github.com/dotnet/source-build-reference-packages
+ 453ab23d599ac904ded70bd9194959a76b05702f
+
+
+
+ https://github.com/dotnet/deployment-tools
+ 9e870996b8bf0b91a791edd1039bfd23bdd01af8
+
+
+ https://github.com/dotnet/sourcelink
+ 33aae13933557fafc954eb1d00d7f4818d46a1cf
+
+
+
+ https://github.com/dotnet/sourcelink
+ 33aae13933557fafc954eb1d00d7f4818d46a1cf
+
+
+ https://github.com/dotnet/sourcelink
+ 33aae13933557fafc954eb1d00d7f4818d46a1cf
+
+
+ https://github.com/dotnet/sourcelink
+ 33aae13933557fafc954eb1d00d7f4818d46a1cf
+
+
+ https://github.com/dotnet/sourcelink
+ 33aae13933557fafc954eb1d00d7f4818d46a1cf
+
+
+ https://github.com/dotnet/sourcelink
+ 33aae13933557fafc954eb1d00d7f4818d46a1cf
+
+
+
+ https://github.com/dotnet/deployment-tools
+ 9e870996b8bf0b91a791edd1039bfd23bdd01af8
+
+
-
+
https://github.com/dotnet/arcade
- c4a85adbff520f62bfade7a6132f471506c3d35a
+ d14c4adbdbb8c7ee060f9e333883fc9890939b66
-
+
https://github.com/dotnet/arcade
- c4a85adbff520f62bfade7a6132f471506c3d35a
+ d14c4adbdbb8c7ee060f9e333883fc9890939b66
-
+
https://github.com/dotnet/arcade
- c4a85adbff520f62bfade7a6132f471506c3d35a
+ d14c4adbdbb8c7ee060f9e333883fc9890939b66
-
+
https://github.com/dotnet/arcade
- c4a85adbff520f62bfade7a6132f471506c3d35a
+ d14c4adbdbb8c7ee060f9e333883fc9890939b66
-
+
https://github.com/dotnet/runtime
- af18fd07d1bb5a0d923a49c39b19c6fbcb6dc07b
+ a66405f0cb49fec9cbe001fcec8927372cd4a58e
-
+
https://github.com/dotnet/xliff-tasks
- 69157952aba0f08738249af4454b045b553614c4
+ f35dcbb16190810eb88b103fb1f2cd48a3a76cf0
diff --git a/eng/Versions.props b/eng/Versions.props
index 39369e3acbb8..efa55cf44751 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -13,7 +13,7 @@
8.0.100
preview
- 2
+ 4
false
release
@@ -23,47 +23,46 @@
15.4.8
15.4.8
15.4.8
- 1.0.0-20200708.1
+ 1.0.0-20230414.1
2.1.0-preview2-26306-03
- 2.19.0
+ 2.21.0
2.0.1-servicing-26011-01
13.0.1
- $(NewtonsoftJsonPackageVersion)
1.2.0-beta.435
- 6.0.0
+ 7.0.0
4.0.0
- 6.0.0
- 8.0.0-beta.23120.1
+ 7.0.0
+ 8.0.0-beta.23224.1
7.0.0-preview.22423.2
- 8.0.0-preview.2.23123.1
+ 8.0.0-preview.4.23224.2
4.3.0
4.3.0
4.0.5
- 6.0.0
- 8.0.0-preview.2.23123.1
+ 7.0.2
+ 8.0.0-preview.4.23224.2
4.6.0
2.0.0-beta4.22564.1
- 1.0.0-preview5.1.22263.1
+ 1.0.0-preview.6.23206.1
3.0.4496
- 8.0.0-preview.2.23123.1
- 8.0.0-preview.2.23123.1
- 8.0.0-preview.2.23123.1
+ 8.0.0-preview.4.23224.2
+ 8.0.0-preview.4.23224.2
+ 8.0.0-preview.4.23224.2
$(MicrosoftNETCoreAppRuntimewinx64PackageVersion)
- 8.0.0-preview.2.23123.1
- 8.0.0-preview.2.23123.1
- 8.0.0-preview.2.23123.1
+ 8.0.0-preview.4.23224.2
+ 8.0.0-preview.4.23224.2
+ 8.0.0-preview.4.23224.2
6.0.0
$(MicrosoftExtensionsDependencyModelPackageVersion)
6.0.0
- 8.0.0-preview.2.23123.1
+ 8.0.0-preview.4.23224.2
7.0.0
- 6.6.0-preview.2.23
+ 6.7.0-preview.1.19
$(NuGetBuildTasksPackageVersion)
6.0.0-rc.278
$(NuGetBuildTasksPackageVersion)
@@ -80,27 +79,28 @@
- 17.6.0-preview-20230221-02
+ 17.7.0-preview.23219.2
$(MicrosoftNETTestSdkPackageVersion)
$(MicrosoftNETTestSdkPackageVersion)
- 8.0.0-preview.2.23123.1
- 8.0.0-preview.2.23123.1
- 8.0.0-preview.2.23123.1
+ 8.0.0-preview.4.23224.2
+ 8.0.0-preview.4.23224.2
+ 8.0.0-preview.4.23224.2
- 8.0.405501
+ 8.0.422401
- 8.0.0-preview1.23121.1
+ 8.0.0-preview.23223.2
+ 3.3.5-beta1.23223.2
- 17.6.0-preview-23122-03
+ 17.7.0-preview-23221-02
$(MicrosoftBuildPackageVersion)
- 8.0.100-preview.2.23123.2
+ 8.0.100-preview.4.23224.6
$(MicrosoftTemplateEngineAbstractionsPackageVersion)
$(MicrosoftTemplateEngineAbstractionsPackageVersion)
$(MicrosoftTemplateEngineAbstractionsPackageVersion)
@@ -133,39 +133,37 @@
- 12.5.0-beta.23122.4
+ 12.5.0-beta.23221.1
- 4.6.0-2.23122.3
- 4.6.0-2.23122.3
- 4.6.0-2.23122.3
- 4.6.0-2.23122.3
- 4.6.0-2.23122.3
- 4.6.0-2.23122.3
- 4.6.0-2.23122.3
+ 4.7.0-1.23222.1
+ 4.7.0-1.23222.1
+ 4.7.0-1.23222.1
+ 4.7.0-1.23222.1
+ 4.7.0-1.23222.1
+ 4.7.0-1.23222.1
+ 4.7.0-1.23222.1
$(MicrosoftNetCompilersToolsetPackageVersion)
- 4.6.0-2.23081.23
- 8.0.0-preview.2.23122.6
- 8.0.0-preview.2.23122.6
- 8.0.0-preview.2.23122.6
- 8.0.0-preview.2.23122.6
- 8.0.0-preview.2.23122.6
- 8.0.0-preview.2.23122.6
+ 8.0.0-preview.4.23224.5
+ 8.0.0-preview.4.23224.5
+ 8.0.0-preview.4.23224.5
+ 8.0.0-preview.4.23224.5
+ 8.0.0-preview.4.23224.5
+ 8.0.0-preview.4.23224.5
- 7.0.0-preview.23122.4
- 7.0.0-preview.23122.4
- 7.0.0-preview.23122.4
- 7.0.0-preview.23122.4
+ 7.0.0-preview.23220.3
+ 7.0.0-preview.23220.3
+ 7.0.0-preview.23220.3
- 8.0.0-preview.2.23121.2
+ 8.0.0-preview.5.23223.2
@@ -174,7 +172,16 @@
- 1.0.0-beta.23116.1
+ 1.0.0-beta.23218.1
+
+
+
+ 8.0.0-beta.23222.2
+ 8.0.0-beta.23222.2
+ 8.0.0-beta.23222.2
+ 8.0.0-beta.23222.2
+ 8.0.0-beta.23222.2
+ 8.0.0-beta.23222.2
@@ -184,8 +191,9 @@
6.10.0
6.1.0
- 8.0.0-beta.23120.1
+ 8.0.0-beta.23224.1
4.8.2
+ 1.3.2
6.0.0-beta.22262.1
diff --git a/eng/build.yml b/eng/build.yml
index 2f75f6dbdbb0..560b06cacc9b 100644
--- a/eng/build.yml
+++ b/eng/build.yml
@@ -15,13 +15,13 @@ parameters:
timeoutInMinutes: 180
jobs:
-- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.SourceBranch'], 'refs/heads/release/7.0.3xx'), not(contains(parameters.agentOs, 'TemplateEngine'))) }}:
+- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.SourceBranch'], 'refs/heads/release/7.0.4xx'), not(contains(parameters.agentOs, 'TemplateEngine'))) }}:
- template: /eng/common/templates/job/onelocbuild.yml
parameters:
CreatePr: true
LclSource: lclFilesfromPackage
LclPackageId: 'LCL-JUNO-PROD-DOTNETSDK'
- MirrorBranch: release/7.0.3xx
+ MirrorBranch: release/7.0.4xx
MirrorRepo: sdk
- ${{ if not(contains(parameters.agentOs, 'TemplateEngine')) }}:
diff --git a/eng/common/cross/arm/sources.list.xenial b/eng/common/cross/arm/sources.list.xenial
index eacd86b7df3c..56fbb36a59f6 100644
--- a/eng/common/cross/arm/sources.list.xenial
+++ b/eng/common/cross/arm/sources.list.xenial
@@ -8,4 +8,4 @@ deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
\ No newline at end of file
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
diff --git a/eng/common/cross/arm64/sources.list.xenial b/eng/common/cross/arm64/sources.list.xenial
index eacd86b7df3c..56fbb36a59f6 100644
--- a/eng/common/cross/arm64/sources.list.xenial
+++ b/eng/common/cross/arm64/sources.list.xenial
@@ -8,4 +8,4 @@ deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
\ No newline at end of file
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh
index ffaa88eb0f06..79bb058ab02d 100755
--- a/eng/common/cross/build-rootfs.sh
+++ b/eng/common/cross/build-rootfs.sh
@@ -14,6 +14,7 @@ usage()
echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine and FreeBSD"
echo "llvmx[.y] - optional, LLVM version for LLVM related packages."
echo "--skipunmount - optional, will skip the unmount of rootfs folder."
+ echo "--skipsigcheck - optional, will skip package signature checks (allowing untrusted packages)."
echo "--use-mirror - optional, use mirror URL to fetch resources, when available."
echo "--jobs N - optional, restrict to N jobs."
exit 1
@@ -55,7 +56,7 @@ __AlpinePackages+=" gettext-dev"
__AlpinePackages+=" icu-dev"
__AlpinePackages+=" libunwind-dev"
__AlpinePackages+=" lttng-ust-dev"
-__AlpinePackages+=" compiler-rt-static"
+__AlpinePackages+=" compiler-rt"
__AlpinePackages+=" numactl-dev"
# runtime libraries' dependencies
@@ -69,7 +70,7 @@ __AlpinePackages+=" krb5-dev"
__AlpinePackages+=" openssl-dev"
__AlpinePackages+=" zlib-dev"
-__FreeBSDBase="12.3-RELEASE"
+__FreeBSDBase="12.4-RELEASE"
__FreeBSDPkg="1.17.0"
__FreeBSDABI="12"
__FreeBSDPackages="libunwind"
@@ -99,7 +100,27 @@ __HaikuPackages+=" mpfr_devel"
__UbuntuPackages+=" libomp5"
__UbuntuPackages+=" libomp-dev"
+# Taken from https://github.com/alpinelinux/alpine-chroot-install/blob/6d08f12a8a70dd9b9dc7d997c88aa7789cc03c42/alpine-chroot-install#L85-L133
+__AlpineKeys='
+4a6a0840:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1yHJxQgsHQREclQu4Ohe\nqxTxd1tHcNnvnQTu/UrTky8wWvgXT+jpveroeWWnzmsYlDI93eLI2ORakxb3gA2O\nQ0Ry4ws8vhaxLQGC74uQR5+/yYrLuTKydFzuPaS1dK19qJPXB8GMdmFOijnXX4SA\njixuHLe1WW7kZVtjL7nufvpXkWBGjsfrvskdNA/5MfxAeBbqPgaq0QMEfxMAn6/R\nL5kNepi/Vr4S39Xvf2DzWkTLEK8pcnjNkt9/aafhWqFVW7m3HCAII6h/qlQNQKSo\nGuH34Q8GsFG30izUENV9avY7hSLq7nggsvknlNBZtFUcmGoQrtx3FmyYsIC8/R+B\nywIDAQAB
+5243ef4b:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvNijDxJ8kloskKQpJdx+\nmTMVFFUGDoDCbulnhZMJoKNkSuZOzBoFC94omYPtxnIcBdWBGnrm6ncbKRlR+6oy\nDO0W7c44uHKCFGFqBhDasdI4RCYP+fcIX/lyMh6MLbOxqS22TwSLhCVjTyJeeH7K\naA7vqk+QSsF4TGbYzQDDpg7+6aAcNzg6InNePaywA6hbT0JXbxnDWsB+2/LLSF2G\nmnhJlJrWB1WGjkz23ONIWk85W4S0XB/ewDefd4Ly/zyIciastA7Zqnh7p3Ody6Q0\nsS2MJzo7p3os1smGjUF158s6m/JbVh4DN6YIsxwl2OjDOz9R0OycfJSDaBVIGZzg\ncQIDAQAB
+524d27bb:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr8s1q88XpuJWLCZALdKj\nlN8wg2ePB2T9aIcaxryYE/Jkmtu+ZQ5zKq6BT3y/udt5jAsMrhHTwroOjIsF9DeG\ne8Y3vjz+Hh4L8a7hZDaw8jy3CPag47L7nsZFwQOIo2Cl1SnzUc6/owoyjRU7ab0p\niWG5HK8IfiybRbZxnEbNAfT4R53hyI6z5FhyXGS2Ld8zCoU/R4E1P0CUuXKEN4p0\n64dyeUoOLXEWHjgKiU1mElIQj3k/IF02W89gDj285YgwqA49deLUM7QOd53QLnx+\nxrIrPv3A+eyXMFgexNwCKQU9ZdmWa00MjjHlegSGK8Y2NPnRoXhzqSP9T9i2HiXL\nVQIDAQAB
+5261cecb:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwlzMkl7b5PBdfMzGdCT0\ncGloRr5xGgVmsdq5EtJvFkFAiN8Ac9MCFy/vAFmS8/7ZaGOXoCDWbYVLTLOO2qtX\nyHRl+7fJVh2N6qrDDFPmdgCi8NaE+3rITWXGrrQ1spJ0B6HIzTDNEjRKnD4xyg4j\ng01FMcJTU6E+V2JBY45CKN9dWr1JDM/nei/Pf0byBJlMp/mSSfjodykmz4Oe13xB\nCa1WTwgFykKYthoLGYrmo+LKIGpMoeEbY1kuUe04UiDe47l6Oggwnl+8XD1MeRWY\nsWgj8sF4dTcSfCMavK4zHRFFQbGp/YFJ/Ww6U9lA3Vq0wyEI6MCMQnoSMFwrbgZw\nwwIDAQAB
+58199dcc:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3v8/ye/V/t5xf4JiXLXa\nhWFRozsnmn3hobON20GdmkrzKzO/eUqPOKTpg2GtvBhK30fu5oY5uN2ORiv2Y2ht\neLiZ9HVz3XP8Fm9frha60B7KNu66FO5P2o3i+E+DWTPqqPcCG6t4Znk2BypILcit\nwiPKTsgbBQR2qo/cO01eLLdt6oOzAaF94NH0656kvRewdo6HG4urbO46tCAizvCR\nCA7KGFMyad8WdKkTjxh8YLDLoOCtoZmXmQAiwfRe9pKXRH/XXGop8SYptLqyVVQ+\ntegOD9wRs2tOlgcLx4F/uMzHN7uoho6okBPiifRX+Pf38Vx+ozXh056tjmdZkCaV\naQIDAQAB
+58cbb476:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoSPnuAGKtRIS5fEgYPXD\n8pSGvKAmIv3A08LBViDUe+YwhilSHbYXUEAcSH1KZvOo1WT1x2FNEPBEFEFU1Eyc\n+qGzbA03UFgBNvArurHQ5Z/GngGqE7IarSQFSoqewYRtFSfp+TL9CUNBvM0rT7vz\n2eMu3/wWG+CBmb92lkmyWwC1WSWFKO3x8w+Br2IFWvAZqHRt8oiG5QtYvcZL6jym\nY8T6sgdDlj+Y+wWaLHs9Fc+7vBuyK9C4O1ORdMPW15qVSl4Lc2Wu1QVwRiKnmA+c\nDsH/m7kDNRHM7TjWnuj+nrBOKAHzYquiu5iB3Qmx+0gwnrSVf27Arc3ozUmmJbLj\nzQIDAQAB
+58e4f17d:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvBxJN9ErBgdRcPr5g4hV\nqyUSGZEKuvQliq2Z9SRHLh2J43+EdB6A+yzVvLnzcHVpBJ+BZ9RV30EM9guck9sh\nr+bryZcRHyjG2wiIEoduxF2a8KeWeQH7QlpwGhuobo1+gA8L0AGImiA6UP3LOirl\nI0G2+iaKZowME8/tydww4jx5vG132JCOScMjTalRsYZYJcjFbebQQolpqRaGB4iG\nWqhytWQGWuKiB1A22wjmIYf3t96l1Mp+FmM2URPxD1gk/BIBnX7ew+2gWppXOK9j\n1BJpo0/HaX5XoZ/uMqISAAtgHZAqq+g3IUPouxTphgYQRTRYpz2COw3NF43VYQrR\nbQIDAQAB
+60ac2099:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwR4uJVtJOnOFGchnMW5Y\nj5/waBdG1u5BTMlH+iQMcV5+VgWhmpZHJCBz3ocD+0IGk2I68S5TDOHec/GSC0lv\n6R9o6F7h429GmgPgVKQsc8mPTPtbjJMuLLs4xKc+viCplXc0Nc0ZoHmCH4da6fCV\ntdpHQjVe6F9zjdquZ4RjV6R6JTiN9v924dGMAkbW/xXmamtz51FzondKC52Gh8Mo\n/oA0/T0KsCMCi7tb4QNQUYrf+Xcha9uus4ww1kWNZyfXJB87a2kORLiWMfs2IBBJ\nTmZ2Fnk0JnHDb8Oknxd9PvJPT0mvyT8DA+KIAPqNvOjUXP4bnjEHJcoCP9S5HkGC\nIQIDAQAB
+6165ee59:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAutQkua2CAig4VFSJ7v54\nALyu/J1WB3oni7qwCZD3veURw7HxpNAj9hR+S5N/pNeZgubQvJWyaPuQDm7PTs1+\ntFGiYNfAsiibX6Rv0wci3M+z2XEVAeR9Vzg6v4qoofDyoTbovn2LztaNEjTkB+oK\ntlvpNhg1zhou0jDVYFniEXvzjckxswHVb8cT0OMTKHALyLPrPOJzVtM9C1ew2Nnc\n3848xLiApMu3NBk0JqfcS3Bo5Y2b1FRVBvdt+2gFoKZix1MnZdAEZ8xQzL/a0YS5\nHd0wj5+EEKHfOd3A75uPa/WQmA+o0cBFfrzm69QDcSJSwGpzWrD1ScH3AK8nWvoj\nv7e9gukK/9yl1b4fQQ00vttwJPSgm9EnfPHLAtgXkRloI27H6/PuLoNvSAMQwuCD\nhQRlyGLPBETKkHeodfLoULjhDi1K2gKJTMhtbnUcAA7nEphkMhPWkBpgFdrH+5z4\nLxy+3ek0cqcI7K68EtrffU8jtUj9LFTUC8dERaIBs7NgQ/LfDbDfGh9g6qVj1hZl\nk9aaIPTm/xsi8v3u+0qaq7KzIBc9s59JOoA8TlpOaYdVgSQhHHLBaahOuAigH+VI\nisbC9vmqsThF2QdDtQt37keuqoda2E6sL7PUvIyVXDRfwX7uMDjlzTxHTymvq2Ck\nhtBqojBnThmjJQFgZXocHG8CAwEAAQ==
+61666e3f:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlEyxkHggKCXC2Wf5Mzx4\nnZLFZvU2bgcA3exfNPO/g1YunKfQY+Jg4fr6tJUUTZ3XZUrhmLNWvpvSwDS19ZmC\nIXOu0+V94aNgnhMsk9rr59I8qcbsQGIBoHzuAl8NzZCgdbEXkiY90w1skUw8J57z\nqCsMBydAueMXuWqF5nGtYbi5vHwK42PffpiZ7G5Kjwn8nYMW5IZdL6ZnMEVJUWC9\nI4waeKg0yskczYDmZUEAtrn3laX9677ToCpiKrvmZYjlGl0BaGp3cxggP2xaDbUq\nqfFxWNgvUAb3pXD09JM6Mt6HSIJaFc9vQbrKB9KT515y763j5CC2KUsilszKi3mB\nHYe5PoebdjS7D1Oh+tRqfegU2IImzSwW3iwA7PJvefFuc/kNIijfS/gH/cAqAK6z\nbhdOtE/zc7TtqW2Wn5Y03jIZdtm12CxSxwgtCF1NPyEWyIxAQUX9ACb3M0FAZ61n\nfpPrvwTaIIxxZ01L3IzPLpbc44x/DhJIEU+iDt6IMTrHOphD9MCG4631eIdB0H1b\n6zbNX1CXTsafqHRFV9XmYYIeOMggmd90s3xIbEujA6HKNP/gwzO6CDJ+nHFDEqoF\nSkxRdTkEqjTjVKieURW7Swv7zpfu5PrsrrkyGnsRrBJJzXlm2FOOxnbI2iSL1B5F\nrO5kbUxFeZUIDq+7Yv4kLWcCAwEAAQ==
+616a9724:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnC+bR4bHf/L6QdU4puhQ\ngl1MHePszRC38bzvVFDUJsmCaMCL2suCs2A2yxAgGb9pu9AJYLAmxQC4mM3jNqhg\n/E7yuaBbek3O02zN/ctvflJ250wZCy+z0ZGIp1ak6pu1j14IwHokl9j36zNfGtfv\nADVOcdpWITFFlPqwq1qt/H3UsKVmtiF3BNWWTeUEQwKvlU8ymxgS99yn0+4OPyNT\nL3EUeS+NQJtDS01unau0t7LnjUXn+XIneWny8bIYOQCuVR6s/gpIGuhBaUqwaJOw\n7jkJZYF2Ij7uPb4b5/R3vX2FfxxqEHqssFSg8FFUNTZz3qNZs0CRVyfA972g9WkJ\nhPfn31pQYil4QGRibCMIeU27YAEjXoqfJKEPh4UWMQsQLrEfdGfb8VgwrPbniGfU\nL3jKJR3VAafL9330iawzVQDlIlwGl6u77gEXMl9K0pfazunYhAp+BMP+9ot5ckK+\nosmrqj11qMESsAj083GeFdfV3pXEIwUytaB0AKEht9DbqUfiE/oeZ/LAXgySMtVC\nsbC4ESmgVeY2xSBIJdDyUap7FR49GGrw0W49NUv9gRgQtGGaNVQQO9oGL2PBC41P\niWF9GLoX30HIz1P8PF/cZvicSSPkQf2Z6TV+t0ebdGNS5DjapdnCrq8m9Z0pyKsQ\nuxAL2a7zX8l5i1CZh1ycUGsCAwEAAQ==
+616abc23:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0MfCDrhODRCIxR9Dep1s\neXafh5CE5BrF4WbCgCsevyPIdvTeyIaW4vmO3bbG4VzhogDZju+R3IQYFuhoXP5v\nY+zYJGnwrgz3r5wYAvPnLEs1+dtDKYOgJXQj+wLJBW1mzRDL8FoRXOe5iRmn1EFS\nwZ1DoUvyu7/J5r0itKicZp3QKED6YoilXed+1vnS4Sk0mzN4smuMR9eO1mMCqNp9\n9KTfRDHTbakIHwasECCXCp50uXdoW6ig/xUAFanpm9LtK6jctNDbXDhQmgvAaLXZ\nLvFqoaYJ/CvWkyYCgL6qxvMvVmPoRv7OPcyni4xR/WgWa0MSaEWjgPx3+yj9fiMA\n1S02pFWFDOr5OUF/O4YhFJvUCOtVsUPPfA/Lj6faL0h5QI9mQhy5Zb9TTaS9jB6p\nLw7u0dJlrjFedk8KTJdFCcaGYHP6kNPnOxMylcB/5WcztXZVQD5WpCicGNBxCGMm\nW64SgrV7M07gQfL/32QLsdqPUf0i8hoVD8wfQ3EpbQzv6Fk1Cn90bZqZafg8XWGY\nwddhkXk7egrr23Djv37V2okjzdqoyLBYBxMz63qQzFoAVv5VoY2NDTbXYUYytOvG\nGJ1afYDRVWrExCech1mX5ZVUB1br6WM+psFLJFoBFl6mDmiYt0vMYBddKISsvwLl\nIJQkzDwtXzT2cSjoj3T5QekCAwEAAQ==
+616ac3bc:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvaaoSLab+IluixwKV5Od\n0gib2YurjPatGIbn5Ov2DLUFYiebj2oJINXJSwUOO+4WcuHFEqiL/1rya+k5hLZt\nhnPL1tn6QD4rESznvGSasRCQNT2vS/oyZbTYJRyAtFkEYLlq0t3S3xBxxHWuvIf0\nqVxVNYpQWyM3N9RIeYBR/euXKJXileSHk/uq1I5wTC0XBIHWcthczGN0m9wBEiWS\n0m3cnPk4q0Ea8mUJ91Rqob19qETz6VbSPYYpZk3qOycjKosuwcuzoMpwU8KRiMFd\n5LHtX0Hx85ghGsWDVtS0c0+aJa4lOMGvJCAOvDfqvODv7gKlCXUpgumGpLdTmaZ8\n1RwqspAe3IqBcdKTqRD4m2mSg23nVx2FAY3cjFvZQtfooT7q1ItRV5RgH6FhQSl7\n+6YIMJ1Bf8AAlLdRLpg+doOUGcEn+pkDiHFgI8ylH1LKyFKw+eXaAml/7DaWZk1d\ndqggwhXOhc/UUZFQuQQ8A8zpA13PcbC05XxN2hyP93tCEtyynMLVPtrRwDnHxFKa\nqKzs3rMDXPSXRn3ZZTdKH3069ApkEjQdpcwUh+EmJ1Ve/5cdtzT6kKWCjKBFZP/s\n91MlRrX2BTRdHaU5QJkUheUtakwxuHrdah2F94lRmsnQlpPr2YseJu6sIE+Dnx4M\nCfhdVbQL2w54R645nlnohu8CAwEAAQ==
+616adfeb:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq0BFD1D4lIxQcsqEpQzU\npNCYM3aP1V/fxxVdT4DWvSI53JHTwHQamKdMWtEXetWVbP5zSROniYKFXd/xrD9X\n0jiGHey3lEtylXRIPxe5s+wXoCmNLcJVnvTcDtwx/ne2NLHxp76lyc25At+6RgE6\nADjLVuoD7M4IFDkAsd8UQ8zM0Dww9SylIk/wgV3ZkifecvgUQRagrNUdUjR56EBZ\nraQrev4hhzOgwelT0kXCu3snbUuNY/lU53CoTzfBJ5UfEJ5pMw1ij6X0r5S9IVsy\nKLWH1hiO0NzU2c8ViUYCly4Fe9xMTFc6u2dy/dxf6FwERfGzETQxqZvSfrRX+GLj\n/QZAXiPg5178hT/m0Y3z5IGenIC/80Z9NCi+byF1WuJlzKjDcF/TU72zk0+PNM/H\nKuppf3JT4DyjiVzNC5YoWJT2QRMS9KLP5iKCSThwVceEEg5HfhQBRT9M6KIcFLSs\nmFjx9kNEEmc1E8hl5IR3+3Ry8G5/bTIIruz14jgeY9u5jhL8Vyyvo41jgt9sLHR1\n/J1TxKfkgksYev7PoX6/ZzJ1ksWKZY5NFoDXTNYUgzFUTOoEaOg3BAQKadb3Qbbq\nXIrxmPBdgrn9QI7NCgfnAY3Tb4EEjs3ON/BNyEhUENcXOH6I1NbcuBQ7g9P73kE4\nVORdoc8MdJ5eoKBpO8Ww8HECAwEAAQ==
+616ae350:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyduVzi1mWm+lYo2Tqt/0\nXkCIWrDNP1QBMVPrE0/ZlU2bCGSoo2Z9FHQKz/mTyMRlhNqTfhJ5qU3U9XlyGOPJ\npiM+b91g26pnpXJ2Q2kOypSgOMOPA4cQ42PkHBEqhuzssfj9t7x47ppS94bboh46\nxLSDRff/NAbtwTpvhStV3URYkxFG++cKGGa5MPXBrxIp+iZf9GnuxVdST5PGiVGP\nODL/b69sPJQNbJHVquqUTOh5Ry8uuD2WZuXfKf7/C0jC/ie9m2+0CttNu9tMciGM\nEyKG1/Xhk5iIWO43m4SrrT2WkFlcZ1z2JSf9Pjm4C2+HovYpihwwdM/OdP8Xmsnr\nDzVB4YvQiW+IHBjStHVuyiZWc+JsgEPJzisNY0Wyc/kNyNtqVKpX6dRhMLanLmy+\nf53cCSI05KPQAcGj6tdL+D60uKDkt+FsDa0BTAobZ31OsFVid0vCXtsbplNhW1IF\nHwsGXBTVcfXg44RLyL8Lk/2dQxDHNHzAUslJXzPxaHBLmt++2COa2EI1iWlvtznk\nOk9WP8SOAIj+xdqoiHcC4j72BOVVgiITIJNHrbppZCq6qPR+fgXmXa+sDcGh30m6\n9Wpbr28kLMSHiENCWTdsFij+NQTd5S47H7XTROHnalYDuF1RpS+DpQidT5tUimaT\nJZDr++FjKrnnijbyNF8b98UCAwEAAQ==
+616db30d:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnpUpyWDWjlUk3smlWeA0\nlIMW+oJ38t92CRLHH3IqRhyECBRW0d0aRGtq7TY8PmxjjvBZrxTNDpJT6KUk4LRm\na6A6IuAI7QnNK8SJqM0DLzlpygd7GJf8ZL9SoHSH+gFsYF67Cpooz/YDqWrlN7Vw\ntO00s0B+eXy+PCXYU7VSfuWFGK8TGEv6HfGMALLjhqMManyvfp8hz3ubN1rK3c8C\nUS/ilRh1qckdbtPvoDPhSbTDmfU1g/EfRSIEXBrIMLg9ka/XB9PvWRrekrppnQzP\nhP9YE3x/wbFc5QqQWiRCYyQl/rgIMOXvIxhkfe8H5n1Et4VAorkpEAXdsfN8KSVv\nLSMazVlLp9GYq5SUpqYX3KnxdWBgN7BJoZ4sltsTpHQ/34SXWfu3UmyUveWj7wp0\nx9hwsPirVI00EEea9AbP7NM2rAyu6ukcm4m6ATd2DZJIViq2es6m60AE6SMCmrQF\nwmk4H/kdQgeAELVfGOm2VyJ3z69fQuywz7xu27S6zTKi05Qlnohxol4wVb6OB7qG\nLPRtK9ObgzRo/OPumyXqlzAi/Yvyd1ZQk8labZps3e16bQp8+pVPiumWioMFJDWV\nGZjCmyMSU8V6MB6njbgLHoyg2LCukCAeSjbPGGGYhnKLm1AKSoJh3IpZuqcKCk5C\n8CM1S15HxV78s9dFntEqIokCAwEAAQ==
+'
__Keyring=
+__SkipSigCheck=0
__UseMirror=0
__UnprocessedBuildArgs=
@@ -150,7 +171,6 @@ while :; do
__BuildArch=riscv64
__AlpineArch=riscv64
__AlpinePackages="${__AlpinePackages// lldb-dev/}"
- __AlpinePackages="${__AlpinePackages// compiler-rt-static/}"
__QEMUArch=riscv64
__UbuntuArch=riscv64
__UbuntuRepo="http://deb.debian.org/debian-ports"
@@ -160,10 +180,6 @@ while :; do
if [[ -e "/usr/share/keyrings/debian-ports-archive-keyring.gpg" ]]; then
__Keyring="--keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg --include=debian-ports-archive-keyring"
fi
-
- if [[ "$version" != "edge" && ( -z "$__AlpineVersion" || -z "$__AlpineMajorVersion" )]]; then
- __AlpineVersion=edge # minimum version with APKINDEX.tar.gz (packages archive)
- fi
;;
ppc64le)
__BuildArch=ppc64le
@@ -175,10 +191,6 @@ while :; do
__UbuntuPackages="${__UbuntuPackages// libomp-dev/}"
__UbuntuPackages="${__UbuntuPackages// libomp5/}"
unset __LLDB_Package
-
- if [[ "$version" != "edge" && ( -z "$__AlpineVersion" || -z "$__AlpineMajorVersion" )]]; then
- __AlpineVersion=3.15 # minimum version that supports compiler-rt
- fi
;;
s390x)
__BuildArch=s390x
@@ -190,22 +202,20 @@ while :; do
__UbuntuPackages="${__UbuntuPackages// libomp-dev/}"
__UbuntuPackages="${__UbuntuPackages// libomp5/}"
unset __LLDB_Package
-
- if [[ "$version" != "edge" && ( -z "$__AlpineVersion" || -z "$__AlpineMajorVersion" )]]; then
- __AlpineVersion=3.15 # minimum version that supports compiler-rt
- fi
;;
x64)
__BuildArch=x64
+ __AlpineArch=x86_64
__UbuntuArch=amd64
__FreeBSDArch=amd64
__FreeBSDMachineArch=amd64
__illumosArch=x86_64
- __UbuntuRepo=
+ __UbuntuRepo="http://archive.ubuntu.com/ubuntu/"
;;
x86)
__BuildArch=x86
__UbuntuArch=i386
+ __AlpineArch=x86
__UbuntuRepo="http://archive.ubuntu.com/ubuntu/"
;;
lldb*)
@@ -260,25 +270,40 @@ while :; do
;;
jessie) # Debian 8
__CodeName=jessie
- __UbuntuRepo="http://ftp.debian.org/debian/"
+
+ if [[ -z "$__UbuntuRepo" ]]; then
+ __UbuntuRepo="http://ftp.debian.org/debian/"
+ fi
;;
stretch) # Debian 9
__CodeName=stretch
- __UbuntuRepo="http://ftp.debian.org/debian/"
__LLDB_Package="liblldb-6.0-dev"
+
+ if [[ -z "$__UbuntuRepo" ]]; then
+ __UbuntuRepo="http://ftp.debian.org/debian/"
+ fi
;;
buster) # Debian 10
__CodeName=buster
- __UbuntuRepo="http://ftp.debian.org/debian/"
__LLDB_Package="liblldb-6.0-dev"
+
+ if [[ -z "$__UbuntuRepo" ]]; then
+ __UbuntuRepo="http://ftp.debian.org/debian/"
+ fi
;;
bullseye) # Debian 11
__CodeName=bullseye
- __UbuntuRepo="http://ftp.debian.org/debian/"
+
+ if [[ -z "$__UbuntuRepo" ]]; then
+ __UbuntuRepo="http://ftp.debian.org/debian/"
+ fi
;;
sid) # Debian sid
__CodeName=sid
- __UbuntuRepo="http://ftp.debian.org/debian/"
+
+ if [[ -z "$__UbuntuRepo" ]]; then
+ __UbuntuRepo="http://ftp.debian.org/debian/"
+ fi
;;
tizen)
__CodeName=
@@ -296,29 +321,8 @@ while :; do
parts=(${version//./ })
__AlpineMajorVersion="${parts[0]}"
__AlpineMinoVersion="${parts[1]}"
-
- if [[ -z "$__AlpineVersion" ]]; then
- __AlpineVersion="$__AlpineMajorVersion.$__AlpineMinoVersion"
- fi
+ __AlpineVersion="$__AlpineMajorVersion.$__AlpineMinoVersion"
fi
-
- case "$__AlpineVersion" in
- 3.14) __AlpinePackages+=" llvm11-libs" ;;
- 3.15) __AlpinePackages+=" llvm12-libs" ;;
- 3.16) __AlpinePackages+=" llvm13-libs" ;;
- 3.17) __AlpinePackages+=" llvm15-libs" ;;
- edge) __AlpineLlvmLibsLookup=1 ;;
- *)
- if [[ "$__AlpineArch" =~ "s390x|ppc64le" ]]; then
- __AlpineVersion=3.15 # minimum version that supports compiler-rt
- __AlpinePackages+=" llvm12-libs"
- elif [[ "$__AlpineArch" == "riscv64" ]]; then
- __AlpineLlvmLibsLookup=1
- __AlpineVersion=edge # minimum version with APKINDEX.tar.gz (packages archive)
- else
- __AlpineVersion=3.13 # 3.13 to maximize compatibility
- fi
- esac
;;
freebsd12)
__CodeName=freebsd
@@ -342,6 +346,9 @@ while :; do
--skipunmount)
__SkipUnmount=1
;;
+ --skipsigcheck)
+ __SkipSigCheck=1
+ ;;
--rootfsdir|-rootfsdir)
shift
__RootfsDir="$1"
@@ -361,10 +368,45 @@ while :; do
shift
done
+case "$__AlpineVersion" in
+ 3.14) __AlpinePackages+=" llvm11-libs" ;;
+ 3.15) __AlpinePackages+=" llvm12-libs" ;;
+ 3.16) __AlpinePackages+=" llvm13-libs" ;;
+ 3.17) __AlpinePackages+=" llvm15-libs" ;;
+ edge) __AlpineLlvmLibsLookup=1 ;;
+ *)
+ if [[ "$__AlpineArch" =~ s390x|ppc64le ]]; then
+ __AlpineVersion=3.15 # minimum version that supports lldb-dev
+ __AlpinePackages+=" llvm12-libs"
+ elif [[ "$__AlpineArch" == "x86" ]]; then
+ __AlpineVersion=3.17 # minimum version that supports lldb-dev
+ __AlpinePackages+=" llvm15-libs"
+ elif [[ "$__AlpineArch" == "riscv64" ]]; then
+ __AlpineLlvmLibsLookup=1
+ __AlpineVersion=edge # minimum version with APKINDEX.tar.gz (packages archive)
+ else
+ __AlpineVersion=3.13 # 3.13 to maximize compatibility
+ __AlpinePackages+=" llvm10-libs"
+
+ if [[ "$__AlpineArch" == "armv7" ]]; then
+ __AlpinePackages="${__AlpinePackages//numactl-dev/}"
+ fi
+ fi
+esac
+
+if [[ "$__AlpineVersion" =~ 3\.1[345] ]]; then
+ # compiler-rt--static was merged in compiler-rt package in alpine 3.16
+ # for older versions, we need compiler-rt--static, so replace the name
+ __AlpinePackages="${__AlpinePackages/compiler-rt/compiler-rt-static}"
+fi
+
if [[ "$__BuildArch" == "armel" ]]; then
__LLDB_Package="lldb-3.5-dev"
-elif [[ "$__BuildArch" == "arm" && "$__AlpineVersion" == "3.13" ]]; then
- __AlpinePackages="${__AlpinePackages//numactl-dev/}"
+fi
+
+if [[ "$__CodeName" == "xenial" && "$__UbuntuArch" == "armhf" ]]; then
+ # libnuma-dev is not available on armhf for xenial
+ __UbuntuPackages="${__UbuntuPackages//libnuma-dev/}"
fi
__UbuntuPackages+=" ${__LLDB_Package:-}"
@@ -393,13 +435,18 @@ __RootfsDir="$( cd "$__RootfsDir" && pwd )"
if [[ "$__CodeName" == "alpine" ]]; then
__ApkToolsVersion=2.12.11
+ __ApkToolsSHA512SUM=53e57b49230da07ef44ee0765b9592580308c407a8d4da7125550957bb72cb59638e04f8892a18b584451c8d841d1c7cb0f0ab680cc323a3015776affaa3be33
__ApkToolsDir="$(mktemp -d)"
+ __ApkKeysDir="$(mktemp -d)"
wget "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic//v$__ApkToolsVersion/x86_64/apk.static" -P "$__ApkToolsDir"
+ echo "$__ApkToolsSHA512SUM $__ApkToolsDir/apk.static" | sha512sum -c
chmod +x "$__ApkToolsDir/apk.static"
- mkdir -p "$__RootfsDir"/usr/bin
- cp -v "/usr/bin/qemu-$__QEMUArch-static" "$__RootfsDir/usr/bin"
+ if [[ -f "/usr/bin/qemu-$__QEMUArch-static" ]]; then
+ mkdir -p "$__RootfsDir"/usr/bin
+ cp -v "/usr/bin/qemu-$__QEMUArch-static" "$__RootfsDir/usr/bin"
+ fi
if [[ "$__AlpineVersion" == "edge" ]]; then
version=edge
@@ -407,26 +454,40 @@ if [[ "$__CodeName" == "alpine" ]]; then
version="v$__AlpineVersion"
fi
+ for line in $__AlpineKeys; do
+ id="${line%%:*}"
+ content="${line#*:}"
+
+ echo -e "-----BEGIN PUBLIC KEY-----\n$content\n-----END PUBLIC KEY-----" > "$__ApkKeysDir/alpine-devel@lists.alpinelinux.org-$id.rsa.pub"
+ done
+
+ if [[ "$__SkipSigCheck" == "1" ]]; then
+ __ApkSignatureArg="--allow-untrusted"
+ else
+ __ApkSignatureArg="--keys-dir $__ApkKeysDir"
+ fi
+
+ # initialize DB
"$__ApkToolsDir/apk.static" \
-X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \
-X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \
- -U --allow-untrusted --root "$__RootfsDir" --arch "$__AlpineArch" --initdb \
- add $__AlpinePackages
+ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" --initdb add
if [[ "$__AlpineLlvmLibsLookup" == 1 ]]; then
- "$__ApkToolsDir/apk.static" \
+ __AlpinePackages+=" $("$__ApkToolsDir/apk.static" \
-X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \
-X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \
- -U --allow-untrusted --root "$__RootfsDir" --arch "$__AlpineArch" \
- search 'llvm*-libs' | sort | tail -1 | while IFS=- read name rest; do
- "$__ApkToolsDir/apk.static" \
- -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \
- -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \
- -U --allow-untrusted --root "$__RootfsDir" --arch "$__AlpineArch" \
- add "$name-libs"
- done
+ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" \
+ search 'llvm*-libs' | sort | tail -1 | sed 's/-[^-]*//2g')"
fi
+ # install all packages in one go
+ "$__ApkToolsDir/apk.static" \
+ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \
+ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \
+ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" \
+ add $__AlpinePackages
+
rm -r "$__ApkToolsDir"
elif [[ "$__CodeName" == "freebsd" ]]; then
mkdir -p "$__RootfsDir"/usr/local/etc
@@ -560,7 +621,12 @@ elif [[ "$__CodeName" == "haiku" ]]; then
fi
done
elif [[ -n "$__CodeName" ]]; then
- qemu-debootstrap $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo"
+
+ if [[ "$__SkipSigCheck" == "0" ]]; then
+ __Keyring="$__Keyring --force-check-gpg"
+ fi
+
+ debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo"
cp "$__CrossDir/$__BuildArch/sources.list.$__CodeName" "$__RootfsDir/etc/apt/sources.list"
chroot "$__RootfsDir" apt-get update
chroot "$__RootfsDir" apt-get -f -y install
diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake
index ccfb9951a52c..1c9d212d1359 100644
--- a/eng/common/cross/toolchain.cmake
+++ b/eng/common/cross/toolchain.cmake
@@ -76,7 +76,9 @@ elseif(TARGET_ARCH_NAME STREQUAL "s390x")
set(TOOLCHAIN "s390x-linux-gnu")
elseif(TARGET_ARCH_NAME STREQUAL "x64")
set(CMAKE_SYSTEM_PROCESSOR x86_64)
- if(LINUX)
+ if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/x86_64-alpine-linux-musl)
+ set(TOOLCHAIN "x86_64-alpine-linux-musl")
+ elseif(LINUX)
set(TOOLCHAIN "x86_64-linux-gnu")
if(TIZEN)
set(TIZEN_TOOLCHAIN "x86_64-tizen-linux-gnu/9.2.0")
@@ -279,7 +281,7 @@ endif()
# Specify compile options
-if((TARGET_ARCH_NAME MATCHES "^(arm|arm64|armel|armv6|ppc64le|riscv64|s390x)$" AND NOT ANDROID AND NOT FREEBSD) OR ILLUMOS OR HAIKU)
+if((TARGET_ARCH_NAME MATCHES "^(arm|arm64|armel|armv6|ppc64le|riscv64|s390x|x64|x86)$" AND NOT ANDROID AND NOT FREEBSD) OR ILLUMOS OR HAIKU)
set(CMAKE_C_COMPILER_TARGET ${TOOLCHAIN})
set(CMAKE_CXX_COMPILER_TARGET ${TOOLCHAIN})
set(CMAKE_ASM_COMPILER_TARGET ${TOOLCHAIN})
@@ -298,6 +300,9 @@ if(TARGET_ARCH_NAME MATCHES "^(arm|armel)$")
add_definitions (-DCLR_ARM_FPU_CAPABILITY=${CLR_ARM_FPU_CAPABILITY})
+ # persist variables across multiple try_compile passes
+ list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CLR_ARM_FPU_TYPE CLR_ARM_FPU_CAPABILITY)
+
if(TARGET_ARCH_NAME STREQUAL "armel")
add_compile_options(-mfloat-abi=softfp)
endif()
diff --git a/eng/common/cross/x64/sources.list.xenial b/eng/common/cross/x64/sources.list.xenial
new file mode 100644
index 000000000000..ad9c5a0144ef
--- /dev/null
+++ b/eng/common/cross/x64/sources.list.xenial
@@ -0,0 +1,11 @@
+deb http://archive.ubuntu.com/ubuntu/ xenial main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted
+deb-src http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted
+
+deb http://archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse
+deb-src http://archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse
diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml
index 61914a1fbcd3..a21533fdd31d 100644
--- a/eng/common/templates/job/job.yml
+++ b/eng/common/templates/job/job.yml
@@ -25,7 +25,7 @@ parameters:
enablePublishTestResults: false
enablePublishUsingPipelines: false
enableBuildRetry: false
- disableComponentGovernance: false
+ disableComponentGovernance: ''
componentGovernanceIgnoreDirectories: ''
mergeTestResults: false
testRunTitle: ''
@@ -101,7 +101,7 @@ jobs:
# handle key-value variable syntax.
# example:
# - [key]: [value]
- - ${{ if and(eq(variable.name, ''), eq(variable.group, '')) }}:
+ - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}:
- ${{ each pair in variable }}:
- name: ${{ pair.key }}
value: ${{ pair.value }}
@@ -155,11 +155,14 @@ jobs:
uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }}
continueOnError: true
- - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), ne(parameters.disableComponentGovernance, 'true')) }}:
- - task: ComponentGovernanceComponentDetection@0
- continueOnError: true
- inputs:
- ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
+ - template: /eng/common/templates/steps/component-governance.yml
+ parameters:
+ ${{ if eq(parameters.disableComponentGovernance, '') }}:
+ ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(contains(variables['Build.SourceBranch'], 'internal/release'), eq(variables['Build.SourceBranch'], 'main'))) }}:
+ disableComponentGovernance: false
+ ${{ else }}:
+ disableComponentGovernance: true
+ componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
- ${{ if eq(parameters.enableMicrobuild, 'true') }}:
- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml
index 71b66aeb8a5c..b98202aa02d8 100644
--- a/eng/common/templates/job/source-index-stage1.yml
+++ b/eng/common/templates/job/source-index-stage1.yml
@@ -1,6 +1,6 @@
parameters:
runAsPublic: false
- sourceIndexPackageVersion: 1.0.1-20221220.2
+ sourceIndexPackageVersion: 1.0.1-20230228.2
sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json
sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci"
preSteps: []
diff --git a/eng/common/templates/steps/component-governance.yml b/eng/common/templates/steps/component-governance.yml
new file mode 100644
index 000000000000..0ecec47b0c91
--- /dev/null
+++ b/eng/common/templates/steps/component-governance.yml
@@ -0,0 +1,13 @@
+parameters:
+ disableComponentGovernance: false
+ componentGovernanceIgnoreDirectories: ''
+
+steps:
+- ${{ if eq(parameters.disableComponentGovernance, 'true') }}:
+ - script: "echo ##vso[task.setvariable variable=skipComponentGovernanceDetection]true"
+ displayName: Set skipComponentGovernanceDetection variable
+- ${{ if ne(parameters.disableComponentGovernance, 'true') }}:
+ - task: ComponentGovernanceComponentDetection@0
+ continueOnError: true
+ inputs:
+ ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
\ No newline at end of file
diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1
index 7caacc6de2e1..8ad03be3eccb 100644
--- a/eng/common/tools.ps1
+++ b/eng/common/tools.ps1
@@ -913,11 +913,13 @@ if (!$disableConfigureToolsetImport) {
function Enable-Nuget-EnhancedRetry() {
if ($ci) {
Write-Host "Setting NUGET enhanced retry environment variables"
- $env:NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY = 'true'
- $env:NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT = 6
- $env:NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS = 1000
- Write-PipelineSetVariable -Name 'NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY' -Value 'true'
- Write-PipelineSetVariable -Name 'NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT' -Value '6'
- Write-PipelineSetVariable -Name 'NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS' -Value '1000'
+ $env:NUGET_ENABLE_ENHANCED_HTTP_RETRY = 'true'
+ $env:NUGET_ENHANCED_MAX_NETWORK_TRY_COUNT = 6
+ $env:NUGET_ENHANCED_NETWORK_RETRY_DELAY_MILLISECONDS = 1000
+ $env:NUGET_RETRY_HTTP_429 = 'true'
+ Write-PipelineSetVariable -Name 'NUGET_ENABLE_ENHANCED_HTTP_RETRY' -Value 'true'
+ Write-PipelineSetVariable -Name 'NUGET_ENHANCED_MAX_NETWORK_TRY_COUNT' -Value '6'
+ Write-PipelineSetVariable -Name 'NUGET_ENHANCED_NETWORK_RETRY_DELAY_MILLISECONDS' -Value '1000'
+ Write-PipelineSetVariable -Name 'NUGET_RETRY_HTTP_429' -Value 'true'
}
}
diff --git a/eng/dependabot/Packages.props b/eng/dependabot/Packages.props
index 5a10edc44671..534f3b8b7d05 100644
--- a/eng/dependabot/Packages.props
+++ b/eng/dependabot/Packages.props
@@ -4,7 +4,7 @@
-
+
diff --git a/eng/dogfood.ps1 b/eng/dogfood.ps1
index 95e6ba8b68ca..652004201557 100644
--- a/eng/dogfood.ps1
+++ b/eng/dogfood.ps1
@@ -39,7 +39,7 @@ try {
$TestDotnetRoot = Join-Path $ArtifactsDir "bin\redist\$configuration\dotnet"
- $testDotnetVersion = (Get-Childitem -Directory "$TestDotnetRoot\sdk")[0]
+ $testDotnetVersion = (Get-Childitem -Directory "$TestDotnetRoot\sdk")[-1]
$env:DOTNET_MSBUILD_SDK_RESOLVER_SDKS_DIR = Join-Path $TestDotnetRoot "sdk\$testDotnetVersion\Sdks"
$env:MicrosoftNETBuildExtensionsTargets = Join-Path $ArtifactsDir "bin\$configuration\Sdks\Microsoft.NET.Build.Extensions\msbuildExtensions\Microsoft\Microsoft.NET.Build.Extensions\Microsoft.NET.Build.Extensions.targets"
diff --git a/global.json b/global.json
index 3c209918bf48..cad758012451 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"tools": {
- "dotnet": "8.0.100-alpha.1.23067.5",
+ "dotnet": "8.0.100-preview.4.23221.6",
"runtimes": {
"dotnet": [
"$(VSRedistCommonNetCoreSharedFrameworkx6480PackageVersion)"
@@ -11,7 +11,7 @@
}
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23120.1",
- "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23120.1"
+ "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23224.1",
+ "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23224.1"
}
}
diff --git a/sdk.sln b/sdk.sln
index 153f535b4b1a..b3a51e4e38da 100644
--- a/sdk.sln
+++ b/sdk.sln
@@ -308,7 +308,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk (2)", "Sdk (2)", "{4ACCAC39-8ECD-45F8-B5AF-EB7E37CD36CC}"
ProjectSection(SolutionItems) = preProject
src\RazorSdk\Sdk\Sdk.props = src\RazorSdk\Sdk\Sdk.props
- src\RazorSdk\Sdk\Sdk.Razor.StaticAssets.ProjectSystem.props = src\RazorSdk\Sdk\Sdk.Razor.StaticAssets.ProjectSystem.props
src\RazorSdk\Sdk\Sdk.targets = src\RazorSdk\Sdk\Sdk.targets
EndProjectSection
EndProject
@@ -322,8 +321,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets (2)", "Targets (2)"
src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.GenerateAssemblyInfo.targets = src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.GenerateAssemblyInfo.targets
src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.MvcApplicationPartsDiscovery.targets = src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.MvcApplicationPartsDiscovery.targets
src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.props = src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.props
- src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.ScopedCss.targets = src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.ScopedCss.targets
- src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.StaticWebAssets.targets = src\RazorSdk\Targets\Microsoft.NET.Sdk.Razor.StaticWebAssets.targets
src\RazorSdk\Targets\Sdk.Razor.CurrentVersion.props = src\RazorSdk\Targets\Sdk.Razor.CurrentVersion.props
src\RazorSdk\Targets\Sdk.Razor.CurrentVersion.targets = src\RazorSdk\Targets\Sdk.Razor.CurrentVersion.targets
EndProjectSection
@@ -413,6 +410,66 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.GenAPI.Tas
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.Web.Tests", "src\Tests\Microsoft.NET.Sdk.Web.Tests\Microsoft.NET.Sdk.Web.Tests.csproj", "{B8A61A5C-A9A4-45C5-97E3-CB368358682F}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StaticWebAssetsSdk", "StaticWebAssetsSdk", "{9E9F3BB2-6FED-47BC-869C-BFAF6E7C85FC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{CA976F33-7BFA-4F56-8F86-AE132B3B4CBE}"
+ ProjectSection(SolutionItems) = preProject
+ src\StaticWebAssetsSdk\Sdk\Sdk.props = src\StaticWebAssetsSdk\Sdk\Sdk.props
+ src\StaticWebAssetsSdk\Sdk\Sdk.StaticWebAssets.StaticAssets.ProjectSystem.props = src\StaticWebAssetsSdk\Sdk\Sdk.StaticWebAssets.StaticAssets.ProjectSystem.props
+ src\StaticWebAssetsSdk\Sdk\Sdk.targets = src\StaticWebAssetsSdk\Sdk\Sdk.targets
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{C5C73211-A713-40BF-8FC8-A690CCBE66F5}"
+ ProjectSection(SolutionItems) = preProject
+ src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.5_0.targets = src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.5_0.targets
+ src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets = src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets
+ src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.Pack.CrossTargeting.targets = src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.Pack.CrossTargeting.targets
+ src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.Pack.targets = src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.Pack.targets
+ src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.props = src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.props
+ src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.ScopedCss.5_0.targets = src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.ScopedCss.5_0.targets
+ src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.ScopedCss.targets = src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.ScopedCss.targets
+ src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.targets = src\StaticWebAssetsSdk\Targets\Microsoft.NET.Sdk.StaticWebAssets.targets
+ src\StaticWebAssetsSdk\Targets\Sdk.StaticWebAssets.CurrentVersion.props = src\StaticWebAssetsSdk\Targets\Sdk.StaticWebAssets.CurrentVersion.props
+ src\StaticWebAssetsSdk\Targets\Sdk.StaticWebAssets.CurrentVersion.targets = src\StaticWebAssetsSdk\Targets\Sdk.StaticWebAssets.CurrentVersion.targets
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tasks", "Tasks", "{6C8E1E65-EA73-434D-818F-E564BFFE9F86}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.StaticWebAssets.Tasks", "src\StaticWebAssetsSdk\Tasks\Microsoft.NET.Sdk.StaticWebAssets.Tasks.csproj", "{3D42A6BA-38DB-4AA5-9F86-8A78D00D9A07}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tool", "Tool", "{51A31407-7C6A-42E9-93B8-F21DEC518A34}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.StaticWebAssets.Tool", "src\StaticWebAssetsSdk\Tool\Microsoft.NET.Sdk.StaticWebAssets.Tool.csproj", "{B8550E71-0CBE-4F88-AC79-2003EFED1DE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WasmSdk", "WasmSdk", "{21835A9E-D667-4761-8675-B2BC105CC2FE}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{71BC1256-D225-4272-ADB2-95264E09AF73}"
+ ProjectSection(SolutionItems) = preProject
+ src\WasmSdk\Targets\Microsoft.NET.Sdk.WebAssembly.Current.props = src\WasmSdk\Targets\Microsoft.NET.Sdk.WebAssembly.Current.props
+ src\WasmSdk\Targets\Microsoft.NET.Sdk.WebAssembly.Current.targets = src\WasmSdk\Targets\Microsoft.NET.Sdk.WebAssembly.Current.targets
+ src\WasmSdk\Targets\Wasm.web.config = src\WasmSdk\Targets\Wasm.web.config
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{B2CE3F28-8FEC-4715-B483-5B442E3136CE}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tasks", "Tasks", "{F720D695-F35A-4700-9463-C359163D14EE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.WebAssembly.Tasks", "src\WasmSdk\Tasks\Microsoft.NET.Sdk.WebAssembly.Tasks.csproj", "{754C18B9-AEDB-4455-BAF4-844C6CEEF8F7}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Containers", "Containers", "{EC4A66C5-E2E2-4201-9E8D-BAC6B630D12A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "containerize", "src\Containers\containerize\containerize.csproj", "{ECCDB04A-A365-4656-989D-4E258D286AE4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Build.Containers", "src\Containers\Microsoft.NET.Build.Containers\Microsoft.NET.Build.Containers.csproj", "{9E8C7C3B-B8B3-490C-BA11-E1F60ED4E21D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "package", "src\Containers\packaging\package.csproj", "{DEA8FE40-0AE9-4CE6-9430-089C985217CA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "containerize.UnitTests", "src\Tests\containerize.UnitTests\containerize.UnitTests.csproj", "{F04DB812-7278-47F2-913E-225CE2EF150C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Build.Containers.IntegrationTests", "src\Tests\Microsoft.NET.Build.Containers.IntegrationTests\Microsoft.NET.Build.Containers.IntegrationTests.csproj", "{7DCA2BEC-B1E1-4F2B-952A-A26B5110FDA5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Build.Containers.UnitTests", "src\Tests\Microsoft.NET.Build.Containers.UnitTests\Microsoft.NET.Build.Containers.UnitTests.csproj", "{E54506B8-0B81-4FC4-99B5-5C67E19D4B09}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -799,6 +856,42 @@ Global
{B8A61A5C-A9A4-45C5-97E3-CB368358682F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8A61A5C-A9A4-45C5-97E3-CB368358682F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8A61A5C-A9A4-45C5-97E3-CB368358682F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3D42A6BA-38DB-4AA5-9F86-8A78D00D9A07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3D42A6BA-38DB-4AA5-9F86-8A78D00D9A07}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3D42A6BA-38DB-4AA5-9F86-8A78D00D9A07}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3D42A6BA-38DB-4AA5-9F86-8A78D00D9A07}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B8550E71-0CBE-4F88-AC79-2003EFED1DE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B8550E71-0CBE-4F88-AC79-2003EFED1DE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B8550E71-0CBE-4F88-AC79-2003EFED1DE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B8550E71-0CBE-4F88-AC79-2003EFED1DE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {754C18B9-AEDB-4455-BAF4-844C6CEEF8F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {754C18B9-AEDB-4455-BAF4-844C6CEEF8F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {754C18B9-AEDB-4455-BAF4-844C6CEEF8F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {754C18B9-AEDB-4455-BAF4-844C6CEEF8F7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ECCDB04A-A365-4656-989D-4E258D286AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ECCDB04A-A365-4656-989D-4E258D286AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ECCDB04A-A365-4656-989D-4E258D286AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ECCDB04A-A365-4656-989D-4E258D286AE4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9E8C7C3B-B8B3-490C-BA11-E1F60ED4E21D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9E8C7C3B-B8B3-490C-BA11-E1F60ED4E21D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9E8C7C3B-B8B3-490C-BA11-E1F60ED4E21D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9E8C7C3B-B8B3-490C-BA11-E1F60ED4E21D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DEA8FE40-0AE9-4CE6-9430-089C985217CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DEA8FE40-0AE9-4CE6-9430-089C985217CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DEA8FE40-0AE9-4CE6-9430-089C985217CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DEA8FE40-0AE9-4CE6-9430-089C985217CA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F04DB812-7278-47F2-913E-225CE2EF150C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F04DB812-7278-47F2-913E-225CE2EF150C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F04DB812-7278-47F2-913E-225CE2EF150C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F04DB812-7278-47F2-913E-225CE2EF150C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7DCA2BEC-B1E1-4F2B-952A-A26B5110FDA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7DCA2BEC-B1E1-4F2B-952A-A26B5110FDA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7DCA2BEC-B1E1-4F2B-952A-A26B5110FDA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7DCA2BEC-B1E1-4F2B-952A-A26B5110FDA5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E54506B8-0B81-4FC4-99B5-5C67E19D4B09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E54506B8-0B81-4FC4-99B5-5C67E19D4B09}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E54506B8-0B81-4FC4-99B5-5C67E19D4B09}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E54506B8-0B81-4FC4-99B5-5C67E19D4B09}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -944,6 +1037,25 @@ Global
{5F74AD67-A4AD-4660-A63C-844DAAF354C4} = {95D8B040-FD7F-4C86-8E47-341AF630EDA9}
{C419AE2D-D318-49EB-8ECA-6A5DC13FE4EA} = {95D8B040-FD7F-4C86-8E47-341AF630EDA9}
{B8A61A5C-A9A4-45C5-97E3-CB368358682F} = {580D1AE7-AA8F-4912-8B76-105594E00B3B}
+ {9E9F3BB2-6FED-47BC-869C-BFAF6E7C85FC} = {22AB674F-ED91-4FBC-BFEE-8A1E82F9F05E}
+ {CA976F33-7BFA-4F56-8F86-AE132B3B4CBE} = {9E9F3BB2-6FED-47BC-869C-BFAF6E7C85FC}
+ {C5C73211-A713-40BF-8FC8-A690CCBE66F5} = {9E9F3BB2-6FED-47BC-869C-BFAF6E7C85FC}
+ {6C8E1E65-EA73-434D-818F-E564BFFE9F86} = {9E9F3BB2-6FED-47BC-869C-BFAF6E7C85FC}
+ {3D42A6BA-38DB-4AA5-9F86-8A78D00D9A07} = {6C8E1E65-EA73-434D-818F-E564BFFE9F86}
+ {51A31407-7C6A-42E9-93B8-F21DEC518A34} = {9E9F3BB2-6FED-47BC-869C-BFAF6E7C85FC}
+ {B8550E71-0CBE-4F88-AC79-2003EFED1DE1} = {51A31407-7C6A-42E9-93B8-F21DEC518A34}
+ {21835A9E-D667-4761-8675-B2BC105CC2FE} = {22AB674F-ED91-4FBC-BFEE-8A1E82F9F05E}
+ {71BC1256-D225-4272-ADB2-95264E09AF73} = {21835A9E-D667-4761-8675-B2BC105CC2FE}
+ {B2CE3F28-8FEC-4715-B483-5B442E3136CE} = {21835A9E-D667-4761-8675-B2BC105CC2FE}
+ {F720D695-F35A-4700-9463-C359163D14EE} = {21835A9E-D667-4761-8675-B2BC105CC2FE}
+ {754C18B9-AEDB-4455-BAF4-844C6CEEF8F7} = {F720D695-F35A-4700-9463-C359163D14EE}
+ {EC4A66C5-E2E2-4201-9E8D-BAC6B630D12A} = {22AB674F-ED91-4FBC-BFEE-8A1E82F9F05E}
+ {ECCDB04A-A365-4656-989D-4E258D286AE4} = {EC4A66C5-E2E2-4201-9E8D-BAC6B630D12A}
+ {9E8C7C3B-B8B3-490C-BA11-E1F60ED4E21D} = {EC4A66C5-E2E2-4201-9E8D-BAC6B630D12A}
+ {DEA8FE40-0AE9-4CE6-9430-089C985217CA} = {EC4A66C5-E2E2-4201-9E8D-BAC6B630D12A}
+ {F04DB812-7278-47F2-913E-225CE2EF150C} = {580D1AE7-AA8F-4912-8B76-105594E00B3B}
+ {7DCA2BEC-B1E1-4F2B-952A-A26B5110FDA5} = {580D1AE7-AA8F-4912-8B76-105594E00B3B}
+ {E54506B8-0B81-4FC4-99B5-5C67E19D4B09} = {580D1AE7-AA8F-4912-8B76-105594E00B3B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FB8F26CE-4DE6-433F-B32A-79183020BBD6}
diff --git a/source-build.slnf b/source-build.slnf
index 8670ef2f534e..c40dd4fca539 100644
--- a/source-build.slnf
+++ b/source-build.slnf
@@ -6,6 +6,7 @@
"src\\ApiCompat\\Microsoft.DotNet.ApiCompat.Task\\Microsoft.DotNet.ApiCompat.Task.csproj",
"src\\ApiCompat\\Microsoft.DotNet.ApiCompatibility\\Microsoft.DotNet.ApiCompatibility.csproj",
"src\\ApiCompat\\Microsoft.DotNet.PackageValidation\\Microsoft.DotNet.PackageValidation.csproj",
+ "src\\WasmSdk\\Tasks\\Microsoft.NET.Sdk.WebAssembly.Tasks.csproj",
"src\\BlazorWasmSdk\\Tasks\\Microsoft.NET.Sdk.BlazorWebAssembly.Tasks.csproj",
"src\\BlazorWasmSdk\\Tool\\Microsoft.NET.Sdk.BlazorWebAssembly.Tool.csproj",
"src\\BuiltInTools\\BrowserRefresh\\Microsoft.AspNetCore.Watch.BrowserRefresh.csproj",
@@ -18,6 +19,9 @@
"src\\Cli\\Microsoft.DotNet.InternalAbstractions\\Microsoft.DotNet.InternalAbstractions.csproj",
"src\\Cli\\Microsoft.TemplateEngine.Cli\\Microsoft.TemplateEngine.Cli.csproj",
"src\\Cli\\dotnet\\dotnet.csproj",
+ "src\\Containers\\Microsoft.NET.Build.Containers\\Microsoft.NET.Build.Containers.csproj",
+ "src\\Containers\\containerize\\containerize.csproj",
+ "src\\Containers\\packaging\\package.csproj",
"src\\Layout\\redist\\redist.csproj",
"src\\Layout\\tool_fsharp\\tool_fsc.csproj",
"src\\Layout\\tool_msbuild\\tool_msbuild.csproj",
@@ -34,6 +38,8 @@
"src\\Resolvers\\Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver\\Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver.csproj",
"src\\Resolvers\\Microsoft.NET.Sdk.WorkloadManifestReader\\Microsoft.NET.Sdk.WorkloadManifestReader.csproj",
"src\\Resolvers\\WorkloadManifestValidator\\WorkloadManifestValidator.csproj",
+ "src\\StaticWebAssetsSdk\\Tasks\\Microsoft.NET.Sdk.StaticWebAssets.Tasks.csproj",
+ "src\\StaticWebAssetsSdk\\Tool\\Microsoft.NET.Sdk.StaticWebAssets.Tool.csproj",
"src\\Tasks\\Microsoft.NET.Build.Extensions.Tasks\\Microsoft.NET.Build.Extensions.Tasks.csproj",
"src\\Tasks\\Microsoft.NET.Build.Tasks\\Microsoft.NET.Build.Tasks.csproj",
"src\\WebSdk\\ProjectSystem\\Tasks\\Microsoft.NET.Sdk.Web.ProjectSystem.Tasks.csproj",
@@ -44,4 +50,4 @@
"template_feed\\Microsoft.DotNet.Common.ProjectTemplates.8.0\\Microsoft.DotNet.Common.ProjectTemplates.8.0.csproj"
]
}
-}
\ No newline at end of file
+}
diff --git a/src/ApiCompat/Microsoft.DotNet.ApiCompatibility/Rules/AttributesMustMatch.cs b/src/ApiCompat/Microsoft.DotNet.ApiCompatibility/Rules/AttributesMustMatch.cs
index 37cf14c2fafa..308a3f40fdae 100644
--- a/src/ApiCompat/Microsoft.DotNet.ApiCompatibility/Rules/AttributesMustMatch.cs
+++ b/src/ApiCompat/Microsoft.DotNet.ApiCompatibility/Rules/AttributesMustMatch.cs
@@ -4,8 +4,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;
+using Microsoft.DotNet.ApiSymbolExtensions;
namespace Microsoft.DotNet.ApiCompatibility.Rules
{
@@ -70,12 +72,16 @@ private void ReportAttributeDifferences(ISymbol containing,
MetadataInformation leftMetadata,
MetadataInformation rightMetadata,
string itemRef,
- IList left,
- IList right,
+ ImmutableArray left,
+ ImmutableArray right,
IList differences)
{
+ // See discussion in https://github.com/dotnet/sdk/pull/27774. ApiCompat intentionally considers non excluded attribute arguments.
+ left = left.ExcludeNonVisibleOutsideOfAssembly(_settings.SymbolFilter, excludeWithTypeArgumentsNotVisibleOutsideOfAssembly: false);
+ right = right.ExcludeNonVisibleOutsideOfAssembly(_settings.SymbolFilter, excludeWithTypeArgumentsNotVisibleOutsideOfAssembly: false);
+
// No attributes, nothing to do. Exit early.
- if (left.Count == 0 && right.Count == 0)
+ if (left.Length == 0 && right.Length == 0)
{
return;
}
@@ -88,8 +94,8 @@ private void ReportAttributeDifferences(ISymbol containing,
// public void F() {}
// would give you a set like
// { { Foo("a"), Foo("b") }, { Bar } }
- AttributeSet leftAttributeSet = new(_settings, left);
- AttributeSet rightAttributeSet = new(_settings, right);
+ AttributeSet leftAttributeSet = new(_settings.SymbolEqualityComparer, left);
+ AttributeSet rightAttributeSet = new(_settings.SymbolEqualityComparer, right);
foreach (AttributeGroup leftGroup in leftAttributeSet)
{
@@ -290,25 +296,23 @@ private class AttributeSet : IEnumerable
// We use a List instead of a HashSet because in practice, the number of attributes
// on a declaration is going to be extremely small (on the order of 1-3).
private readonly List _set = new();
- private readonly IRuleSettings _settings;
+ private readonly IEqualityComparer _symbolEqualityComparer;
- public AttributeSet(IRuleSettings settings, IList attributes)
+ public AttributeSet(IEqualityComparer symbolEqualityComparer,
+ IList attributes)
{
- _settings = settings;
+ _symbolEqualityComparer = symbolEqualityComparer;
for (int i = 0; i < attributes.Count; i++)
{
Add(attributes[i]);
}
}
- public void Add(AttributeData attributeData)
+ private void Add(AttributeData attributeData)
{
- if (attributeData.AttributeClass != null && !_settings.SymbolFilter.Include(attributeData.AttributeClass))
- return;
-
foreach (AttributeGroup group in _set)
{
- if (_settings.SymbolEqualityComparer.Equals(group.Representative.AttributeClass!, attributeData.AttributeClass!))
+ if (_symbolEqualityComparer.Equals(group.Representative.AttributeClass!, attributeData.AttributeClass!))
{
group.Add(attributeData);
return;
@@ -322,7 +326,7 @@ public bool TryGetValue(AttributeData attributeData, [MaybeNullWhen(false)] out
{
foreach (AttributeGroup group in _set)
{
- if (_settings.SymbolEqualityComparer.Equals(group.Representative.AttributeClass!, attributeData.AttributeClass!))
+ if (_symbolEqualityComparer.Equals(group.Representative.AttributeClass!, attributeData.AttributeClass!))
{
attributeGroup = group;
return true;
diff --git a/src/Assets/TestPackages/PackageLibraryDirectDependency/PackageLibraryDirectDependency/PackageLibraryDirectDependency.csproj b/src/Assets/TestPackages/PackageLibraryDirectDependency/PackageLibraryDirectDependency/PackageLibraryDirectDependency.csproj
index 231823edc8c7..c4ed8baeb193 100644
--- a/src/Assets/TestPackages/PackageLibraryDirectDependency/PackageLibraryDirectDependency/PackageLibraryDirectDependency.csproj
+++ b/src/Assets/TestPackages/PackageLibraryDirectDependency/PackageLibraryDirectDependency/PackageLibraryDirectDependency.csproj
@@ -1,10 +1,6 @@
-
true
-
-
-
net8.0
© Microsoft
Razor Test
diff --git a/src/Assets/TestPackages/PackageLibraryDirectDependency/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj b/src/Assets/TestPackages/PackageLibraryDirectDependency/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
index 1da2577afcc2..5da5c0d37f18 100644
--- a/src/Assets/TestPackages/PackageLibraryDirectDependency/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
+++ b/src/Assets/TestPackages/PackageLibraryDirectDependency/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
@@ -2,9 +2,6 @@
true
-
-
-
net8.0
© Microsoft
Razor Test
diff --git a/src/Assets/TestPackages/PackageLibraryNoStaticAssets/PackageLibraryNoStaticAssets.csproj b/src/Assets/TestPackages/PackageLibraryNoStaticAssets/PackageLibraryNoStaticAssets.csproj
index c65be45a61e3..3d574e76ce85 100644
--- a/src/Assets/TestPackages/PackageLibraryNoStaticAssets/PackageLibraryNoStaticAssets.csproj
+++ b/src/Assets/TestPackages/PackageLibraryNoStaticAssets/PackageLibraryNoStaticAssets.csproj
@@ -2,9 +2,6 @@
true
-
-
-
net8.0
© Microsoft
Razor Test
diff --git a/src/Assets/TestPackages/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj b/src/Assets/TestPackages/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
index 1da2577afcc2..5da5c0d37f18 100644
--- a/src/Assets/TestPackages/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
+++ b/src/Assets/TestPackages/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
@@ -2,9 +2,6 @@
true
-
-
-
net8.0
© Microsoft
Razor Test
diff --git a/src/Assets/TestProjects/AllResourcesInSatellite/AllResourcesInSatellite.csproj b/src/Assets/TestProjects/AllResourcesInSatellite/AllResourcesInSatellite.csproj
index 89d58fc6df67..04c26e61f36b 100644
--- a/src/Assets/TestProjects/AllResourcesInSatellite/AllResourcesInSatellite.csproj
+++ b/src/Assets/TestProjects/AllResourcesInSatellite/AllResourcesInSatellite.csproj
@@ -8,15 +8,6 @@
true
-
-
- $(TargetFrameworks);net46
-
-
false
diff --git a/src/Assets/TestProjects/AllResourcesInSatelliteDisableVersionGenerate/AllResourcesInSatellite.csproj b/src/Assets/TestProjects/AllResourcesInSatelliteDisableVersionGenerate/AllResourcesInSatellite.csproj
index e88002c8e9fa..bd26300d209a 100644
--- a/src/Assets/TestProjects/AllResourcesInSatelliteDisableVersionGenerate/AllResourcesInSatellite.csproj
+++ b/src/Assets/TestProjects/AllResourcesInSatelliteDisableVersionGenerate/AllResourcesInSatellite.csproj
@@ -9,15 +9,6 @@
false
-
-
- $(TargetFrameworks);net46
-
-
false
diff --git a/src/Assets/TestProjects/BlazorHosted/blazorwasm/icudt_custom.dat b/src/Assets/TestProjects/BlazorHosted/blazorwasm/icudt_custom.dat
new file mode 100644
index 000000000000..703d9704375e
Binary files /dev/null and b/src/Assets/TestProjects/BlazorHosted/blazorwasm/icudt_custom.dat differ
diff --git a/src/Assets/TestProjects/BlazorWasmMinimal/icudt_custom.dat b/src/Assets/TestProjects/BlazorWasmMinimal/icudt_custom.dat
new file mode 100644
index 000000000000..703d9704375e
Binary files /dev/null and b/src/Assets/TestProjects/BlazorWasmMinimal/icudt_custom.dat differ
diff --git a/src/Assets/TestProjects/KitchenSink/TestApp/TestApp.csproj b/src/Assets/TestProjects/KitchenSink/TestApp/TestApp.csproj
index 08c45bd4dcae..0c4bb268304d 100644
--- a/src/Assets/TestProjects/KitchenSink/TestApp/TestApp.csproj
+++ b/src/Assets/TestProjects/KitchenSink/TestApp/TestApp.csproj
@@ -26,6 +26,7 @@
false
true
true
+ false
false
<_EnableConsumingManagedCodeFromNativeHosting>false
false
diff --git a/src/Assets/TestProjects/NetCoreCsharpAppReferenceCppCliLib/NETCoreCppCliTest/NETCoreCppCliTest.vcxproj b/src/Assets/TestProjects/NetCoreCsharpAppReferenceCppCliLib/NETCoreCppCliTest/NETCoreCppCliTest.vcxproj
index 353ed36ccf3a..d31795f09d38 100644
--- a/src/Assets/TestProjects/NetCoreCsharpAppReferenceCppCliLib/NETCoreCppCliTest/NETCoreCppCliTest.vcxproj
+++ b/src/Assets/TestProjects/NetCoreCsharpAppReferenceCppCliLib/NETCoreCppCliTest/NETCoreCppCliTest.vcxproj
@@ -17,6 +17,7 @@
ManagedCProj
NETCoreCppCliTest
10.0
+ PackageReference
diff --git a/src/Assets/TestProjects/NewtonsoftProfile/NewtonsoftFilterProfile.xml b/src/Assets/TestProjects/NewtonsoftProfile/NewtonsoftFilterProfile.xml
index 8f5abe95ecf1..5cdbe3bea188 100644
--- a/src/Assets/TestProjects/NewtonsoftProfile/NewtonsoftFilterProfile.xml
+++ b/src/Assets/TestProjects/NewtonsoftProfile/NewtonsoftFilterProfile.xml
@@ -1,3 +1,3 @@
-
+
diff --git a/src/Assets/TestProjects/NewtonsoftProfile/NewtonsoftProfile.xml b/src/Assets/TestProjects/NewtonsoftProfile/NewtonsoftProfile.xml
index 6cc6c5cdc041..bcd999b9dc09 100644
--- a/src/Assets/TestProjects/NewtonsoftProfile/NewtonsoftProfile.xml
+++ b/src/Assets/TestProjects/NewtonsoftProfile/NewtonsoftProfile.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Assets/TestProjects/RazorClassLibrary/ClassLibrary.csproj b/src/Assets/TestProjects/RazorClassLibrary/ClassLibrary.csproj
index 80a63856ab17..34e81b98ce53 100644
--- a/src/Assets/TestProjects/RazorClassLibrary/ClassLibrary.csproj
+++ b/src/Assets/TestProjects/RazorClassLibrary/ClassLibrary.csproj
@@ -2,9 +2,6 @@
true
-
-
-
$(AspNetTestTfm)
© Microsoft
Razor Test
diff --git a/src/Assets/TestProjects/SourceLinkTestApp/Directory.Build.props b/src/Assets/TestProjects/SourceLinkTestApp/Directory.Build.props
new file mode 100644
index 000000000000..c1df2220ddc6
--- /dev/null
+++ b/src/Assets/TestProjects/SourceLinkTestApp/Directory.Build.props
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/Assets/TestProjects/SourceLinkTestApp/Directory.Build.targets b/src/Assets/TestProjects/SourceLinkTestApp/Directory.Build.targets
new file mode 100644
index 000000000000..c1df2220ddc6
--- /dev/null
+++ b/src/Assets/TestProjects/SourceLinkTestApp/Directory.Build.targets
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/Assets/TestProjects/SourceLinkTestApp/Program.cs b/src/Assets/TestProjects/SourceLinkTestApp/Program.cs
new file mode 100644
index 000000000000..67c7486af97f
--- /dev/null
+++ b/src/Assets/TestProjects/SourceLinkTestApp/Program.cs
@@ -0,0 +1,12 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+class Program
+{
+ public static void Main()
+ {
+ Console.WriteLine("Hello World!");
+ }
+}
diff --git a/src/Assets/TestProjects/SourceLinkTestApp/SourceLinkTestApp.csproj b/src/Assets/TestProjects/SourceLinkTestApp/SourceLinkTestApp.csproj
new file mode 100644
index 000000000000..213a534d1e60
--- /dev/null
+++ b/src/Assets/TestProjects/SourceLinkTestApp/SourceLinkTestApp.csproj
@@ -0,0 +1,7 @@
+
+
+ true
+ $(CurrentTargetFramework)
+ Exe
+
+
diff --git a/src/Assets/TestProjects/TestAppWithSlnAndSolutionFolders/src/App/App.csproj b/src/Assets/TestProjects/TestAppWithSlnAndSolutionFolders/src/App/App.csproj
index c2844dce4189..612607351fbf 100644
--- a/src/Assets/TestProjects/TestAppWithSlnAndSolutionFolders/src/App/App.csproj
+++ b/src/Assets/TestProjects/TestAppWithSlnAndSolutionFolders/src/App/App.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Assets/TestProjects/VanillaWasm/Program.cs b/src/Assets/TestProjects/VanillaWasm/Program.cs
new file mode 100644
index 000000000000..ecf115b0e712
--- /dev/null
+++ b/src/Assets/TestProjects/VanillaWasm/Program.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Runtime.InteropServices.JavaScript;
+
+Console.WriteLine("Hello, Browser!");
+
+public partial class MyClass
+{
+ [JSExport]
+ internal static string Greeting()
+ {
+ var text = $"Hello, World! Greetings from {GetHRef()}";
+ Console.WriteLine(text);
+ return text;
+ }
+
+ [JSImport("window.location.href", "main.js")]
+ internal static partial string GetHRef();
+}
diff --git a/src/Assets/TestProjects/VanillaWasm/Properties/AssemblyInfo.cs b/src/Assets/TestProjects/VanillaWasm/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000000..9ad9b578f206
--- /dev/null
+++ b/src/Assets/TestProjects/VanillaWasm/Properties/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+[assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")]
diff --git a/src/Assets/TestProjects/VanillaWasm/Properties/launchSettings.json b/src/Assets/TestProjects/VanillaWasm/Properties/launchSettings.json
new file mode 100644
index 000000000000..1de68ebf4458
--- /dev/null
+++ b/src/Assets/TestProjects/VanillaWasm/Properties/launchSettings.json
@@ -0,0 +1,13 @@
+{
+ "profiles": {
+ "WasmMySdk": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:7251;http://localhost:5015",
+ "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/debug?browser={browserInspectUri}"
+ }
+ }
+}
diff --git a/src/Assets/TestProjects/VanillaWasm/VanillaWasm.csproj b/src/Assets/TestProjects/VanillaWasm/VanillaWasm.csproj
new file mode 100644
index 000000000000..588c52195821
--- /dev/null
+++ b/src/Assets/TestProjects/VanillaWasm/VanillaWasm.csproj
@@ -0,0 +1,6 @@
+
+
+ net8.0
+ true
+
+
diff --git a/src/Assets/TestProjects/VanillaWasm/runtimeconfig.template.json b/src/Assets/TestProjects/VanillaWasm/runtimeconfig.template.json
new file mode 100644
index 000000000000..8f0557352c6e
--- /dev/null
+++ b/src/Assets/TestProjects/VanillaWasm/runtimeconfig.template.json
@@ -0,0 +1,11 @@
+{
+ "wasmHostProperties": {
+ "perHostConfig": [
+ {
+ "name": "browser",
+ "html-path": "index.html",
+ "Host": "browser"
+ }
+ ]
+ }
+}
diff --git a/src/Assets/TestProjects/VanillaWasm/wwwroot/index.html b/src/Assets/TestProjects/VanillaWasm/wwwroot/index.html
new file mode 100644
index 000000000000..e9f8422826d3
--- /dev/null
+++ b/src/Assets/TestProjects/VanillaWasm/wwwroot/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ WasmMySdk
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Assets/TestProjects/VanillaWasm/wwwroot/main.js b/src/Assets/TestProjects/VanillaWasm/wwwroot/main.js
new file mode 100644
index 000000000000..a073fc9cf703
--- /dev/null
+++ b/src/Assets/TestProjects/VanillaWasm/wwwroot/main.js
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import { dotnet } from './_framework/dotnet.js'
+
+const { setModuleImports, getAssemblyExports, getConfig } = await dotnet
+ .withDiagnosticTracing(false)
+ .withApplicationArgumentsFromQuery()
+ .create();
+
+setModuleImports('main.js', {
+ window: {
+ location: {
+ href: () => globalThis.window.location.href
+ }
+ }
+});
+
+const config = getConfig();
+const exports = await getAssemblyExports(config.mainAssemblyName);
+const text = exports.MyClass.Greeting();
+console.log(text);
+
+document.getElementById('out').innerHTML = text;
+await dotnet.run();
\ No newline at end of file
diff --git a/src/Assets/TestProjects/WatchAppWithLaunchSettings/Program.cs b/src/Assets/TestProjects/WatchAppWithLaunchSettings/Program.cs
index 03a88d03a1a3..00282907050c 100644
--- a/src/Assets/TestProjects/WatchAppWithLaunchSettings/Program.cs
+++ b/src/Assets/TestProjects/WatchAppWithLaunchSettings/Program.cs
@@ -1,5 +1,6 @@
Console.WriteLine("Started");
Console.WriteLine($"Environment: {Environment.GetEnvironmentVariable("EnvironmentFromProfile")}");
+Console.WriteLine($"Arguments: {string.Join(",", args)}");
if (Environment.GetEnvironmentVariable("READ_INPUT") != null)
{
diff --git a/src/Assets/TestProjects/WatchAppWithLaunchSettings/Properties/launchSettings.json b/src/Assets/TestProjects/WatchAppWithLaunchSettings/Properties/launchSettings.json
index f8b1abd49b2b..5af4e95e7b68 100644
--- a/src/Assets/TestProjects/WatchAppWithLaunchSettings/Properties/launchSettings.json
+++ b/src/Assets/TestProjects/WatchAppWithLaunchSettings/Properties/launchSettings.json
@@ -5,6 +5,18 @@
"environmentVariables": {
"EnvironmentFromProfile": "Development"
}
+ },
+ "P1": {
+ "commandName": "Project",
+ "commandLineArgs": "argP1"
+ },
+ "P2": {
+ "commandName": "Project",
+ "commandLineArgs": "argP2"
+ },
+ "P and Q and \"R\"": {
+ "commandName": "Project",
+ "commandLineArgs": "argPQR"
}
}
}
diff --git a/src/Assets/TestProjects/WatchBrowserLaunchApp/WatchBrowserLaunchApp.csproj b/src/Assets/TestProjects/WatchBrowserLaunchApp/WatchBrowserLaunchApp.csproj
index bb943a79101b..5fd57ba4e91c 100644
--- a/src/Assets/TestProjects/WatchBrowserLaunchApp/WatchBrowserLaunchApp.csproj
+++ b/src/Assets/TestProjects/WatchBrowserLaunchApp/WatchBrowserLaunchApp.csproj
@@ -1,4 +1,4 @@
-
+
$(CurrentTargetFramework)
diff --git a/src/Assets/TestProjects/WatchHotReloadApp/Program.cs b/src/Assets/TestProjects/WatchHotReloadApp/Program.cs
new file mode 100644
index 000000000000..0e8a498b81e8
--- /dev/null
+++ b/src/Assets/TestProjects/WatchHotReloadApp/Program.cs
@@ -0,0 +1,35 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.Versioning;
+using System.Threading;
+
+var assembly = typeof(C).Assembly;
+
+Console.WriteLine("Started");
+
+// Process ID is insufficient because PID's may be reused.
+Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}");
+Console.WriteLine($"DOTNET_WATCH = {Environment.GetEnvironmentVariable("DOTNET_WATCH")}");
+Console.WriteLine($"DOTNET_WATCH_ITERATION = {Environment.GetEnvironmentVariable("DOTNET_WATCH_ITERATION")}");
+Console.WriteLine($"Arguments = {string.Join(",", args)}");
+Console.WriteLine($"Version = {assembly.GetCustomAttributes().FirstOrDefault()?.Version ?? ""}");
+Console.WriteLine($"TFM = {assembly.GetCustomAttributes().FirstOrDefault()?.FrameworkName ?? ""}");
+Console.WriteLine($"Configuration = {assembly.GetCustomAttributes().FirstOrDefault()?.Configuration ?? ""}");
+
+Loop();
+
+static void Loop()
+{
+ while (true)
+ {
+ Console.WriteLine(".");
+ Thread.Sleep(1000);
+ }
+}
+
+class C { }
diff --git a/src/Assets/TestProjects/WatchHotReloadApp/WatchHotReloadApp.csproj b/src/Assets/TestProjects/WatchHotReloadApp/WatchHotReloadApp.csproj
new file mode 100644
index 000000000000..761b3d38b55e
--- /dev/null
+++ b/src/Assets/TestProjects/WatchHotReloadApp/WatchHotReloadApp.csproj
@@ -0,0 +1,6 @@
+
+
+ $(CurrentTargetFramework)
+ Exe
+
+
diff --git a/src/Assets/TestProjects/WatchHotReloadAppMultiTfm/Program.cs b/src/Assets/TestProjects/WatchHotReloadAppMultiTfm/Program.cs
new file mode 100644
index 000000000000..7d24c192006b
--- /dev/null
+++ b/src/Assets/TestProjects/WatchHotReloadAppMultiTfm/Program.cs
@@ -0,0 +1,36 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.Versioning;
+using System.Threading;
+
+var assembly = typeof(C).Assembly;
+
+Console.WriteLine("Started");
+
+// Process ID is insufficient because PID's may be reused.
+Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}");
+Console.WriteLine($"DOTNET_WATCH = {Environment.GetEnvironmentVariable("DOTNET_WATCH")}");
+Console.WriteLine($"DOTNET_WATCH_ITERATION = {Environment.GetEnvironmentVariable("DOTNET_WATCH_ITERATION")}");
+Console.WriteLine($"Arguments = {string.Join(",", args)}");
+Console.WriteLine($"AssemblyName = {assembly.GetName()}");
+Console.WriteLine($"AssemblyTitle = '{assembly.GetCustomAttributes().FirstOrDefault()?.Title ?? ""}'");
+Console.WriteLine($"TFM = {assembly.GetCustomAttributes().FirstOrDefault()?.FrameworkName ?? ""}");
+Console.WriteLine($"Configuration = {assembly.GetCustomAttributes().FirstOrDefault()?.Configuration ?? ""}");
+
+Loop();
+
+static void Loop()
+{
+ while (true)
+ {
+ Console.WriteLine(".");
+ Thread.Sleep(1000);
+ }
+}
+
+class C { }
diff --git a/src/Assets/TestProjects/WatchHotReloadAppMultiTfm/WatchHotReloadAppMultiTfm.csproj b/src/Assets/TestProjects/WatchHotReloadAppMultiTfm/WatchHotReloadAppMultiTfm.csproj
new file mode 100644
index 000000000000..555794d00141
--- /dev/null
+++ b/src/Assets/TestProjects/WatchHotReloadAppMultiTfm/WatchHotReloadAppMultiTfm.csproj
@@ -0,0 +1,6 @@
+
+
+ $(CurrentTargetFramework);net6.0
+ Exe
+
+
diff --git a/src/Assets/TestProjects/x64SolutionBuild/x64SolutionBuild.csproj b/src/Assets/TestProjects/x64SolutionBuild/x64SolutionBuild.csproj
index 14ef6f89c5e5..e2163fcb1a6e 100644
--- a/src/Assets/TestProjects/x64SolutionBuild/x64SolutionBuild.csproj
+++ b/src/Assets/TestProjects/x64SolutionBuild/x64SolutionBuild.csproj
@@ -1,13 +1,12 @@
-
-
-
-
Exe
$(CurrentTargetFramework)
+
+
+
diff --git a/src/BlazorWasmSdk/.editorconfig b/src/BlazorWasmSdk/.editorconfig
index 58a365c0b27c..17128bc319cd 100644
--- a/src/BlazorWasmSdk/.editorconfig
+++ b/src/BlazorWasmSdk/.editorconfig
@@ -7,3 +7,6 @@
csharp_style_var_elsewhere = true
csharp_style_var_for_built_in_types = true
csharp_style_var_when_type_is_apparent = true
+
+# IDE0073: The file header does not match the required text
+dotnet_diagnostic.IDE0073.severity = error
diff --git a/src/BlazorWasmSdk/Sdk/Sdk.props b/src/BlazorWasmSdk/Sdk/Sdk.props
index e15ec777d8d0..229a27872c8e 100644
--- a/src/BlazorWasmSdk/Sdk/Sdk.props
+++ b/src/BlazorWasmSdk/Sdk/Sdk.props
@@ -9,7 +9,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and
Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
-
+
true
diff --git a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.5_0.targets b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.5_0.targets
index d878b660067c..6ad8f0b3b07a 100644
--- a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.5_0.targets
+++ b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.5_0.targets
@@ -10,6 +10,9 @@ Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
+
+
+
true
diff --git a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets
index 437a3c4aafc0..42b353e5c0db 100644
--- a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets
+++ b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets
@@ -17,8 +17,13 @@ Copyright (c) .NET Foundation. All rights reserved.
true
+
+
+ _GatherBlazorFilesToPublish;$(WasmNestedPublishAppDependsOn)
+
+
$(MSBuildThisFileDirectory)..\
@@ -28,15 +33,8 @@ Copyright (c) .NET Foundation. All rights reserved.
<_BlazorWebAssemblySdkToolAssembly>$(BlazorWebAssemblySdkDirectoryRoot)tools\net8.0\Microsoft.NET.Sdk.BlazorWebAssembly.Tool.dll
-
-
-
-
-
-
-
-
+
true
@@ -52,93 +50,44 @@ Copyright (c) .NET Foundation. All rights reserved.
<_AggressiveAttributeTrimming Condition="'$(_AggressiveAttributeTrimming)' == ''">true
false
true
-
-
- false
- false
- false
- false
- true
+ true
false
- <_TargetingNET60OrLater Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '6.0'))">true
-
-
-
- false
-
true
true
- false
- _GatherWasmFilesToPublish;$(WasmNestedPublishAppDependsOn)
- false
- <_WasmNestedPublishAppPreTarget>ComputeFilesToPublish
-
-
-
-
-
-
$(ResolveStaticWebAssetsInputsDependsOn);
- _AddBlazorWasmStaticWebAssets;
+ _ResolveBlazorWasmOutputs;
-
- _GenerateBuildBlazorBootJson;
- $(StaticWebAssetsPrepareForRunDependsOn)
-
-
-
- $(ResolvePublishStaticWebAssetsDependsOn);
- ProcessPublishFilesForBlazor;
- ComputeBlazorExtensions;
- _AddPublishBlazorBootJsonToStaticWebAssets;
-
-
-
- $(GenerateStaticWebAssetsPublishManifestDependsOn);
- GeneratePublishBlazorBootJson;
-
+
+ $(GenerateBuildWasmBootJsonDependsOn);
+ GenerateBuildBlazorBootExtensionJson;
+
+
+ $(GeneratePublishWasmBootJsonDependsOn);
+ GeneratePublishBlazorBootExtensionJson;
+
-
+
-
+
-
-
-
-
-
- <_BlazorEnableTimeZoneSupport>$(BlazorEnableTimeZoneSupport)
- <_BlazorEnableTimeZoneSupport Condition="'$(_BlazorEnableTimeZoneSupport)' == ''">true
- <_BlazorInvariantGlobalization>$(InvariantGlobalization)
- <_BlazorInvariantGlobalization Condition="'$(_BlazorInvariantGlobalization)' == ''">true
- <_BlazorCopyOutputSymbolsToOutputDirectory>$(CopyOutputSymbolsToOutputDirectory)
- <_BlazorCopyOutputSymbolsToOutputDirectory Condition="'$(_BlazorCopyOutputSymbolsToOutputDirectory)'==''">true
- <_BlazorWebAssemblyLoadAllGlobalizationData>$(BlazorWebAssemblyLoadAllGlobalizationData)
- <_BlazorWebAssemblyLoadAllGlobalizationData Condition="'$(_BlazorWebAssemblyLoadAllGlobalizationData)' == ''">false
-
-
- $(OutputPath)$(PublishDirName)\
-
-
-
-
+
<_BlazorJSFile Include="$(BlazorWebAssemblyJSPath)" />
<_BlazorJSFile Include="$(BlazorWebAssemblyJSMapPath)" Condition="Exists('$(BlazorWebAssemblyJSMapPath)')" />
@@ -151,489 +100,69 @@ Copyright (c) .NET Foundation. All rights reserved.
Text="Unable to find BlazorWebAssembly JS files. This usually indicates a packaging error."
Code="RAZORSDK1007"
Condition="'@(_BlazorJSFile->Count())' == '0'" />
-
- <_BlazorConfigFileCandidates Include="@(StaticWebAsset)" Condition="'%(SourceType)' == 'Discovered'" />
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_BlazorBuildGZipCompressDirectory>$(IntermediateOutputPath)build-gz\
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_BlazorBuildGZipCompressedFile>
- %(RelatedAsset)
-
-
- <_BlazorGzipStaticWebAsset Include="@(_BlazorBuildGZipCompressedFile->'%(FullPath)')" />
-
-
-
- <_BlazorBuildBootJsonPath>$(IntermediateOutputPath)blazor.boot.json
-
-
-
- <_BuildBlazorBootJson
- Include="$(_BlazorBuildBootJsonPath)"
- RelativePath="_framework/blazor.boot.json" />
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
- <_BlazorBuildBootJsonPath>$(IntermediateOutputPath)blazor.boot.json
- <_BlazorWebAssemblyLoadAllGlobalizationData Condition="'$(BlazorWebAssemblyLoadAllGlobalizationData)' == ''">false
-
-
-
- <_BlazorJsModuleCandidatesForBuild
- Include="@(StaticWebAsset)"
- Condition="'%(StaticWebAsset.AssetTraitName)' == 'JSModule' and '%(StaticWebAsset.AssetTraitValue)' == 'JSLibraryModule' and '%(AssetKind)' != 'Publish'" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_BlazorTypeGranularTrimmerDescriptorFile>$(IntermediateOutputPath)typegranularity.trimmerdescriptor.xml
-
-
-
- <_BlazorTypeGranularAssembly
- Include="@(ManagedAssemblyToLink)"
- Condition="'%(Extension)' == '.dll' AND $([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.'))">
- false
- all
-
-
-
-
-
-
-
+
-
-
-
+
-
-
+
- <_BlazorAotEnabled>$(UsingBrowserRuntimeWorkload)
- <_BlazorAotEnabled Condition="'$(_BlazorAotEnabled)' == ''">false
- <_BlazorLinkerEnabled>$(PublishTrimmed)
- <_BlazorLinkerEnabled Condition="'$(_BlazorLinkerEnabled)' == ''">true
+ <_BlazorBuildBootExtensionJsonPath>$(IntermediateOutputPath)blazor.build.boot-extension.json
-
-
-
- <_BlazorPublishPrefilteredAssets
- Include="@(StaticWebAsset)"
- Condition="'%(StaticWebAsset.AssetTraitName)' == 'BlazorWebAssemblyResource' or '%(StaticWebAsset.AssetTraitName)' == 'Culture' or '%(AssetRole)' == 'Alternative'" />
-
-
-
- <_DotNetJsItem Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.DestinationSubPath)' == 'dotnet.js' AND '%(ResolvedFileToPublish.AssetType)' == 'native'" />
-
-
-
- <_DotNetJsVersion>%(_DotNetJsItem.NuGetPackageVersion)
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
- <_BlazorExtensionsCandidate Include="@(BlazorPublishExtension->'%(FullPath)')">
- $(PackageId)
- Computed
- $(PublishDir)wwwroot
- $(StaticWebAssetBasePath)
- %(BlazorPublishExtension.RelativePath)
- Publish
- All
- Primary
- BlazorWebAssemblyResource
- extension:%(BlazorPublishExtension.ExtensionName)
- Never
- PreserveNewest
- %(BlazorPublishExtension.Identity)
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
- <_PublishBlazorBootJson
- Include="$(IntermediateOutputPath)blazor.publish.boot.json"
- RelativePath="_framework/blazor.boot.json" />
-
-
-
-
-
-
-
-
-
-
- <_BlazorPublishAsset
- Include="@(StaticWebAsset)"
- Condition="'%(AssetKind)' != 'Build' and '%(StaticWebAsset.AssetTraitValue)' != 'manifest' and ('%(StaticWebAsset.AssetTraitName)' == 'BlazorWebAssemblyResource' or '%(StaticWebAsset.AssetTraitName)' == 'Culture') and '%(StaticWebAsset.AssetTraitValue)' != 'boot'" />
-
- <_BlazorPublishConfigFile
- Include="@(StaticWebAsset)"
- Condition="'%(StaticWebAsset.AssetTraitName)' == 'BlazorWebAssemblyResource' and '%(StaticWebAsset.AssetTraitValue)' == 'settings'"/>
-
- <_BlazorJsModuleCandidatesForPublish
- Include="@(StaticWebAsset)"
- Condition="'%(StaticWebAsset.AssetTraitName)' == 'JSModule' and '%(StaticWebAsset.AssetTraitValue)' == 'JSLibraryModule' and '%(AssetKind)' != 'Build'" />
-
-
- <_BlazorPublishAsset Remove="@(_BlazorExtensionsCandidatesForPublish)" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
- <_CompressedFileOutputPath>$(IntermediateOutputPath)compress\
- <_BlazorWebAssemblyBrotliIncremental>true
-
-
-
- <_DotNetHostDirectory>$(NetCoreRoot)
- <_DotNetHostFileName>dotnet
- <_DotNetHostFileName Condition="'$(OS)' == 'Windows_NT'">dotnet.exe
+ <_BlazorPublishBootExtensionJsonPath>$(IntermediateOutputPath)blazor.publish.boot-extension.json
-
-
-
-
-
- <_GzipFileToCompressForPublish Include="@(StaticWebAsset)"
- Condition="'%(AssetKind)' != 'Build' and ('%(StaticWebAsset.AssetTraitName)' == 'BlazorWebAssemblyResource' or '%(StaticWebAsset.AssetTraitName)' == 'Culture')" >
- %(Identity)
- Alternative
- Content-Encoding
- gzip
-
-
- <_BrotliFileToCompressForPublish Include="@(_GzipFileToCompressForPublish)" Condition="'%(AssetKind)' != 'Build'">
- br
-
-
-
- <_AlreadyGzipCompressedAssets
- Include="@(StaticWebAsset)"
- Condition="'%(AssetKind)' != 'Build' and ('%(StaticWebAsset.AssetTraitName)' == 'Content-Encoding' and '%(StaticWebAsset.AssetTraitValue)' == 'gzip')" />
- <_GzipFileToCompressForPublish Remove="@(_AlreadyGzipCompressedAssets->'%(RelatedAsset)')" />
-
-
-
-
-
-
-
-
-
-
-
-
-
+
- <_BlazorPublishGZipCompressedFile>
- %(RelatedAsset)
-
- <_BlazorPublishBrotliCompressedFile>
- %(RelatedAsset)
-
-
-
-
+
+
+
diff --git a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.props b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.props
index b7f228be4019..708f19963aa1 100644
--- a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.props
+++ b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.props
@@ -11,20 +11,10 @@ Copyright (c) .NET Foundation. All rights reserved.
-->
-
- browser-wasm
- true
-
-
- false
-
exe
- false
-
- false
-
-
+ browser-wasm
+ false
false
@@ -33,19 +23,12 @@ Copyright (c) .NET Foundation. All rights reserved.
false
- /
- Root
- ComputeFilesToPublish;GetCurrentProjectPublishStaticWebAssetItems
- $(StaticWebAssetsAdditionalPublishProperties);BuildProjectReferences=false;ResolveAssemblyReferencesFindRelatedSatellites=true;_PublishingBlazorWasmProject=true
- $(StaticWebAssetsAdditionalPublishPropertiesToRemove);NoBuild;RuntimeIdentifier
+ $(StaticWebAssetsAdditionalPublishProperties);_PublishingBlazorWasmProject=true
-
-
-
-
+
diff --git a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets
index 879850bdad9d..02d5930912cc 100644
--- a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets
+++ b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets
@@ -17,6 +17,9 @@ Copyright (c) .NET Foundation. All rights reserved.
true
+
+
+ true
@@ -35,7 +38,8 @@ Copyright (c) .NET Foundation. All rights reserved.
- <_BlazorWebAssemblyVersionedTargetsFile Condition="'$(_BlazorWebAssemblyVersionedTargetsFile)' == '' And '$(UseStaticWebAssetsV2)' == 'true'">$(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets
+ <_BlazorTargetingNET60OrLater Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '6.0')) ">true
+ <_BlazorWebAssemblyVersionedTargetsFile Condition="'$(_BlazorWebAssemblyVersionedTargetsFile)' == '' And '$(_BlazorTargetingNET60OrLater)' == 'true'">$(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets
<_BlazorWebAssemblyVersionedTargetsFile Condition="'$(_BlazorWebAssemblyVersionedTargetsFile)' == ''">$(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.5_0.targets
diff --git a/src/BlazorWasmSdk/Tasks/AssetsManifestFile.cs b/src/BlazorWasmSdk/Tasks/AssetsManifestFile.cs
index 872b17aae220..984b64237d39 100644
--- a/src/BlazorWasmSdk/Tasks/AssetsManifestFile.cs
+++ b/src/BlazorWasmSdk/Tasks/AssetsManifestFile.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
namespace Microsoft.NET.Sdk.BlazorWebAssembly
{
diff --git a/src/BlazorWasmSdk/Tasks/BlazorReadSatelliteAssemblyFile.cs b/src/BlazorWasmSdk/Tasks/BlazorReadSatelliteAssemblyFile.cs
index f6bf0c88f8d0..9591fec9f7fe 100644
--- a/src/BlazorWasmSdk/Tasks/BlazorReadSatelliteAssemblyFile.cs
+++ b/src/BlazorWasmSdk/Tasks/BlazorReadSatelliteAssemblyFile.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
using System.Linq;
using System.Xml.Linq;
diff --git a/src/BlazorWasmSdk/Tasks/BlazorWriteSatelliteAssemblyFile.cs b/src/BlazorWasmSdk/Tasks/BlazorWriteSatelliteAssemblyFile.cs
index 92fd8d33e874..882eb6e3d8f4 100644
--- a/src/BlazorWasmSdk/Tasks/BlazorWriteSatelliteAssemblyFile.cs
+++ b/src/BlazorWasmSdk/Tasks/BlazorWriteSatelliteAssemblyFile.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
using System.IO;
using System.Xml;
diff --git a/src/BlazorWasmSdk/Tasks/BootExtensionJsonData.cs b/src/BlazorWasmSdk/Tasks/BootExtensionJsonData.cs
new file mode 100644
index 000000000000..b01ce4ec41fa
--- /dev/null
+++ b/src/BlazorWasmSdk/Tasks/BootExtensionJsonData.cs
@@ -0,0 +1,20 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.NET.Sdk.BlazorWebAssembly
+{
+ public class BootExtensionJsonData
+ {
+#pragma warning disable IDE1006 // Naming Styles
+
+#pragma warning restore IDE1006 // Naming Styles
+ }
+}
diff --git a/src/BlazorWasmSdk/Tasks/BootJsonData.cs b/src/BlazorWasmSdk/Tasks/BootJsonData.cs
index 2a1a54280ddf..f83347e4ea68 100644
--- a/src/BlazorWasmSdk/Tasks/BootJsonData.cs
+++ b/src/BlazorWasmSdk/Tasks/BootJsonData.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
using System.Collections.Generic;
using System.Runtime.Serialization;
@@ -11,7 +12,7 @@ namespace Microsoft.NET.Sdk.BlazorWebAssembly
///
/// Defines the structure of a Blazor boot JSON file
///
- public class BootJsonData
+ public class BootJsonData50
{
///
/// Gets the name of the assembly with the application entry point
@@ -27,7 +28,7 @@ public class BootJsonData
/// and values are SHA-256 hashes formatted in prefixed base-64 style (e.g., 'sha256-abcdefg...')
/// as used for subresource integrity checking.
///
- public ResourcesData resources { get; set; } = new ResourcesData();
+ public ResourcesData50 resources { get; set; } = new ResourcesData50();
///
/// Gets a value that determines whether to enable caching of the
@@ -53,10 +54,10 @@ public class BootJsonData
///
/// Gets or sets the that determines how icu files are loaded.
///
- public ICUDataMode icuDataMode { get; set; }
+ public ICUDataMode50 icuDataMode { get; set; }
}
- public class ResourcesData
+ public class ResourcesData50
{
///
/// .NET Wasm runtime resources (dotnet.wasm, dotnet.js) etc.
@@ -103,14 +104,14 @@ public class ResourcesData
/// Additional assets that the runtime consumes as part of the boot process.
///
[DataMember(EmitDefaultValue = false)]
- public Dictionary runtimeAssets { get; set; }
+ public Dictionary runtimeAssets { get; set; }
}
- public enum ICUDataMode : int
+ public enum ICUDataMode50 : int
{
// Note that the numeric values are serialized and used in JS code, so don't change them without also updating the JS code
-
+
///
/// Load optimized icu data file based on the user's locale
///
@@ -125,6 +126,21 @@ public enum ICUDataMode : int
/// Do not load any icu data files.
///
Invariant = 2,
+
+ ///
+ /// Load custom icu file provided by the developer.
+ ///
+ Custom = 3,
+ }
+
+ [DataContract]
+ public class AdditionalAsset50
+ {
+ [DataMember(Name = "hash")]
+ public string Hash { get; set; }
+
+ [DataMember(Name = "behavior")]
+ public string Behavior { get; set; }
}
#pragma warning restore IDE1006 // Naming Styles
}
diff --git a/src/BlazorWasmSdk/Tasks/BrotliCompress.cs b/src/BlazorWasmSdk/Tasks/BrotliCompress.cs
index f2e305585b48..05d64220599e 100644
--- a/src/BlazorWasmSdk/Tasks/BrotliCompress.cs
+++ b/src/BlazorWasmSdk/Tasks/BrotliCompress.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
using System;
using System.Diagnostics;
diff --git a/src/BlazorWasmSdk/Tasks/ComputeBlazorBuildAssets.cs b/src/BlazorWasmSdk/Tasks/ComputeBlazorBuildAssets.cs
deleted file mode 100644
index 3b04fdac7238..000000000000
--- a/src/BlazorWasmSdk/Tasks/ComputeBlazorBuildAssets.cs
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright (c) .NET Foundation and contributors. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace Microsoft.NET.Sdk.BlazorWebAssembly
-{
- // This task does the build work of processing the project inputs and producing a set of pseudo-static web assets
- // specific to Blazor.
- public class ComputeBlazorBuildAssets : Task
- {
- [Required]
- public ITaskItem[] Candidates { get; set; }
-
- [Required]
- public ITaskItem[] ProjectAssembly { get; set; }
-
- [Required]
- public ITaskItem[] ProjectDebugSymbols { get; set; }
-
- [Required]
- public ITaskItem[] SatelliteAssemblies { get; set; }
-
- [Required]
- public ITaskItem[] ProjectSatelliteAssemblies { get; set; }
-
- [Required]
- public string OutputPath { get; set; }
-
- [Required]
- public bool TimeZoneSupport { get; set; }
-
- [Required]
- public bool InvariantGlobalization { get; set; }
-
- [Required]
- public bool CopySymbols { get; set; }
-
- [Output]
- public ITaskItem[] AssetCandidates { get; set; }
-
- [Output]
- public ITaskItem[] FilesToRemove { get; set; }
-
- public override bool Execute()
- {
- var filesToRemove = new List();
- var assetCandidates = new List();
-
- try
- {
- if (ProjectAssembly.Length != 1)
- {
- Log.LogError("Invalid number of project assemblies '{0}'", string.Join("," + Environment.NewLine, ProjectAssembly.Select(a => a.ItemSpec)));
- return true;
- }
-
- if (ProjectDebugSymbols.Length > 1)
- {
- Log.LogError("Invalid number of symbol assemblies '{0}'", string.Join("," + Environment.NewLine, ProjectDebugSymbols.Select(a => a.ItemSpec)));
- return true;
- }
-
- for (int i = 0; i < Candidates.Length; i++)
- {
- var candidate = Candidates[i];
- if (ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, out var reason))
- {
- Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' because '{1}'", candidate.ItemSpec, reason);
- filesToRemove.Add(candidate);
- continue;
- }
-
- var satelliteAssembly = SatelliteAssemblies.FirstOrDefault(s => s.ItemSpec == candidate.ItemSpec);
- if (satelliteAssembly != null)
- {
- var inferredCulture = satelliteAssembly.GetMetadata("DestinationSubDirectory").Trim('\\', '/');
- Log.LogMessage(MessageImportance.Low, "Found satellite assembly '{0}' asset for candidate '{1}' with inferred culture '{2}'", satelliteAssembly.ItemSpec, candidate.ItemSpec, inferredCulture);
-
- var assetCandidate = new TaskItem(satelliteAssembly);
- assetCandidate.SetMetadata("AssetKind", "Build");
- assetCandidate.SetMetadata("AssetRole", "Related");
- assetCandidate.SetMetadata("AssetTraitName", "Culture");
- assetCandidate.SetMetadata("AssetTraitValue", inferredCulture);
- assetCandidate.SetMetadata("RelativePath", $"_framework/{inferredCulture}/{satelliteAssembly.GetMetadata("FileName")}{satelliteAssembly.GetMetadata("Extension")}");
- assetCandidate.SetMetadata("RelatedAsset", Path.GetFullPath(Path.Combine(OutputPath, "wwwroot", "_framework", Path.GetFileName(assetCandidate.GetMetadata("ResolvedFrom")))));
-
- assetCandidates.Add(assetCandidate);
- continue;
- }
-
- var destinationSubPath = candidate.GetMetadata("DestinationSubPath");
- if (candidate.GetMetadata("FileName") == "dotnet" && candidate.GetMetadata("Extension") == ".js")
- {
- var itemHash = FileHasher.GetFileHash(candidate.ItemSpec);
- var cacheBustedDotNetJSFileName = $"dotnet.{candidate.GetMetadata("NuGetPackageVersion")}.{itemHash}.js";
-
- var originalFileFullPath = Path.GetFullPath(candidate.ItemSpec);
- var originalFileDirectory = Path.GetDirectoryName(originalFileFullPath);
-
- var cacheBustedDotNetJSFullPath = Path.Combine(originalFileDirectory, cacheBustedDotNetJSFileName);
-
- var newDotNetJs = new TaskItem(cacheBustedDotNetJSFullPath, candidate.CloneCustomMetadata());
- newDotNetJs.SetMetadata("OriginalItemSpec", candidate.ItemSpec);
-
- var newRelativePath = $"_framework/{cacheBustedDotNetJSFileName}";
- newDotNetJs.SetMetadata("RelativePath", newRelativePath);
-
- newDotNetJs.SetMetadata("AssetTraitName", "BlazorWebAssemblyResource");
- newDotNetJs.SetMetadata("AssetTraitValue", "native");
-
- assetCandidates.Add(newDotNetJs);
- continue;
- }
- else if (string.IsNullOrEmpty(destinationSubPath))
- {
- var relativePath = candidate.GetMetadata("FileName") + candidate.GetMetadata("Extension");
- candidate.SetMetadata("RelativePath", $"_framework/{relativePath}");
- }
- else
- {
- candidate.SetMetadata("RelativePath", $"_framework/{destinationSubPath}");
- }
-
- // Workaround for https://github.com/dotnet/aspnetcore/issues/37574.
- // For items added as "Reference" in project references, the OriginalItemSpec is incorrect.
- // Ignore it, and use the FullPath instead.
- if (candidate.GetMetadata("ReferenceSourceTarget") == "ProjectReference")
- {
- candidate.SetMetadata("OriginalItemSpec", candidate.ItemSpec);
- }
-
- var culture = candidate.GetMetadata("Culture");
- if (!string.IsNullOrEmpty(culture))
- {
- candidate.SetMetadata("AssetKind", "Build");
- candidate.SetMetadata("AssetRole", "Related");
- candidate.SetMetadata("AssetTraitName", "Culture");
- candidate.SetMetadata("AssetTraitValue", culture);
- var fileName = candidate.GetMetadata("FileName");
- var suffixIndex = fileName.Length - ".resources".Length;
- var relatedAssetPath = Path.GetFullPath(Path.Combine(
- OutputPath,
- "wwwroot",
- "_framework",
- fileName.Substring(0, suffixIndex) + ProjectAssembly[0].GetMetadata("Extension")));
-
- candidate.SetMetadata("RelatedAsset", relatedAssetPath);
-
- Log.LogMessage(MessageImportance.Low, "Found satellite assembly '{0}' asset for inferred candidate '{1}' with culture '{2}'", candidate.ItemSpec, relatedAssetPath, culture);
- }
-
- assetCandidates.Add(candidate);
- }
-
- var intermediateAssembly = new TaskItem(ProjectAssembly[0]);
- intermediateAssembly.SetMetadata("RelativePath", $"_framework/{intermediateAssembly.GetMetadata("FileName")}{intermediateAssembly.GetMetadata("Extension")}");
- assetCandidates.Add(intermediateAssembly);
-
- if (ProjectDebugSymbols.Length > 0)
- {
- var debugSymbols = new TaskItem(ProjectDebugSymbols[0]);
- debugSymbols.SetMetadata("RelativePath", $"_framework/{debugSymbols.GetMetadata("FileName")}{debugSymbols.GetMetadata("Extension")}");
- assetCandidates.Add(debugSymbols);
- }
-
- for (int i = 0; i < ProjectSatelliteAssemblies.Length; i++)
- {
- var projectSatelliteAssembly = ProjectSatelliteAssemblies[i];
- var candidateCulture = projectSatelliteAssembly.GetMetadata("Culture");
- Log.LogMessage(
- "Found satellite assembly '{0}' asset for project '{1}' with culture '{2}'",
- projectSatelliteAssembly.ItemSpec,
- intermediateAssembly.ItemSpec,
- candidateCulture);
-
- var assetCandidate = new TaskItem(Path.GetFullPath(projectSatelliteAssembly.ItemSpec), projectSatelliteAssembly.CloneCustomMetadata());
- var projectAssemblyAssetPath = Path.GetFullPath(Path.Combine(
- OutputPath,
- "wwwroot",
- "_framework",
- ProjectAssembly[0].GetMetadata("FileName") + ProjectAssembly[0].GetMetadata("Extension")));
-
- var normalizedPath = assetCandidate.GetMetadata("TargetPath").Replace('\\', '/');
-
- assetCandidate.SetMetadata("AssetKind", "Build");
- assetCandidate.SetMetadata("AssetRole", "Related");
- assetCandidate.SetMetadata("AssetTraitName", "Culture");
- assetCandidate.SetMetadata("AssetTraitValue", candidateCulture);
- assetCandidate.SetMetadata("RelativePath", Path.Combine("_framework", normalizedPath));
- assetCandidate.SetMetadata("RelatedAsset", projectAssemblyAssetPath);
-
- assetCandidates.Add(assetCandidate);
- }
-
- for (var i = 0; i < assetCandidates.Count; i++)
- {
- var candidate = assetCandidates[i];
- ApplyUniqueMetadataProperties(candidate);
- }
- }
- catch (Exception ex)
- {
- Log.LogError(ex.ToString());
- return false;
- }
-
- FilesToRemove = filesToRemove.ToArray();
- AssetCandidates = assetCandidates.ToArray();
-
- return !Log.HasLoggedErrors;
- }
-
- private static void ApplyUniqueMetadataProperties(ITaskItem candidate)
- {
- var extension = candidate.GetMetadata("Extension");
- var filename = candidate.GetMetadata("FileName");
- switch (extension)
- {
- case ".dll":
- if (string.IsNullOrEmpty(candidate.GetMetadata("AssetTraitName")))
- {
- candidate.SetMetadata("AssetTraitName", "BlazorWebAssemblyResource");
- candidate.SetMetadata("AssetTraitValue", "runtime");
- }
- if (string.Equals(candidate.GetMetadata("ResolvedFrom"), "{HintPathFromItem}", StringComparison.Ordinal))
- {
- candidate.RemoveMetadata("OriginalItemSpec");
- }
- break;
- case ".wasm":
- case ".blat":
- case ".dat" when filename.StartsWith("icudt"):
- candidate.SetMetadata("AssetTraitName", "BlazorWebAssemblyResource");
- candidate.SetMetadata("AssetTraitValue", "native");
- break;
- case ".pdb":
- candidate.SetMetadata("AssetTraitName", "BlazorWebAssemblyResource");
- candidate.SetMetadata("AssetTraitValue", "symbol");
- candidate.RemoveMetadata("OriginalItemSpec");
- break;
- default:
- break;
- }
- }
-
- public static bool ShouldFilterCandidate(
- ITaskItem candidate,
- bool timezoneSupport,
- bool invariantGlobalization,
- bool copySymbols,
- out string reason)
- {
- var extension = candidate.GetMetadata("Extension");
- var fileName = candidate.GetMetadata("FileName");
- var assetType = candidate.GetMetadata("AssetType");
- var fromMonoPackage = string.Equals(
- candidate.GetMetadata("NuGetPackageId"),
- "Microsoft.NETCore.App.Runtime.Mono.browser-wasm",
- StringComparison.Ordinal);
-
- reason = extension switch
- {
- ".a" when fromMonoPackage => "extension is .a is not supported.",
- ".c" when fromMonoPackage => "extension is .c is not supported.",
- ".h" when fromMonoPackage => "extension is .h is not supported.",
- // It is safe to filter out all XML files since we are not interested in any XML file from the list
- // of ResolvedFilesToPublish to become a static web asset. Things like this include XML doc files and
- // so on.
- ".xml" => "it is a documentation file",
- ".rsp" when fromMonoPackage => "extension is .rsp is not supported.",
- ".props" when fromMonoPackage => "extension is .props is not supported.",
- ".blat" when !timezoneSupport => "timezone support is not enabled.",
- ".dat" when invariantGlobalization && fileName.StartsWith("icudt") => "invariant globalization is enabled",
- ".json" when fromMonoPackage && (fileName == "emcc-props" || fileName == "package") => $"{fileName}{extension} is not used by Blazor",
- ".ts" when fromMonoPackage && fileName == "dotnet.d" => "dotnet type definition is not used by Blazor",
- ".ts" when fromMonoPackage && fileName == "dotnet-legacy.d" => "dotnet type definition is not used by Blazor",
- ".js" when assetType == "native" && fileName != "dotnet" => $"{fileName}{extension} is not used by Blazor",
- ".pdb" when !copySymbols => "copying symbols is disabled",
- ".symbols" when fromMonoPackage => "extension .symbols is not required.",
- _ => null
- };
-
- return reason != null;
- }
- }
-}
diff --git a/src/BlazorWasmSdk/Tasks/ComputeBlazorFilesToCompress.cs b/src/BlazorWasmSdk/Tasks/ComputeBlazorFilesToCompress.cs
deleted file mode 100644
index 5ce7636cd024..000000000000
--- a/src/BlazorWasmSdk/Tasks/ComputeBlazorFilesToCompress.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) .NET Foundation and contributors. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System.Collections.Generic;
-using System.IO;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace Microsoft.NET.Sdk.BlazorWebAssembly
-{
- // During the blazor build process some assets might not be at their final location by the time we try to compress them.
- // For that reason we need to determine the path to use to compress the file, which is what this task deals with.
- // We first check on the OriginalItemSpec of the asset and use that if the asset exists there.
- // In case it does not, we rely use the ItemSpec, which in case OriginalItemSpec does not exist, should point to an existing file on disk.
- // If neither the ItemSpec nor the OriginalItemSpec exist, we issue an error, since it indicates that the asset is not correctly
- // defined.
- // We can't just use the ItemSpec because for some assets that points to the output folder and causes issues with incrementalism.
- public class ComputeBlazorFilesToCompress : Task
- {
- [Required] public ITaskItem[] Assets { get; set; }
-
- [Output] public ITaskItem[] AssetsToCompress { get; set; }
-
- public override bool Execute()
- {
- var result = new List();
-
- for (var i = 0; i < Assets.Length; i++)
- {
- var asset = Assets[i];
- var originalItemSpec = asset.GetMetadata("OriginalItemSpec");
- if (File.Exists(originalItemSpec))
- {
- Log.LogMessage(MessageImportance.Low, "Asset '{0}' found at OriginalItemSpec '{1}' and will be used for compressing the asset",
- asset.ItemSpec,
- originalItemSpec);
-
- result.Add(CreateGzipAsset(asset, originalItemSpec));
- }
- else if (File.Exists(asset.ItemSpec))
- {
- Log.LogMessage(MessageImportance.Low, "Asset '{0}' found at '{1}' and will be used for compressing the asset",
- asset.ItemSpec,
- asset.ItemSpec);
-
- result.Add(CreateGzipAsset(asset, asset.ItemSpec));
- }
- else
- {
- Log.LogError("The asset '{0}' can not be found at any of the searched locations '{1}' and '{2}'",
- asset.ItemSpec,
- asset.ItemSpec,
- originalItemSpec);
- break;
- }
- }
-
- AssetsToCompress = result.ToArray();
-
- return !Log.HasLoggedErrors;
-
- static TaskItem CreateGzipAsset(ITaskItem asset, string gzipSpec)
- {
- var result = new TaskItem(gzipSpec, asset.CloneCustomMetadata());
-
- result.SetMetadata("RelatedAsset", asset.ItemSpec);
- result.SetMetadata("AssetRole", "Alternative");
- result.SetMetadata("AssetTraitName", "Content-Encoding");
- result.SetMetadata("AssetTraitValue", "gzip");
-
- return result;
- }
- }
- }
-}
diff --git a/src/BlazorWasmSdk/Tasks/ComputeBlazorPublishAssets.cs b/src/BlazorWasmSdk/Tasks/ComputeBlazorPublishAssets.cs
deleted file mode 100644
index fa7e2f67403f..000000000000
--- a/src/BlazorWasmSdk/Tasks/ComputeBlazorPublishAssets.cs
+++ /dev/null
@@ -1,618 +0,0 @@
-// Copyright (c) .NET Foundation and contributors. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace Microsoft.NET.Sdk.BlazorWebAssembly
-{
- // This target computes the list of publish static web assets based on the changes that happen during publish and the list of build static
- // web assets.
- // In this target we need to do 2 things:
- // * Harmonize the list of dlls produced at build time with the list of resolved files to publish.
- // * We iterate over the list of existing static web assets and do as follows:
- // * If we find the assembly in the resolved files to publish and points to the original assembly (linker disabled or assembly not linked)
- // we create a new "Publish" static web asset for the assembly.
- // * If we find the assembly in the resolved files to publish and points to a new location, we assume this assembly has been updated (as part of linking)
- // and we create a new "Publish" static web asset for the asembly pointing to the new location.
- // * If we don't find the assembly on the resolved files to publish it has been linked out from the app, so we don't add any new static web asset and we
- // also avoid adding any existing related static web asset (satellite assemblies and compressed versions).
- // * We update static web assets for satellite assemblies and compressed assets accordingly.
- // * Look at the list of "native" assets and determine whether we need to create new publish assets for the current build assets or if we need to
- // update the native assets because the app was ahead of time compiled.
- public class ComputeBlazorPublishAssets : Task
- {
- [Required]
- public ITaskItem[] ResolvedFilesToPublish { get; set; }
-
- [Required]
- public ITaskItem[] WasmAotAssets { get; set; }
-
- [Required]
- public ITaskItem[] ExistingAssets { get; set; }
-
- [Required]
- public bool TimeZoneSupport { get; set; }
-
- [Required]
- public bool InvariantGlobalization { get; set; }
-
- [Required]
- public bool CopySymbols { get; set; }
-
- [Required]
- public string PublishPath { get; set; }
-
- [Required]
- public string DotNetJsVersion { get; set; }
-
- [Output]
- public ITaskItem[] NewCandidates { get; set; }
-
- [Output]
- public ITaskItem[] FilesToRemove { get; set; }
-
- public override bool Execute()
- {
- var filesToRemove = new List();
- var newAssets = new List();
-
- try
- {
- // We'll do a first pass over the resolved files to publish to figure out what files need to be removed
- // as well as categorize resolved files into different groups.
- var resolvedFilesToPublishToRemove = new Dictionary(StringComparer.Ordinal);
-
- // These assemblies are keyed of the assembly name "computed" based on the relative path, which must be
- // unique.
- var resolvedAssembliesToPublish = new Dictionary(StringComparer.Ordinal);
- var resolvedSymbolsToPublish = new Dictionary(StringComparer.Ordinal);
- var satelliteAssemblyToPublish = new Dictionary<(string, string), ITaskItem>(EqualityComparer<(string, string)>.Default);
- var resolvedNativeAssetToPublish = new Dictionary(StringComparer.Ordinal);
- GroupResolvedFilesToPublish(
- resolvedFilesToPublishToRemove,
- resolvedAssembliesToPublish,
- satelliteAssemblyToPublish,
- resolvedSymbolsToPublish,
- resolvedNativeAssetToPublish);
-
- // Group candidate static web assets
- var assemblyAssets = new Dictionary();
- var symbolAssets = new Dictionary();
- var nativeAssets = new Dictionary();
- var satelliteAssemblyAssets = new Dictionary();
- var compressedRepresentations = new Dictionary();
- GroupExistingStaticWebAssets(
- assemblyAssets,
- nativeAssets,
- satelliteAssemblyAssets,
- symbolAssets,
- compressedRepresentations);
-
- var newStaticWebAssets = ComputeUpdatedAssemblies(
- satelliteAssemblyToPublish,
- filesToRemove,
- resolvedAssembliesToPublish,
- assemblyAssets,
- satelliteAssemblyAssets,
- compressedRepresentations);
-
- newAssets.AddRange(newStaticWebAssets);
-
- var nativeStaticWebAssets = ProcessNativeAssets(
- nativeAssets,
- resolvedFilesToPublishToRemove,
- resolvedNativeAssetToPublish,
- compressedRepresentations,
- filesToRemove);
-
- newAssets.AddRange(nativeStaticWebAssets);
-
- var symbolStaticWebAssets = ProcessSymbolAssets(
- symbolAssets,
- compressedRepresentations,
- resolvedFilesToPublishToRemove,
- resolvedSymbolsToPublish,
- filesToRemove);
-
- newAssets.AddRange(symbolStaticWebAssets);
-
- foreach (var kvp in resolvedFilesToPublishToRemove)
- {
- var resolvedPublishFileToRemove = kvp.Value;
- filesToRemove.Add(resolvedPublishFileToRemove);
- }
- }
- catch (Exception ex)
- {
- Log.LogError(ex.ToString());
- return false;
- }
-
- FilesToRemove = filesToRemove.ToArray();
- NewCandidates = newAssets.ToArray();
-
- return !Log.HasLoggedErrors;
- }
-
- private List ProcessNativeAssets(
- Dictionary nativeAssets,
- IDictionary resolvedPublishFilesToRemove,
- Dictionary resolvedNativeAssetToPublish,
- Dictionary compressedRepresentations,
- List filesToRemove)
- {
- var nativeStaticWebAssets = new List();
-
- // Keep track of the updated assets to determine what compressed assets we can reuse
- var updateMap = new Dictionary();
-
- foreach (var kvp in nativeAssets)
- {
- var key = kvp.Key;
- var asset = kvp.Value;
- var isDotNetJs = IsDotNetJs(key);
- var isDotNetWasm = IsDotNetWasm(key);
- if (!isDotNetJs && !isDotNetWasm)
- {
- if (resolvedNativeAssetToPublish.TryGetValue(Path.GetFileName(asset.GetMetadata("OriginalItemSpec")), out var existing))
- {
- if (!resolvedPublishFilesToRemove.TryGetValue(existing.ItemSpec, out var removed))
- {
- // This is a native asset like timezones.blat or similar that was not filtered and that needs to be updated
- // to a publish asset.
- var newAsset = new TaskItem(asset);
- ApplyPublishProperties(newAsset);
- nativeStaticWebAssets.Add(newAsset);
- filesToRemove.Add(existing);
- updateMap.Add(asset.ItemSpec, newAsset);
- Log.LogMessage(MessageImportance.Low, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Removing asset '{0}'.", existing.ItemSpec);
- // This was a file that was filtered, so just remove it, we don't need to add any publish static web asset
- filesToRemove.Add(removed);
-
- // Remove the file from the list to avoid double processing later when we process other files we filtered.
- resolvedPublishFilesToRemove.Remove(existing.ItemSpec);
- }
- }
-
- continue;
- }
-
- if (isDotNetJs)
- {
- var aotDotNetJs = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.js");
- ITaskItem newDotNetJs = null;
- if (aotDotNetJs != null)
- {
- newDotNetJs = new TaskItem(Path.GetFullPath(aotDotNetJs.ItemSpec), asset.CloneCustomMetadata());
- newDotNetJs.SetMetadata("OriginalItemSpec", aotDotNetJs.ItemSpec);
- newDotNetJs.SetMetadata("RelativePath", $"_framework/{$"dotnet.{DotNetJsVersion}.{FileHasher.GetFileHash(aotDotNetJs.ItemSpec)}.js"}");
-
- updateMap.Add(asset.ItemSpec, newDotNetJs);
- Log.LogMessage(MessageImportance.Low, "Replacing asset '{0}' with AoT version '{1}'", asset.ItemSpec, newDotNetJs.ItemSpec);
- }
- else
- {
- newDotNetJs = new TaskItem(asset);
- Log.LogMessage(MessageImportance.Low, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
- }
-
- ApplyPublishProperties(newDotNetJs);
- nativeStaticWebAssets.Add(newDotNetJs);
- if (resolvedNativeAssetToPublish.TryGetValue("dotnet.js", out var resolved))
- {
- filesToRemove.Add(resolved);
- }
- continue;
- }
-
- if (isDotNetWasm)
- {
- var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.wasm");
- ITaskItem newDotNetWasm = null;
- if (aotDotNetWasm != null)
- {
- newDotNetWasm = new TaskItem(Path.GetFullPath(aotDotNetWasm.ItemSpec), asset.CloneCustomMetadata());
- newDotNetWasm.SetMetadata("OriginalItemSpec", aotDotNetWasm.ItemSpec);
- updateMap.Add(asset.ItemSpec, newDotNetWasm);
- Log.LogMessage(MessageImportance.Low, "Replacing asset '{0}' with AoT version '{1}'", asset.ItemSpec, newDotNetWasm.ItemSpec);
- }
- else
- {
- newDotNetWasm = new TaskItem(asset);
- Log.LogMessage(MessageImportance.Low, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
- }
-
- ApplyPublishProperties(newDotNetWasm);
- nativeStaticWebAssets.Add(newDotNetWasm);
- if (resolvedNativeAssetToPublish.TryGetValue("dotnet.wasm", out var resolved))
- {
- filesToRemove.Add(resolved);
- }
- continue;
- }
- }
-
- var compressedUpdatedFiles = ProcessCompressedAssets(compressedRepresentations, nativeAssets, updateMap);
- foreach (var f in compressedUpdatedFiles)
- {
- nativeStaticWebAssets.Add(f);
- }
-
- return nativeStaticWebAssets;
-
- static bool IsDotNetJs(string key)
- {
- var fileName = Path.GetFileName(key);
- return fileName.StartsWith("dotnet.", StringComparison.Ordinal) && fileName.EndsWith(".js", StringComparison.Ordinal) && !fileName.Contains("worker");
- }
-
- static bool IsDotNetWasm(string key) => string.Equals("dotnet.wasm", Path.GetFileName(key), StringComparison.Ordinal);
- }
-
- private List ProcessSymbolAssets(
- Dictionary symbolAssets,
- Dictionary compressedRepresentations,
- Dictionary resolvedPublishFilesToRemove,
- Dictionary resolvedSymbolAssetToPublish,
- List filesToRemove)
- {
- var symbolStaticWebAssets = new List();
- var updateMap = new Dictionary();
-
- foreach (var kvp in symbolAssets)
- {
- var asset = kvp.Value;
- if (resolvedSymbolAssetToPublish.TryGetValue(Path.GetFileName(asset.GetMetadata("OriginalItemSpec")), out var existing))
- {
- if (!resolvedPublishFilesToRemove.TryGetValue(existing.ItemSpec, out var removed))
- {
- // This is a symbol asset like classlibrary.pdb or similar that was not filtered and that needs to be updated
- // to a publish asset.
- var newAsset = new TaskItem(asset);
- ApplyPublishProperties(newAsset);
- symbolStaticWebAssets.Add(newAsset);
- updateMap.Add(newAsset.ItemSpec, newAsset);
- filesToRemove.Add(existing);
- Log.LogMessage(MessageImportance.Low, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
- }
- else
- {
- // This was a file that was filtered, so just remove it, we don't need to add any publish static web asset
- filesToRemove.Add(removed);
-
- // Remove the file from the list to avoid double processing later when we process other files we filtered.
- resolvedPublishFilesToRemove.Remove(existing.ItemSpec);
- }
- }
- }
-
- var compressedFiles = ProcessCompressedAssets(compressedRepresentations, symbolAssets, updateMap);
-
- foreach (var file in compressedFiles)
- {
- symbolStaticWebAssets.Add(file);
- }
-
- return symbolStaticWebAssets;
- }
-
- private List ComputeUpdatedAssemblies(
- IDictionary<(string, string assemblyName), ITaskItem> satelliteAssemblies,
- List filesToRemove,
- Dictionary resolvedAssembliesToPublish,
- Dictionary assemblyAssets,
- Dictionary satelliteAssemblyAssets,
- Dictionary compressedRepresentations)
- {
- // All assemblies, satellite assemblies and gzip files are initially defined as build assets.
- // We need to update them to publish assets when they haven't changed or when they have been linked.
- // For satellite assemblies and compressed files, we won't include them in the list of assets to update
- // when the original assembly they depend on has been linked out.
- var assetsToUpdate = new Dictionary();
- var linkedAssets = new Dictionary();
-
- foreach (var kvp in assemblyAssets)
- {
- var asset = kvp.Value;
- var fileName = Path.GetFileName(asset.GetMetadata("RelativePath"));
- if (resolvedAssembliesToPublish.TryGetValue(fileName, out var existing))
- {
- // We found the assembly, so it'll have to be updated.
- assetsToUpdate.Add(asset.ItemSpec, asset);
- filesToRemove.Add(existing);
- if (!string.Equals(asset.ItemSpec, existing.GetMetadata("FullPath"), StringComparison.Ordinal))
- {
- linkedAssets.Add(asset.ItemSpec, existing);
- }
- }
- }
-
- foreach (var kvp in satelliteAssemblyAssets)
- {
- var satelliteAssembly = kvp.Value;
- var relatedAsset = satelliteAssembly.GetMetadata("RelatedAsset");
- if (assetsToUpdate.ContainsKey(relatedAsset))
- {
- assetsToUpdate.Add(satelliteAssembly.ItemSpec, satelliteAssembly);
- var culture = satelliteAssembly.GetMetadata("AssetTraitValue");
- var fileName = Path.GetFileName(satelliteAssembly.GetMetadata("RelativePath"));
- if (satelliteAssemblies.TryGetValue((culture, fileName), out var existing))
- {
- filesToRemove.Add(existing);
- }
- else
- {
- var message = $"Can't find the original satellite assembly in the list of resolved files to " +
- $"publish for asset '{satelliteAssembly.ItemSpec}'.";
- throw new InvalidOperationException(message);
- }
- }
- }
-
- var compressedFiles = ProcessCompressedAssets(compressedRepresentations, assetsToUpdate, linkedAssets);
-
- foreach (var file in compressedFiles)
- {
- assetsToUpdate.Add(file.ItemSpec, file);
- }
-
- var updatedAssetsMap = new Dictionary(StringComparer.Ordinal);
- foreach (var asset in assetsToUpdate.Select(a => a.Value).OrderBy(a => a.GetMetadata("AssetRole"), Comparer.Create(OrderByAssetRole)))
- {
- var assetTraitName = asset.GetMetadata("AssetTraitName");
- switch (assetTraitName)
- {
- case "BlazorWebAssemblyResource":
- ITaskItem newAsemblyAsset = null;
- if (linkedAssets.TryGetValue(asset.ItemSpec, out var linked))
- {
- newAsemblyAsset = new TaskItem(linked.GetMetadata("FullPath"), asset.CloneCustomMetadata());
- newAsemblyAsset.SetMetadata("OriginalItemSpec", linked.ItemSpec);
- Log.LogMessage(MessageImportance.Low, "Replacing asset '{0}' with linked version '{1}'",
- asset.ItemSpec,
- newAsemblyAsset.ItemSpec);
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Linked asset not found for asset '{0}'", asset.ItemSpec);
- newAsemblyAsset = new TaskItem(asset);
- }
- ApplyPublishProperties(newAsemblyAsset);
-
- updatedAssetsMap.Add(asset.ItemSpec, newAsemblyAsset);
- break;
- default:
- // Satellite assembliess and compressed assets
- var dependentAsset = new TaskItem(asset);
- ApplyPublishProperties(dependentAsset);
- UpdateRelatedAssetProperty(asset, dependentAsset, updatedAssetsMap);
- Log.LogMessage(MessageImportance.Low, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
-
- updatedAssetsMap.Add(asset.ItemSpec, dependentAsset);
- break;
- }
- }
-
- return updatedAssetsMap.Values.ToList();
- }
-
- private List ProcessCompressedAssets(
- Dictionary compressedRepresentations,
- Dictionary assetsToUpdate,
- Dictionary updatedAssets)
- {
- var processed = new List();
- var runtimeAssetsToUpdate = new List();
- foreach (var kvp in compressedRepresentations)
- {
- var compressedAsset = kvp.Value;
- var relatedAsset = compressedAsset.GetMetadata("RelatedAsset");
- if (assetsToUpdate.ContainsKey(relatedAsset))
- {
- if (!updatedAssets.ContainsKey(relatedAsset))
- {
- Log.LogMessage(MessageImportance.Low, "Related assembly for '{0}' was not updated and the compressed asset can be reused.", relatedAsset);
- var newCompressedAsset = new TaskItem(compressedAsset);
- ApplyPublishProperties(newCompressedAsset);
- runtimeAssetsToUpdate.Add(newCompressedAsset);
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Related assembly for '{0}' was updated and the compressed asset will be discarded.", relatedAsset);
- }
-
- processed.Add(kvp.Key);
- }
- }
-
- // Remove all the elements we've found to avoid having to iterate over them when we process other assets.
- foreach (var element in processed)
- {
- compressedRepresentations.Remove(element);
- }
-
- return runtimeAssetsToUpdate;
- }
-
- private static void UpdateRelatedAssetProperty(ITaskItem asset, TaskItem newAsset, Dictionary updatedAssetsMap)
- {
- if (!updatedAssetsMap.TryGetValue(asset.GetMetadata("RelatedAsset"), out var updatedRelatedAsset))
- {
- throw new InvalidOperationException("Related asset not found.");
- }
-
- newAsset.SetMetadata("RelatedAsset", updatedRelatedAsset.ItemSpec);
- }
-
- private int OrderByAssetRole(string left, string right)
- {
- var leftScore = GetScore(left);
- var rightScore = GetScore(right);
-
- return leftScore - rightScore;
-
- static int GetScore(string candidate) => candidate switch
- {
- "Primary" => 0,
- "Related" => 1,
- "Alternative" => 2,
- _ => throw new InvalidOperationException("Invalid asset role"),
- };
- }
-
- private void ApplyPublishProperties(ITaskItem newAsemblyAsset)
- {
- newAsemblyAsset.SetMetadata("AssetKind", "Publish");
- newAsemblyAsset.SetMetadata("ContentRoot", Path.Combine(PublishPath, "wwwroot"));
- newAsemblyAsset.SetMetadata("CopyToOutputDirectory", "Never");
- newAsemblyAsset.SetMetadata("CopyToPublishDirectory", "PreserveNewest");
- }
-
- private void GroupExistingStaticWebAssets(
- Dictionary assemblyAssets,
- Dictionary nativeAssets,
- Dictionary satelliteAssemblyAssets,
- Dictionary symbolAssets,
- Dictionary compressedRepresentations)
- {
- foreach (var asset in ExistingAssets)
- {
- var traitName = asset.GetMetadata("AssetTraitName");
- if (IsWebAssemblyResource(traitName))
- {
- var traitValue = asset.GetMetadata("AssetTraitValue");
- if (IsRuntimeAsset(traitValue))
- {
- assemblyAssets.Add(asset.ItemSpec, asset);
- }
- else if (IsNativeAsset(traitValue))
- {
- nativeAssets.Add(asset.ItemSpec, asset);
- }
- else if (IsSymbolAsset(traitValue))
- {
- symbolAssets.Add(asset.ItemSpec, asset);
- }
- }
- else if (IsCulture(traitName))
- {
- satelliteAssemblyAssets.Add(asset.ItemSpec, asset);
- }
- else if (IsAlternative(asset))
- {
- compressedRepresentations.Add(asset.ItemSpec, asset);
- }
- }
- }
-
- private void GroupResolvedFilesToPublish(
- Dictionary resolvedFilesToPublishToRemove,
- Dictionary resolvedAssemblyToPublish,
- Dictionary<(string, string), ITaskItem> satelliteAssemblyToPublish,
- Dictionary resolvedSymbolsToPublish,
- Dictionary resolvedNativeAssetToPublish)
- {
- foreach (var candidate in ResolvedFilesToPublish)
- {
- if (ComputeBlazorBuildAssets.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, out var reason))
- {
- Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' because '{1}'", candidate.ItemSpec, reason);
- if (!resolvedFilesToPublishToRemove.ContainsKey(candidate.ItemSpec))
- {
- resolvedFilesToPublishToRemove.Add(candidate.ItemSpec, candidate);
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Duplicate candidate '{0}' found in ResolvedFilesToPublish", candidate.ItemSpec);
- }
- continue;
- }
-
- var extension = candidate.GetMetadata("Extension");
- if (string.Equals(extension, ".dll", StringComparison.Ordinal))
- {
- var culture = candidate.GetMetadata("Culture");
- var inferredCulture = candidate.GetMetadata("DestinationSubDirectory").Replace("\\", "/").Trim('/');
- if (!string.IsNullOrEmpty(culture) || !string.IsNullOrEmpty(inferredCulture))
- {
- var finalCulture = !string.IsNullOrEmpty(culture) ? culture : inferredCulture;
- var assemblyName = Path.GetFileName(candidate.GetMetadata("RelativePath").Replace("\\", "/"));
- if (!satelliteAssemblyToPublish.ContainsKey((finalCulture, assemblyName)))
- {
- satelliteAssemblyToPublish.Add((finalCulture, assemblyName), candidate);
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Duplicate candidate '{0}' found in ResolvedFilesToPublish", candidate.ItemSpec);
- }
- continue;
- }
-
- var candidateName = Path.GetFileName(candidate.GetMetadata("RelativePath"));
- if (!resolvedAssemblyToPublish.ContainsKey(candidateName))
- {
- resolvedAssemblyToPublish.Add(candidateName, candidate);
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Duplicate candidate '{0}' found in ResolvedFilesToPublish", candidate.ItemSpec);
- }
-
- continue;
- }
-
- if (string.Equals(extension, ".pdb", StringComparison.Ordinal))
- {
- var candidateName = Path.GetFileName(candidate.GetMetadata("RelativePath"));
- if (!resolvedSymbolsToPublish.ContainsKey(candidateName))
- {
- resolvedSymbolsToPublish.Add(candidateName, candidate);
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Duplicate candidate '{0}' found in ResolvedFilesToPublish", candidate.ItemSpec);
- }
-
- continue;
- }
-
- // Capture all the native unfiltered assets since we need to process them to determine what static web assets need to get
- // upgraded
- if (string.Equals(candidate.GetMetadata("AssetType"), "native", StringComparison.Ordinal))
- {
- var candidateName = $"{candidate.GetMetadata("FileName")}{extension}";
- if (!resolvedNativeAssetToPublish.ContainsKey(candidateName))
- {
- resolvedNativeAssetToPublish.Add(candidateName, candidate);
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Duplicate candidate '{0}' found in ResolvedFilesToPublish", candidate.ItemSpec);
- }
- continue;
- }
- }
- }
-
- private static bool IsNativeAsset(string traitValue) => string.Equals(traitValue, "native", StringComparison.Ordinal);
-
- private static bool IsRuntimeAsset(string traitValue) => string.Equals(traitValue, "runtime", StringComparison.Ordinal);
- private static bool IsSymbolAsset(string traitValue) => string.Equals(traitValue, "symbol", StringComparison.Ordinal);
-
- private static bool IsAlternative(ITaskItem asset) => string.Equals(asset.GetMetadata("AssetRole"), "Alternative", StringComparison.Ordinal);
-
- private static bool IsCulture(string traitName) => string.Equals(traitName, "Culture", StringComparison.Ordinal);
-
- private static bool IsWebAssemblyResource(string traitName) => string.Equals(traitName, "BlazorWebAssemblyResource", StringComparison.Ordinal);
- }
-}
diff --git a/src/BlazorWasmSdk/Tasks/CreateBlazorTrimmerRootDescriptorFile.cs b/src/BlazorWasmSdk/Tasks/CreateBlazorTrimmerRootDescriptorFile.cs
index f14ffad2219a..9eacd7901756 100644
--- a/src/BlazorWasmSdk/Tasks/CreateBlazorTrimmerRootDescriptorFile.cs
+++ b/src/BlazorWasmSdk/Tasks/CreateBlazorTrimmerRootDescriptorFile.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
using System;
using System.Collections.Generic;
diff --git a/src/BlazorWasmSdk/Tasks/FileHasher.cs b/src/BlazorWasmSdk/Tasks/FileHasher.cs
deleted file mode 100644
index d79cfc4f1ed6..000000000000
--- a/src/BlazorWasmSdk/Tasks/FileHasher.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System;
-using System.Numerics;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace Microsoft.NET.Sdk.BlazorWebAssembly
-{
- public static class FileHasher
- {
- public static string GetFileHash(string filePath)
- {
- using var hash = SHA256.Create();
- var bytes = Encoding.UTF8.GetBytes(filePath);
- var hashBytes = hash.ComputeHash(bytes);
- return ToBase36(hashBytes);
- }
-
- private static string ToBase36(byte[] hash)
- {
- const string chars = "0123456789abcdefghijklmnopqrstuvwxyz";
-
- var result = new char[10];
- var dividend = BigInteger.Abs(new BigInteger(hash.AsSpan().Slice(0, 9).ToArray()));
- for (var i = 0; i < 10; i++)
- {
- dividend = BigInteger.DivRem(dividend, 36, out var remainder);
- result[i] = chars[(int)remainder];
- }
-
- return new string(result);
- }
- }
-}
diff --git a/src/BlazorWasmSdk/Tasks/GZipCompress.cs b/src/BlazorWasmSdk/Tasks/GZipCompress.cs
index e4c594f708b7..1c7eb3efd6c3 100644
--- a/src/BlazorWasmSdk/Tasks/GZipCompress.cs
+++ b/src/BlazorWasmSdk/Tasks/GZipCompress.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
using System;
using System.IO;
diff --git a/src/BlazorWasmSdk/Tasks/GenerateBlazorBootExtensionJson.cs b/src/BlazorWasmSdk/Tasks/GenerateBlazorBootExtensionJson.cs
new file mode 100644
index 000000000000..266296cd64d9
--- /dev/null
+++ b/src/BlazorWasmSdk/Tasks/GenerateBlazorBootExtensionJson.cs
@@ -0,0 +1,53 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Serialization.Json;
+using System.Text;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.NET.Sdk.BlazorWebAssembly
+{
+ public class GenerateBlazorBootExtensionJson : Task
+ {
+ [Required]
+ public string OutputPath { get; set; }
+
+ public override bool Execute()
+ {
+ using var fileStream = File.Create(OutputPath);
+
+ try
+ {
+ WriteJson(fileStream);
+ }
+ catch (Exception ex)
+ {
+ Log.LogError(ex.ToString());
+ }
+
+ return !Log.HasLoggedErrors;
+ }
+
+ // Internal for tests
+ public void WriteJson(Stream output)
+ {
+ var result = new BootExtensionJsonData();
+
+ var serializer = new DataContractJsonSerializer(typeof(BootExtensionJsonData), new DataContractJsonSerializerSettings
+ {
+ UseSimpleDictionaryFormat = true
+ });
+
+ using var writer = JsonReaderWriterFactory.CreateJsonWriter(output, Encoding.UTF8, ownsStream: false, indent: true);
+ serializer.WriteObject(writer, result);
+ }
+ }
+}
diff --git a/src/BlazorWasmSdk/Tasks/GenerateBlazorWebAssemblyBootJson.cs b/src/BlazorWasmSdk/Tasks/GenerateBlazorWebAssemblyBootJson.cs
deleted file mode 100644
index 238afb02f620..000000000000
--- a/src/BlazorWasmSdk/Tasks/GenerateBlazorWebAssemblyBootJson.cs
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright (c) .NET Foundation and contributors. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.Serialization;
-using System.Runtime.Serialization.Json;
-using System.Text;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary;
-
-namespace Microsoft.NET.Sdk.BlazorWebAssembly
-{
- public class GenerateBlazorWebAssemblyBootJson : Task
- {
- [Required]
- public string AssemblyPath { get; set; }
-
- [Required]
- public ITaskItem[] Resources { get; set; }
-
- [Required]
- public bool DebugBuild { get; set; }
-
- [Required]
- public bool LinkerEnabled { get; set; }
-
- [Required]
- public bool CacheBootResources { get; set; }
-
- public bool LoadAllICUData { get; set; }
-
- public string InvariantGlobalization { get; set; }
-
- public ITaskItem[] ConfigurationFiles { get; set; }
-
- [Required]
- public string OutputPath { get; set; }
-
- public ITaskItem[] LazyLoadedAssemblies { get; set; }
-
- public override bool Execute()
- {
- using var fileStream = File.Create(OutputPath);
- var entryAssemblyName = AssemblyName.GetAssemblyName(AssemblyPath).Name;
-
- try
- {
- WriteBootJson(fileStream, entryAssemblyName);
- }
- catch (Exception ex)
- {
- Log.LogError(ex.ToString());
- }
-
- return !Log.HasLoggedErrors;
- }
-
- // Internal for tests
- public void WriteBootJson(Stream output, string entryAssemblyName)
- {
- var icuDataMode = ICUDataMode.Sharded;
-
- if (string.Equals(InvariantGlobalization, "true", StringComparison.OrdinalIgnoreCase))
- {
- icuDataMode = ICUDataMode.Invariant;
- }
- else if (LoadAllICUData)
- {
- icuDataMode = ICUDataMode.All;
- }
-
- var result = new BootJsonData
- {
- entryAssembly = entryAssemblyName,
- cacheBootResources = CacheBootResources,
- debugBuild = DebugBuild,
- linkerEnabled = LinkerEnabled,
- resources = new ResourcesData(),
- config = new List(),
- icuDataMode = icuDataMode,
- };
-
- // Build a two-level dictionary of the form:
- // - assembly:
- // - UriPath (e.g., "System.Text.Json.dll")
- // - ContentHash (e.g., "4548fa2e9cf52986")
- // - runtime:
- // - UriPath (e.g., "dotnet.js")
- // - ContentHash (e.g., "3448f339acf512448")
- if (Resources != null)
- {
- var remainingLazyLoadAssemblies = new List(LazyLoadedAssemblies ?? Array.Empty());
- var resourceData = result.resources;
- foreach (var resource in Resources)
- {
- ResourceHashesByNameDictionary resourceList = null;
-
- string behavior = null;
- var fileName = resource.GetMetadata("FileName");
- var fileExtension = resource.GetMetadata("Extension");
- var assetTraitName = resource.GetMetadata("AssetTraitName");
- var assetTraitValue = resource.GetMetadata("AssetTraitValue");
- var resourceName = Path.GetFileName(resource.GetMetadata("RelativePath"));
-
- if (TryGetLazyLoadedAssembly(resourceName, out var lazyLoad))
- {
- Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as a lazy loaded assembly.", resource.ItemSpec);
- remainingLazyLoadAssemblies.Remove(lazyLoad);
- resourceData.lazyAssembly ??= new ResourceHashesByNameDictionary();
- resourceList = resourceData.lazyAssembly;
- }
- else if (string.Equals("Culture", assetTraitName, StringComparison.OrdinalIgnoreCase))
- {
- Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as satellite assembly with culture '{1}'.", resource.ItemSpec, assetTraitValue);
- resourceData.satelliteResources ??= new Dictionary(StringComparer.OrdinalIgnoreCase);
- resourceName = assetTraitValue + "/" + resourceName;
-
- if (!resourceData.satelliteResources.TryGetValue(assetTraitValue, out resourceList))
- {
- resourceList = new ResourceHashesByNameDictionary();
- resourceData.satelliteResources.Add(assetTraitValue, resourceList);
- }
- }
- else if (string.Equals("symbol", assetTraitValue, StringComparison.OrdinalIgnoreCase))
- {
- if (TryGetLazyLoadedAssembly($"{fileName}.dll", out _))
- {
- Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as a lazy loaded symbols file.", resource.ItemSpec);
- resourceData.lazyAssembly ??= new ResourceHashesByNameDictionary();
- resourceList = resourceData.lazyAssembly;
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as symbols file.", resource.ItemSpec);
- resourceData.pdb ??= new ResourceHashesByNameDictionary();
- resourceList = resourceData.pdb;
- }
- }
- else if (string.Equals("runtime", assetTraitValue, StringComparison.OrdinalIgnoreCase))
- {
- Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as an app assembly.", resource.ItemSpec);
- resourceList = resourceData.assembly;
- }
- else if (string.Equals(assetTraitName, "BlazorWebAssemblyResource", StringComparison.OrdinalIgnoreCase) &&
- string.Equals(assetTraitValue, "native", StringComparison.OrdinalIgnoreCase))
- {
- Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as a native application resource.", resource.ItemSpec);
- if (string.Equals(fileName, "dotnet", StringComparison.OrdinalIgnoreCase) &&
- string.Equals(fileExtension, ".wasm", StringComparison.OrdinalIgnoreCase))
- {
- behavior = "dotnetwasm";
- }
-
- resourceList = resourceData.runtime;
- }
- else if (string.Equals("JSModule", assetTraitName, StringComparison.OrdinalIgnoreCase) &&
- string.Equals(assetTraitValue, "JSLibraryModule", StringComparison.OrdinalIgnoreCase))
- {
- Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as a library initializer resource.", resource.ItemSpec);
- resourceData.libraryInitializers ??= new();
- resourceList = resourceData.libraryInitializers;
- var targetPath = resource.GetMetadata("TargetPath");
- Debug.Assert(!string.IsNullOrEmpty(targetPath), "Target path for '{0}' must exist.", resource.ItemSpec);
- AddResourceToList(resource, resourceList, targetPath);
- continue;
- }
- else if (string.Equals("BlazorWebAssemblyResource", assetTraitName, StringComparison.OrdinalIgnoreCase) &&
- assetTraitValue.StartsWith("extension:", StringComparison.OrdinalIgnoreCase))
- {
- Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as an extension resource '{1}'.", resource.ItemSpec, assetTraitValue);
- var extensionName = assetTraitValue.Substring("extension:".Length);
- resourceData.extensions ??= new();
- if (!resourceData.extensions.TryGetValue(extensionName, out resourceList))
- {
- resourceList = new();
- resourceData.extensions[extensionName] = resourceList;
- }
- var targetPath = resource.GetMetadata("TargetPath");
- Debug.Assert(!string.IsNullOrEmpty(targetPath), "Target path for '{0}' must exist.", resource.ItemSpec);
- AddResourceToList(resource, resourceList, targetPath);
- continue;
- }
- else
- {
- Log.LogMessage(MessageImportance.Low, "Skipping resource '{0}' since it doesn't belong to a defined category.", resource.ItemSpec);
- // This should include items such as XML doc files, which do not need to be recorded in the manifest.
- continue;
- }
-
- if (resourceList != null)
- {
- AddResourceToList(resource, resourceList, resourceName);
- }
-
- if (!string.IsNullOrEmpty(behavior))
- {
- resourceData.runtimeAssets ??= new Dictionary();
- AddToAdditionalResources(resource, resourceData.runtimeAssets, resourceName, behavior);
- }
- }
-
- if (remainingLazyLoadAssemblies.Count > 0)
- {
- const string message = "Unable to find '{0}' to be lazy loaded later. Confirm that project or " +
- "package references are included and the reference is used in the project.";
-
- Log.LogError(
- subcategory: null,
- errorCode: "BLAZORSDK1001",
- helpKeyword: null,
- file: null,
- lineNumber: 0,
- columnNumber: 0,
- endLineNumber: 0,
- endColumnNumber: 0,
- message: message,
- string.Join(";", LazyLoadedAssemblies.Select(a => a.ItemSpec)));
-
- return;
- }
- }
-
- if (ConfigurationFiles != null)
- {
- foreach (var configFile in ConfigurationFiles)
- {
- result.config.Add(Path.GetFileName(configFile.ItemSpec));
- }
- }
-
- var serializer = new DataContractJsonSerializer(typeof(BootJsonData), new DataContractJsonSerializerSettings
- {
- UseSimpleDictionaryFormat = true
- });
-
- using var writer = JsonReaderWriterFactory.CreateJsonWriter(output, Encoding.UTF8, ownsStream: false, indent: true);
- serializer.WriteObject(writer, result);
-
- void AddResourceToList(ITaskItem resource, ResourceHashesByNameDictionary resourceList, string resourceKey)
- {
- if (!resourceList.ContainsKey(resourceKey))
- {
- Log.LogMessage(MessageImportance.Low, "Added resource '{0}' to the manifest.", resource.ItemSpec);
- resourceList.Add(resourceKey, $"sha256-{resource.GetMetadata("FileHash")}");
- }
- }
- }
-
- private void AddToAdditionalResources(ITaskItem resource, Dictionary additionalResources, string resourceName, string behavior)
- {
- if (!additionalResources.ContainsKey(resourceName))
- {
- Log.LogMessage(MessageImportance.Low, "Added resource '{0}' to the list of additional assets in the manifest.", resource.ItemSpec);
- additionalResources.Add(resourceName, new AdditionalAsset
- {
- Hash = $"sha256-{resource.GetMetadata("FileHash")}",
- Behavior = behavior
- });
- }
- }
-
- private bool TryGetLazyLoadedAssembly(string fileName, out ITaskItem lazyLoadedAssembly)
- {
- return (lazyLoadedAssembly = LazyLoadedAssemblies?.SingleOrDefault(a => a.ItemSpec == fileName)) != null;
- }
- }
-
- [DataContract]
- public class AdditionalAsset
- {
- [DataMember(Name = "hash")]
- public string Hash { get; set; }
-
- [DataMember(Name = "behavior")]
- public string Behavior { get; set; }
- }
-}
diff --git a/src/BlazorWasmSdk/Tasks/GenerateBlazorWebAssemblyBootJson50.cs b/src/BlazorWasmSdk/Tasks/GenerateBlazorWebAssemblyBootJson50.cs
index cc8b8bbeb4c0..49ba03fd3a58 100644
--- a/src/BlazorWasmSdk/Tasks/GenerateBlazorWebAssemblyBootJson50.cs
+++ b/src/BlazorWasmSdk/Tasks/GenerateBlazorWebAssemblyBootJson50.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
using System;
using System.Collections.Generic;
@@ -62,24 +63,24 @@ public override bool Execute()
// Internal for tests
public void WriteBootJson(Stream output, string entryAssemblyName)
{
- var icuDataMode = ICUDataMode.Sharded;
+ var icuDataMode = ICUDataMode50.Sharded;
if (string.Equals(InvariantGlobalization, "true", StringComparison.OrdinalIgnoreCase))
{
- icuDataMode = ICUDataMode.Invariant;
+ icuDataMode = ICUDataMode50.Invariant;
}
else if (LoadAllICUData)
{
- icuDataMode = ICUDataMode.All;
+ icuDataMode = ICUDataMode50.All;
}
- var result = new BootJsonData
+ var result = new BootJsonData50
{
entryAssembly = entryAssemblyName,
cacheBootResources = CacheBootResources,
debugBuild = DebugBuild,
linkerEnabled = LinkerEnabled,
- resources = new ResourcesData(),
+ resources = new ResourcesData50(),
config = new List(),
icuDataMode = icuDataMode,
};
@@ -159,7 +160,7 @@ public void WriteBootJson(Stream output, string entryAssemblyName)
}
}
- var serializer = new DataContractJsonSerializer(typeof(BootJsonData), new DataContractJsonSerializerSettings
+ var serializer = new DataContractJsonSerializer(typeof(BootJsonData50), new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true
});
diff --git a/src/BlazorWasmSdk/Tasks/GenerateServiceWorkerAssetsManifest.cs b/src/BlazorWasmSdk/Tasks/GenerateServiceWorkerAssetsManifest.cs
index 08c75a927af7..45ded717296f 100644
--- a/src/BlazorWasmSdk/Tasks/GenerateServiceWorkerAssetsManifest.cs
+++ b/src/BlazorWasmSdk/Tasks/GenerateServiceWorkerAssetsManifest.cs
@@ -1,5 +1,6 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
using System;
using System.IO;
diff --git a/src/BuiltInTools/BrowserRefresh/WebSocketScriptInjection.js b/src/BuiltInTools/BrowserRefresh/WebSocketScriptInjection.js
index 93d02206b1b1..74881371aa1e 100644
--- a/src/BuiltInTools/BrowserRefresh/WebSocketScriptInjection.js
+++ b/src/BuiltInTools/BrowserRefresh/WebSocketScriptInjection.js
@@ -65,7 +65,7 @@ setTimeout(async function () {
if (path && path.endsWith('.css')) {
updateCssByPath(path);
} else {
- console.debug(`File change detected to css file ${path}. Reloading page...`);
+ console.debug(`File change detected to file ${path}. Reloading page...`);
location.reload();
return;
}
diff --git a/src/BuiltInTools/dotnet-watch/CommandLineOptions.cs b/src/BuiltInTools/dotnet-watch/CommandLineOptions.cs
index 6e140fb1c8b7..794c3b65fbde 100644
--- a/src/BuiltInTools/dotnet-watch/CommandLineOptions.cs
+++ b/src/BuiltInTools/dotnet-watch/CommandLineOptions.cs
@@ -1,32 +1,285 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#nullable enable
+
using System;
using System.Collections.Generic;
+using System.CommandLine;
+using System.CommandLine.Invocation;
+using System.Linq;
+
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.DotNet.Watcher.Tools;
+using Microsoft.Extensions.Tools.Internal;
+
+namespace Microsoft.DotNet.Watcher;
+
+internal sealed class RunCommandLineOptions
+{
+ public required bool NoLaunchProfile { get; init; }
+ public required string? LaunchProfileName { get; init; }
+ public required IReadOnlyList RemainingArguments { get; init; }
+}
-namespace Microsoft.DotNet.Watcher
+internal sealed class CommandLineOptions
{
- internal class CommandLineOptions
+ private const string Description = @"
+Environment variables:
+
+ DOTNET_USE_POLLING_FILE_WATCHER
+ When set to '1' or 'true', dotnet-watch will poll the file system for
+ changes. This is required for some file systems, such as network shares,
+ Docker mounted volumes, and other virtual file systems.
+
+ DOTNET_WATCH
+ dotnet-watch sets this variable to '1' on all child processes launched.
+
+ DOTNET_WATCH_ITERATION
+ dotnet-watch sets this variable to '1' and increments by one each time
+ a file is changed and the command is restarted.
+
+ DOTNET_WATCH_SUPPRESS_EMOJIS
+ When set to '1' or 'true', dotnet-watch will not show emojis in the
+ console output.
+
+Remarks:
+ The special option '--' is used to delimit the end of the options and
+ the beginning of arguments that will be passed to the child dotnet process.
+
+ For example: dotnet watch -- --verbose run
+
+ Even though '--verbose' is an option dotnet-watch supports, the use of '--'
+ indicates that '--verbose' should be treated instead as an argument for
+ dotnet-run.
+
+Examples:
+ dotnet watch run
+ dotnet watch test
+";
+
+ private const string NoLaunchProfileOptionName = "--no-launch-profile";
+ private const string LaunchProfileOptionName = "--launch-profile";
+ private const string TargetFrameworkOptionName = "--framework";
+ private const string BuildPropertyOptionName = "--property";
+
+ public string? Project { get; init; }
+ public string? LaunchProfileName { get; init; }
+ public string? TargetFramework { get; init; }
+ public IReadOnlyList<(string name, string value)>? BuildProperties { get; init; }
+ public bool BinaryLogger { get; init; }
+ public bool NoLaunchProfile { get; init; }
+ public bool Quiet { get; init; }
+ public bool Verbose { get; init; }
+ public bool List { get; init; }
+ public bool NoHotReload { get; init; }
+ public bool NonInteractive { get; init; }
+ public required IReadOnlyList RemainingArguments { get; init; }
+ public RunCommandLineOptions? RunOptions { get; init; }
+
+ public static CommandLineOptions? Parse(string[] args, IReporter reporter, out int errorCode, System.CommandLine.IConsole? console = null)
+ {
+ var quietOption = new Option(new[] { "--quiet", "-q" }, "Suppresses all output except warnings and errors");
+ var verboseOption = new Option(new[] { "--verbose", "-v" }, "Show verbose output");
+
+ verboseOption.AddValidator(v =>
+ {
+ if (v.FindResultFor(quietOption) is not null && v.FindResultFor(verboseOption) is not null)
+ {
+ v.ErrorMessage = Resources.Error_QuietAndVerboseSpecified;
+ }
+ });
+
+ var listOption = new Option("--list", "Lists all discovered files without starting the watcher.");
+ var shortProjectOption = new Option("-p", "The project to watch.") { IsHidden = true };
+ var longProjectOption = new Option("--project", "The project to watch");
+
+ // launch profile used by dotnet-watch
+ var launchProfileWatchOption = new Option(new[] { "-lp", LaunchProfileOptionName }, "The launch profile to start the project with (case-sensitive).");
+ var noLaunchProfileWatchOption = new Option(new[] { NoLaunchProfileOptionName }, "Do not attempt to use launchSettings.json to configure the application.");
+
+ // launch profile used by dotnet-run
+ var launchProfileRunOption = new Option(new[] { "-lp", LaunchProfileOptionName }) { IsHidden = true };
+ var noLaunchProfileRunOption = new Option(new[] { NoLaunchProfileOptionName }) { IsHidden = true };
+
+ var targetFrameworkOption = new Option(new[] { "-f", "--framework" }, "The target framework to run for. The target framework must also be specified in the project file.");
+ var propertyOption = new Option(new[] { "--property" }, "Properties to be passed to MSBuild.");
+
+ propertyOption.AddValidator(v =>
+ {
+ var invalidProperty = v.GetValue(propertyOption)?.FirstOrDefault(
+ property => !(property.IndexOf('=') is > 0 and var index && index < property.Length - 1 && property[..index].Trim().Length > 0));
+
+ if (invalidProperty != null)
+ {
+ v.ErrorMessage = $"Invalid property format: '{invalidProperty}'. Expected 'name=value'.";
+ }
+ });
+
+ var noHotReloadOption = new Option("--no-hot-reload", "Suppress hot reload for supported apps.");
+ var nonInteractiveOption = new Option(
+ "--non-interactive",
+ "Runs dotnet-watch in non-interactive mode. This option is only supported when running with Hot Reload enabled. " +
+ "Use this option to prevent console input from being captured.");
+
+ var remainingWatchArgs = new Argument("forwardedArgs", "Arguments to pass to the child dotnet process.");
+ var remainingRunArgs = new Argument(name: null);
+
+ var runCommand = new Command("run") { IsHidden = true };
+ var rootCommand = new RootCommand(Description);
+ addOptions(runCommand);
+ addOptions(rootCommand);
+
+ void addOptions(Command command)
+ {
+ command.Add(quietOption);
+ command.Add(verboseOption);
+ command.Add(noHotReloadOption);
+ command.Add(nonInteractiveOption);
+ command.Add(longProjectOption);
+ command.Add(shortProjectOption);
+
+ if (command == runCommand)
+ {
+ command.Add(launchProfileRunOption);
+ command.Add(noLaunchProfileRunOption);
+ }
+ else
+ {
+ command.Add(launchProfileWatchOption);
+ command.Add(noLaunchProfileWatchOption);
+ }
+
+ command.Add(targetFrameworkOption);
+ command.Add(propertyOption);
+
+ command.Add(listOption);
+
+ if (command == runCommand)
+ {
+ command.Add(remainingRunArgs);
+ }
+ else
+ {
+ command.Add(runCommand);
+ command.Add(remainingWatchArgs);
+ }
+ };
+
+ CommandLineOptions? options = null;
+
+ runCommand.SetHandler(context =>
+ {
+ RootHandler(context, new()
+ {
+ LaunchProfileName = context.ParseResult.GetValue(launchProfileRunOption),
+ NoLaunchProfile = context.ParseResult.GetValue(noLaunchProfileRunOption),
+ RemainingArguments = context.ParseResult.GetValue(remainingRunArgs),
+ });
+ });
+
+ rootCommand.SetHandler(context => RootHandler(context, runOptions: null));
+
+ void RootHandler(InvocationContext context, RunCommandLineOptions? runOptions)
+ {
+ var parseResults = context.ParseResult;
+ var projectValue = parseResults.GetValue(longProjectOption);
+ if (string.IsNullOrEmpty(projectValue))
+ {
+ var projectShortValue = parseResults.GetValue(shortProjectOption);
+ if (!string.IsNullOrEmpty(projectShortValue))
+ {
+ reporter.Warn(Resources.Warning_ProjectAbbreviationDeprecated);
+ projectValue = projectShortValue;
+ }
+ }
+
+ options = new()
+ {
+ Quiet = parseResults.GetValue(quietOption),
+ List = parseResults.GetValue(listOption),
+ NoHotReload = parseResults.GetValue(noHotReloadOption),
+ NonInteractive = parseResults.GetValue(nonInteractiveOption),
+ Verbose = parseResults.GetValue(verboseOption),
+ Project = projectValue,
+ LaunchProfileName = parseResults.GetValue(launchProfileWatchOption),
+ NoLaunchProfile = parseResults.GetValue(noLaunchProfileWatchOption),
+ TargetFramework = parseResults.GetValue(targetFrameworkOption),
+ BuildProperties = parseResults.GetValue(propertyOption)?
+ .Select(p => (p[..p.IndexOf('=')].Trim(), p[(p.IndexOf('=') + 1)..])).ToArray(),
+ RemainingArguments = parseResults.GetValue(remainingWatchArgs),
+ RunOptions = runOptions,
+ };
+ }
+
+ errorCode = rootCommand.Invoke(args, console);
+ return options;
+ }
+
+ public IReadOnlyList GetLaunchProcessArguments(bool hotReload, IReporter reporter, out bool watchNoLaunchProfile, out string? watchLaunchProfileName)
{
- public string Project { get; set; }
- public string LaunchProfile { get; set; }
- public bool Quiet { get; set; }
- public bool Verbose { get; set; }
- public bool List { get; set; }
- public bool NoHotReload { get; set; }
+ var argsBuilder = new List();
+ if (!hotReload)
+ {
+ // Arguments are passed to dotnet and the first argument is interpreted as a command.
+ argsBuilder.Add("run");
- public bool NonInteractive { get; set; }
- public IReadOnlyList RemainingArguments { get; set; }
+ // add options that are applicable to dotnet run:
- public static bool IsPollingEnabled
+ if (TargetFramework != null)
+ {
+ argsBuilder.Add(TargetFrameworkOptionName);
+ argsBuilder.Add(TargetFramework);
+ }
+
+ if (BuildProperties != null)
+ {
+ foreach (var (name, value) in BuildProperties)
+ {
+ argsBuilder.Add(BuildPropertyOptionName);
+ argsBuilder.Add($"{name}={value}");
+ }
+ }
+ }
+
+ argsBuilder.AddRange(RemainingArguments);
+
+ // launch profile:
+ if (hotReload)
{
- get
+ watchNoLaunchProfile = NoLaunchProfile || RunOptions?.NoLaunchProfile == true;
+ watchLaunchProfileName = LaunchProfileName ?? RunOptions?.LaunchProfileName;
+
+ if (LaunchProfileName != null && RunOptions?.LaunchProfileName != null)
{
- var envVar = Environment.GetEnvironmentVariable("DOTNET_USE_POLLING_FILE_WATCHER");
- return envVar != null &&
- (envVar.Equals("1", StringComparison.OrdinalIgnoreCase) ||
- envVar.Equals("true", StringComparison.OrdinalIgnoreCase));
+ reporter.Warn($"Using launch profile name '{LaunchProfileName}', ignoring '{RunOptions.LaunchProfileName}'.");
}
}
+ else
+ {
+ var runNoLaunchProfile = (RunOptions != null) ? RunOptions.NoLaunchProfile : NoLaunchProfile;
+ watchNoLaunchProfile = NoLaunchProfile;
+
+ var runLaunchProfileName = (RunOptions != null) ? RunOptions.LaunchProfileName : LaunchProfileName;
+ watchLaunchProfileName = LaunchProfileName;
+
+ if (runNoLaunchProfile)
+ {
+ argsBuilder.Add(NoLaunchProfileOptionName);
+ }
+
+ if (runLaunchProfileName != null)
+ {
+ argsBuilder.Add(LaunchProfileOptionName);
+ argsBuilder.Add(runLaunchProfileName);
+ }
+ }
+
+ if (RunOptions != null)
+ {
+ argsBuilder.AddRange(RunOptions.RemainingArguments);
+ }
+
+ return argsBuilder.ToArray();
}
}
diff --git a/src/BuiltInTools/dotnet-watch/DotNetWatchContext.cs b/src/BuiltInTools/dotnet-watch/DotNetWatchContext.cs
index 2ffd92345ac5..b89f7ae3b51f 100644
--- a/src/BuiltInTools/dotnet-watch/DotNetWatchContext.cs
+++ b/src/BuiltInTools/dotnet-watch/DotNetWatchContext.cs
@@ -3,6 +3,8 @@
#nullable enable
+using System.Collections.Generic;
+
using Microsoft.Build.Graph;
using Microsoft.Extensions.Tools.Internal;
@@ -10,6 +12,8 @@ namespace Microsoft.DotNet.Watcher.Tools
{
internal sealed class DotNetWatchContext
{
+ public required bool HotReloadEnabled { get; init; }
+
public IReporter Reporter { get; init; } = NullReporter.Singleton;
public ProcessSpec ProcessSpec { get; init; } = default!;
@@ -29,5 +33,9 @@ internal sealed class DotNetWatchContext
public LaunchSettingsProfile LaunchSettingsProfile { get; init; } = default!;
public ProjectGraph? ProjectGraph { get; set; }
+
+ public string? TargetFramework { get; init; }
+
+ public IReadOnlyList<(string name, string value)>? BuildProperties { get; init; }
}
}
diff --git a/src/BuiltInTools/dotnet-watch/DotNetWatchOptions.cs b/src/BuiltInTools/dotnet-watch/DotNetWatchOptions.cs
index 3aeac9b8f58a..7c06cc344927 100644
--- a/src/BuiltInTools/dotnet-watch/DotNetWatchOptions.cs
+++ b/src/BuiltInTools/dotnet-watch/DotNetWatchOptions.cs
@@ -1,17 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#nullable enable
+
using System;
namespace Microsoft.DotNet.Watcher
{
+ [Flags]
+ internal enum TestFlags
+ {
+ None = 0,
+ RunningAsTest = 1 << 0,
+ BrowserRequired = 1 << 1,
+ }
+
internal sealed record DotNetWatchOptions(
bool SuppressHandlingStaticContentFiles,
bool SuppressMSBuildIncrementalism,
bool SuppressLaunchBrowser,
bool SuppressBrowserRefresh,
bool SuppressEmojis,
- bool RunningAsTest)
+ TestFlags TestFlags)
{
public static DotNetWatchOptions Default { get; } = new DotNetWatchOptions
(
@@ -20,15 +30,17 @@ internal sealed record DotNetWatchOptions(
SuppressLaunchBrowser: IsEnvironmentSet("DOTNET_WATCH_SUPPRESS_LAUNCH_BROWSER"),
SuppressBrowserRefresh: IsEnvironmentSet("DOTNET_WATCH_SUPPRESS_BROWSER_REFRESH"),
SuppressEmojis: IsEnvironmentSet("DOTNET_WATCH_SUPPRESS_EMOJIS"),
- RunningAsTest: IsEnvironmentSet("__DOTNET_WATCH_RUNNING_AS_TEST")
+ TestFlags: Environment.GetEnvironmentVariable("__DOTNET_WATCH_TEST_FLAGS") is { } value ? Enum.Parse(value) : TestFlags.None
);
public bool NonInteractive { get; set; }
+
+ public bool RunningAsTest { get => ((TestFlags & TestFlags.RunningAsTest) != TestFlags.None); }
private static bool IsEnvironmentSet(string key)
{
var envValue = Environment.GetEnvironmentVariable(key);
- return envValue == "1" || envValue == "true";
+ return envValue == "1" || string.Equals(envValue, "true", StringComparison.OrdinalIgnoreCase);
}
}
}
diff --git a/src/BuiltInTools/dotnet-watch/DotNetWatcher.cs b/src/BuiltInTools/dotnet-watch/DotNetWatcher.cs
index 7a04f379004b..64e761d909d6 100644
--- a/src/BuiltInTools/dotnet-watch/DotNetWatcher.cs
+++ b/src/BuiltInTools/dotnet-watch/DotNetWatcher.cs
@@ -21,6 +21,7 @@ internal sealed class DotNetWatcher : IAsyncDisposable
private readonly DotNetWatchOptions _dotnetWatchOptions;
private readonly StaticFileHandler _staticFileHandler;
private readonly IWatchFilter[] _filters;
+ private readonly string _muxerPath;
public DotNetWatcher(IReporter reporter, IFileSetFactory fileSetFactory, DotNetWatchOptions dotNetWatchOptions, string muxerPath)
{
@@ -30,6 +31,7 @@ public DotNetWatcher(IReporter reporter, IFileSetFactory fileSetFactory, DotNetW
_processRunner = new ProcessRunner(reporter);
_dotnetWatchOptions = dotNetWatchOptions;
_staticFileHandler = new StaticFileHandler(reporter);
+ _muxerPath = muxerPath;
_filters = new IWatchFilter[]
{
@@ -47,6 +49,7 @@ public async Task WatchAsync(DotNetWatchContext context, CancellationToken cance
cancelledTaskSource);
var processSpec = context.ProcessSpec;
+ processSpec.Executable = _muxerPath;
var initialArguments = processSpec.Arguments.ToArray();
if (context.SuppressMSBuildIncrementalism)
@@ -89,9 +92,8 @@ public async Task WatchAsync(DotNetWatchContext context, CancellationToken cance
currentRunCancellationSource.Token))
using (var fileSetWatcher = new FileSetWatcher(fileSet, _reporter))
{
+ _reporter.Verbose($"Running {processSpec.ShortDisplayName()} with the following arguments: '{string.Join(" ", processSpec.Arguments)}'");
var processTask = _processRunner.RunAsync(processSpec, combinedCancellationSource.Token);
- var args = string.Join(" ", processSpec.Arguments);
- _reporter.Verbose($"Running {processSpec.ShortDisplayName()} with the following arguments: {args}");
_reporter.Output("Started", emoji: "🚀");
@@ -104,7 +106,7 @@ public async Task WatchAsync(DotNetWatchContext context, CancellationToken cance
finishedTask = await Task.WhenAny(processTask, fileSetTask, cancelledTaskSource.Task);
if (finishedTask == fileSetTask
&& fileSetTask.Result is FileItem fileItem &&
- await _staticFileHandler.TryHandleFileChange(context, fileItem, combinedCancellationSource.Token))
+ await _staticFileHandler.TryHandleFileChange(context.BrowserRefreshServer, fileItem, combinedCancellationSource.Token))
{
// We're able to handle the file change event without doing a full-rebuild.
}
diff --git a/src/BuiltInTools/dotnet-watch/Filters/BrowserRefreshFilter.cs b/src/BuiltInTools/dotnet-watch/Filters/BrowserRefreshFilter.cs
index 625351aabc7b..fd7bd0158f7d 100644
--- a/src/BuiltInTools/dotnet-watch/Filters/BrowserRefreshFilter.cs
+++ b/src/BuiltInTools/dotnet-watch/Filters/BrowserRefreshFilter.cs
@@ -15,21 +15,21 @@ namespace Microsoft.DotNet.Watcher.Tools
{
internal sealed class BrowserRefreshFilter : IWatchFilter, IAsyncDisposable
{
- private readonly bool _suppressBrowserRefresh;
+ private readonly DotNetWatchOptions _options;
private readonly IReporter _reporter;
private readonly string _muxerPath;
private BrowserRefreshServer? _refreshServer;
- public BrowserRefreshFilter(DotNetWatchOptions dotNetWatchOptions, IReporter reporter, string muxerPath)
+ public BrowserRefreshFilter(DotNetWatchOptions options, IReporter reporter, string muxerPath)
{
- _suppressBrowserRefresh = dotNetWatchOptions.SuppressBrowserRefresh;
+ _options = options;
_reporter = reporter;
_muxerPath = muxerPath;
}
public async ValueTask ProcessAsync(DotNetWatchContext context, CancellationToken cancellationToken)
{
- if (_suppressBrowserRefresh)
+ if (_options.SuppressBrowserRefresh)
{
return;
}
@@ -51,7 +51,7 @@ public async ValueTask ProcessAsync(DotNetWatchContext context, CancellationToke
return;
}
- _refreshServer = new BrowserRefreshServer(context.Reporter, _muxerPath);
+ _refreshServer = new BrowserRefreshServer(_options, context.Reporter, _muxerPath);
context.BrowserRefreshServer = _refreshServer;
var serverUrls = string.Join(',', await _refreshServer.StartAsync(cancellationToken));
context.Reporter.Verbose($"Refresh server running at {serverUrls}.");
@@ -62,7 +62,7 @@ public async ValueTask ProcessAsync(DotNetWatchContext context, CancellationToke
context.ProcessSpec.EnvironmentVariables.DotNetStartupHooks.Add(pathToMiddleware);
context.ProcessSpec.EnvironmentVariables.AspNetCoreHostingStartupAssemblies.Add("Microsoft.AspNetCore.Watch.BrowserRefresh");
}
- else if (!_suppressBrowserRefresh)
+ else if (!_options.SuppressBrowserRefresh)
{
// We've detected a change. Notify the browser.
await (_refreshServer?.SendWaitMessageAsync(cancellationToken) ?? default);
diff --git a/src/BuiltInTools/dotnet-watch/Filters/BrowserRefreshServer.cs b/src/BuiltInTools/dotnet-watch/Filters/BrowserRefreshServer.cs
index 55ccf664888b..f0618b8dc27e 100644
--- a/src/BuiltInTools/dotnet-watch/Filters/BrowserRefreshServer.cs
+++ b/src/BuiltInTools/dotnet-watch/Filters/BrowserRefreshServer.cs
@@ -24,6 +24,9 @@
namespace Microsoft.DotNet.Watcher.Tools
{
+ ///
+ /// Communicates with aspnetcore-browser-refresh.js loaded in the browser.
+ ///
internal sealed class BrowserRefreshServer : IAsyncDisposable
{
private readonly byte[] ReloadMessage = Encoding.UTF8.GetBytes("Reload");
@@ -31,15 +34,17 @@ internal sealed class BrowserRefreshServer : IAsyncDisposable
private readonly JsonSerializerOptions _jsonSerializerOptions = new(JsonSerializerDefaults.Web);
private readonly List<(WebSocket clientSocket, string sharedSecret)> _clientSockets = new();
private readonly RSA _rsa;
+ private readonly DotNetWatchOptions _options;
private readonly IReporter _reporter;
private readonly string _muxerPath;
private readonly TaskCompletionSource _terminateWebSocket;
private readonly TaskCompletionSource _clientConnected;
private IHost _refreshServer;
- public BrowserRefreshServer(IReporter reporter, string muxerPath)
+ public BrowserRefreshServer(DotNetWatchOptions options, IReporter reporter, string muxerPath)
{
_rsa = RSA.Create(2048);
+ _options = options;
_reporter = reporter;
_muxerPath = muxerPath;
_terminateWebSocket = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -125,7 +130,25 @@ private async Task WebSocketRequest(HttpContext context)
public async Task WaitForClientConnectionAsync(CancellationToken cancellationToken)
{
- await _clientConnected.Task.WaitAsync(cancellationToken);
+ using var progressCancellationSource = new CancellationTokenSource();
+
+ var progressReportingTask = Task.Run(async () =>
+ {
+ while (!progressCancellationSource.Token.IsCancellationRequested)
+ {
+ await Task.Delay(_options.TestFlags != TestFlags.None ? TimeSpan.MaxValue : TimeSpan.FromSeconds(5), progressCancellationSource.Token);
+ _reporter.Warn("Connecting to the browser is taking longer than expected ...");
+ }
+ }, progressCancellationSource.Token);
+
+ try
+ {
+ await _clientConnected.Task.WaitAsync(cancellationToken);
+ }
+ finally
+ {
+ progressCancellationSource.Cancel();
+ }
}
public ValueTask SendJsonSerlialized(TValue value, CancellationToken cancellationToken = default)
@@ -211,7 +234,7 @@ public async ValueTask DisposeAsync()
{
var (clientSocket, _) = _clientSockets[i];
- if (clientSocket.State is not WebSocketState.Open)
+ if (clientSocket.State != WebSocketState.Open)
{
continue;
}
@@ -219,6 +242,12 @@ public async ValueTask DisposeAsync()
try
{
var result = await clientSocket.ReceiveAsync(buffer, cancellationToken);
+
+ if (result.MessageType == WebSocketMessageType.Close)
+ {
+ continue;
+ }
+
return result;
}
catch (Exception ex)
diff --git a/src/BuiltInTools/dotnet-watch/Filters/DotNetBuildFilter.cs b/src/BuiltInTools/dotnet-watch/Filters/DotNetBuildFilter.cs
index 695e1043f561..38b4444188a0 100644
--- a/src/BuiltInTools/dotnet-watch/Filters/DotNetBuildFilter.cs
+++ b/src/BuiltInTools/dotnet-watch/Filters/DotNetBuildFilter.cs
@@ -2,6 +2,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Runtime.InteropServices.Marshalling;
using System.Threading;
using System.Threading.Tasks;
@@ -29,9 +31,27 @@ public async ValueTask ProcessAsync(DotNetWatchContext context, CancellationToke
{
while (!cancellationToken.IsCancellationRequested)
{
- var arguments = context.Iteration == 0 || (context.ChangedFile?.FilePath is string changedFile && changedFile.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase)) ?
- new[] { "msbuild", "/t:Build", "/restore", "/nologo" } :
- new[] { "msbuild", "/t:Build", "/nologo" };
+ var arguments = new List()
+ {
+ "msbuild",
+ "/nologo",
+ "/t:Build"
+ };
+
+ if (context.TargetFramework != null)
+ {
+ arguments.Add($"/p:TargetFramework={context.TargetFramework}");
+ }
+
+ if (context.BuildProperties != null)
+ {
+ arguments.AddRange(context.BuildProperties.Select(p => $"/p:{p.name}={p.value}"));
+ }
+
+ if (context.Iteration == 0 || (context.ChangedFile?.FilePath is string changedFile && changedFile.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase)))
+ {
+ arguments.Add("/restore");
+ }
var processSpec = new ProcessSpec
{
diff --git a/src/BuiltInTools/dotnet-watch/Filters/LaunchBrowserFilter.cs b/src/BuiltInTools/dotnet-watch/Filters/LaunchBrowserFilter.cs
index 4886ce17e33e..8ef93d1f5c4b 100644
--- a/src/BuiltInTools/dotnet-watch/Filters/LaunchBrowserFilter.cs
+++ b/src/BuiltInTools/dotnet-watch/Filters/LaunchBrowserFilter.cs
@@ -14,8 +14,7 @@ namespace Microsoft.DotNet.Watcher.Tools
internal sealed class LaunchBrowserFilter : IWatchFilter, IAsyncDisposable
{
private static readonly Regex NowListeningRegex = new Regex(@"Now listening on: (?.*)\s*$", RegexOptions.None | RegexOptions.Compiled, TimeSpan.FromSeconds(10));
- private readonly bool _runningInTest;
- private readonly bool _suppressLaunchBrowser;
+ private readonly DotNetWatchOptions _options;
private readonly string _browserPath;
private bool _attemptedBrowserLaunch;
private Process _browserProcess;
@@ -24,16 +23,15 @@ internal sealed class LaunchBrowserFilter : IWatchFilter, IAsyncDisposable
private CancellationToken _cancellationToken;
private DotNetWatchContext _watchContext;
- public LaunchBrowserFilter(DotNetWatchOptions dotNetWatchOptions, bool allowBrowserRefreshWithoutLaunchBrowser = false)
+ public LaunchBrowserFilter(DotNetWatchOptions dotNetWatchOptions)
{
- _suppressLaunchBrowser = dotNetWatchOptions.SuppressLaunchBrowser;
- _runningInTest = dotNetWatchOptions.RunningAsTest;
+ _options = dotNetWatchOptions;
_browserPath = Environment.GetEnvironmentVariable("DOTNET_WATCH_BROWSER_PATH");
}
public ValueTask ProcessAsync(DotNetWatchContext context, CancellationToken cancellationToken)
{
- if (_suppressLaunchBrowser)
+ if (_options.SuppressLaunchBrowser)
{
return default;
}
@@ -54,6 +52,10 @@ public ValueTask ProcessAsync(DotNetWatchContext context, CancellationToken canc
context.ProcessSpec.OnOutput += (_, eventArgs) => Console.WriteLine(eventArgs.Data);
context.ProcessSpec.OnOutput += OnOutput;
}
+ else if (_options.TestFlags.HasFlag(TestFlags.BrowserRequired))
+ {
+ _reporter.Error("Test requires browser to launch");
+ }
}
return default;
@@ -118,7 +120,7 @@ private void LaunchBrowser(string launchUrl)
fileName = _browserPath;
}
- if (_runningInTest)
+ if (_options.TestFlags != TestFlags.None)
{
_reporter.Output($"Launching browser: {fileName} {args}");
return;
@@ -144,11 +146,14 @@ private static bool CanLaunchBrowser(DotNetWatchContext context, out string laun
return false;
}
- var dotnetCommand = context.ProcessSpec.Arguments.FirstOrDefault();
- if (!string.Equals(dotnetCommand, "run", StringComparison.Ordinal))
+ if (!context.HotReloadEnabled)
{
- reporter.Verbose("Browser refresh is only supported for run commands.");
- return false;
+ var dotnetCommand = context.ProcessSpec.Arguments.FirstOrDefault();
+ if (!string.Equals(dotnetCommand, "run", StringComparison.Ordinal))
+ {
+ reporter.Verbose("Browser refresh is only supported for run commands.");
+ return false;
+ }
}
if (context.LaunchSettingsProfile is not { LaunchBrowser: true })
diff --git a/src/BuiltInTools/dotnet-watch/Filters/NoRestoreFilter.cs b/src/BuiltInTools/dotnet-watch/Filters/NoRestoreFilter.cs
index 413b2c24a3c5..5701ccd86188 100644
--- a/src/BuiltInTools/dotnet-watch/Filters/NoRestoreFilter.cs
+++ b/src/BuiltInTools/dotnet-watch/Filters/NoRestoreFilter.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -17,6 +18,8 @@ internal sealed class NoRestoreFilter : IWatchFilter
public ValueTask ProcessAsync(DotNetWatchContext context, CancellationToken cancellationToken)
{
+ Debug.Assert(!context.HotReloadEnabled);
+
if (context.SuppressMSBuildIncrementalism)
{
return default;
diff --git a/src/BuiltInTools/dotnet-watch/HotReload/HotReload.cs b/src/BuiltInTools/dotnet-watch/HotReload/HotReload.cs
index 3d1ca725d37c..23a95345cef0 100644
--- a/src/BuiltInTools/dotnet-watch/HotReload/HotReload.cs
+++ b/src/BuiltInTools/dotnet-watch/HotReload/HotReload.cs
@@ -16,7 +16,7 @@ internal class HotReload : IDisposable
private readonly ScopedCssFileHandler _scopedCssFileHandler;
private readonly CompilationHandler _compilationHandler;
- public HotReload(ProcessRunner processRunner, IReporter reporter)
+ public HotReload(IReporter reporter)
{
_staticFileHandler = new StaticFileHandler(reporter);
_scopedCssFileHandler = new ScopedCssFileHandler(reporter);
@@ -36,7 +36,7 @@ public async ValueTask TryHandleFileChange(DotNetWatchContext context, Fil
for (var i = files.Length - 1; i >= 0; i--)
{
var file = files[i];
- if (await _staticFileHandler.TryHandleFileChange(context, file, cancellationToken) ||
+ if (await _staticFileHandler.TryHandleFileChange(context.BrowserRefreshServer, file, cancellationToken) ||
await _scopedCssFileHandler.TryHandleFileChange(context, file, cancellationToken))
{
fileHandlerResult = true;
diff --git a/src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs b/src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs
index 0c229f86110a..7ba62b3c4007 100644
--- a/src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs
+++ b/src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs
@@ -1,7 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using System.Collections.Generic;
+#nullable enable
+
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
@@ -23,16 +24,16 @@ public StaticFileHandler(IReporter reporter)
_reporter = reporter;
}
- public async ValueTask TryHandleFileChange(DotNetWatchContext context, FileItem file, CancellationToken cancellationToken)
+ public async ValueTask TryHandleFileChange(BrowserRefreshServer? server, FileItem file, CancellationToken cancellationToken)
{
HotReloadEventSource.Log.HotReloadStart(HotReloadEventSource.StartType.StaticHandler);
- if (!file.IsStaticFile || context.BrowserRefreshServer is null)
+ if (!file.IsStaticFile || server is null)
{
HotReloadEventSource.Log.HotReloadEnd(HotReloadEventSource.StartType.StaticHandler);
return false;
}
_reporter.Verbose($"Handling file change event for static content {file.FilePath}.");
- await HandleBrowserRefresh(context.BrowserRefreshServer, file, cancellationToken);
+ await HandleBrowserRefresh(server, file, cancellationToken);
HotReloadEventSource.Log.HotReloadEnd(HotReloadEventSource.StartType.StaticHandler);
_reporter.Output("Hot reload of static file succeeded.", emoji: "🔥");
return true;
diff --git a/src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs b/src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs
index 992d785b28c3..c4de39ff00f4 100644
--- a/src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs
+++ b/src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs
@@ -125,12 +125,11 @@ public async Task WatchAsync(DotNetWatchContext context, CancellationToken cance
try
{
- using var hotReload = new HotReload(_processRunner, _reporter);
+ using var hotReload = new HotReload(_reporter);
await hotReload.InitializeAsync(context, cancellationToken);
+ _reporter.Verbose($"Running {processSpec.ShortDisplayName()} with the following arguments: '{string.Join(" ", processSpec.Arguments)}'");
var processTask = _processRunner.RunAsync(processSpec, combinedCancellationSource.Token);
- var args = string.Join(" ", processSpec.Arguments);
- _reporter.Verbose($"Running {processSpec.ShortDisplayName()} with the following arguments: {args}");
_reporter.Output("Started", emoji: "🚀");
@@ -231,7 +230,11 @@ public async Task WatchAsync(DotNetWatchContext context, CancellationToken cance
}
catch (Exception e)
{
- _reporter.Verbose($"Caught top-level exception from hot reload: {e}");
+ if (e is not OperationCanceledException)
+ {
+ _reporter.Verbose($"Caught top-level exception from hot reload: {e}");
+ }
+
if (!currentRunCancellationSource.IsCancellationRequested)
{
currentRunCancellationSource.Cancel();
@@ -318,7 +321,7 @@ private void ConfigureExecutable(DotNetWatchContext context, ProcessSpec process
processSpec.EnvironmentVariables[rootVariableName] = Path.GetDirectoryName(_muxerPath);
}
- if (context.LaunchSettingsProfile.EnvironmentVariables is IDictionary envVariables)
+ if (context.LaunchSettingsProfile.EnvironmentVariables is { } envVariables)
{
foreach (var entry in envVariables)
{
diff --git a/src/BuiltInTools/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs b/src/BuiltInTools/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs
index 03a76fdcfe32..91fd3b8e69a9 100644
--- a/src/BuiltInTools/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs
+++ b/src/BuiltInTools/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs
@@ -7,8 +7,13 @@ namespace Microsoft.DotNet.Watcher.Internal
{
internal static class FileWatcherFactory
{
+ public static bool IsPollingEnabled
+ => Environment.GetEnvironmentVariable("DOTNET_USE_POLLING_FILE_WATCHER") is { } value &&
+ (value.Equals("1", StringComparison.OrdinalIgnoreCase) ||
+ value.Equals("true", StringComparison.OrdinalIgnoreCase));
+
public static IFileSystemWatcher CreateWatcher(string watchedDirectory)
- => CreateWatcher(watchedDirectory, CommandLineOptions.IsPollingEnabled);
+ => CreateWatcher(watchedDirectory, IsPollingEnabled);
public static IFileSystemWatcher CreateWatcher(string watchedDirectory, bool usePollingWatcher)
{
diff --git a/src/BuiltInTools/dotnet-watch/Internal/MsBuildFileSetFactory.cs b/src/BuiltInTools/dotnet-watch/Internal/MsBuildFileSetFactory.cs
index 2780ea0ef0b5..93d87ca52217 100644
--- a/src/BuiltInTools/dotnet-watch/Internal/MsBuildFileSetFactory.cs
+++ b/src/BuiltInTools/dotnet-watch/Internal/MsBuildFileSetFactory.cs
@@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#nullable enable
+
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -10,8 +12,6 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.Cli;
-using Microsoft.DotNet.Watcher.Tools;
-using Microsoft.Extensions.Tools.Internal;
using IReporter = Microsoft.Extensions.Tools.Internal.IReporter;
namespace Microsoft.DotNet.Watcher.Internal
@@ -31,42 +31,28 @@ internal sealed class MsBuildFileSetFactory : IFileSetFactory
private readonly IReadOnlyList _buildFlags;
public MsBuildFileSetFactory(
- IReporter reporter,
- DotNetWatchOptions dotNetWatchOptions,
- string muxerPath,
- string projectFile,
- bool waitOnError,
- bool trace)
- : this(dotNetWatchOptions, reporter, muxerPath, projectFile, new OutputSink(), waitOnError, trace)
- {
- }
-
- // output sink is for testing
- internal MsBuildFileSetFactory(
DotNetWatchOptions dotNetWatchOptions,
IReporter reporter,
string muxerPath,
string projectFile,
- OutputSink outputSink,
+ string? targetFramework,
+ IReadOnlyList<(string, string)>? buildProperties,
+ OutputSink? outputSink,
bool waitOnError,
bool trace)
{
- Ensure.NotNull(reporter, nameof(reporter));
- Ensure.NotNullOrEmpty(projectFile, nameof(projectFile));
- Ensure.NotNull(outputSink, nameof(outputSink));
-
_reporter = reporter;
_dotNetWatchOptions = dotNetWatchOptions;
_muxerPath = muxerPath;
_projectFile = projectFile;
- _outputSink = outputSink;
+ _outputSink = outputSink ?? new OutputSink();
_processRunner = new ProcessRunner(reporter);
- _buildFlags = InitializeArgs(FindTargetsFile(), trace);
+ _buildFlags = InitializeArgs(FindTargetsFile(), targetFramework, buildProperties, trace);
_waitOnError = waitOnError;
}
- public async Task CreateAsync(CancellationToken cancellationToken)
+ public async Task CreateAsync(CancellationToken cancellationToken)
{
var watchList = Path.GetTempFileName();
try
@@ -109,6 +95,7 @@ public async Task CreateAsync(CancellationToken cancellationToken)
{
using var watchFile = File.OpenRead(watchList);
var result = await JsonSerializer.DeserializeAsync(watchFile, cancellationToken: cancellationToken);
+ Debug.Assert(result != null);
var fileItems = new List();
foreach (var project in result.Projects)
@@ -203,7 +190,7 @@ public async Task CreateAsync(CancellationToken cancellationToken)
}
}
- private IReadOnlyList InitializeArgs(string watchTargetsFile, bool trace)
+ private IReadOnlyList InitializeArgs(string watchTargetsFile, string? targetFramework, IReadOnlyList<(string name, string value)>? buildProperties, bool trace)
{
var args = new List
{
@@ -216,6 +203,16 @@ private IReadOnlyList InitializeArgs(string watchTargetsFile, bool trace
"/p:CustomAfterMicrosoftCommonCrossTargetingTargets=" + watchTargetsFile,
};
+ if (targetFramework != null)
+ {
+ args.Add("/p:TargetFramework=" + targetFramework);
+ }
+
+ if (buildProperties != null)
+ {
+ args.AddRange(buildProperties.Select(p => $"/p:{p.name}={p.value}"));
+ }
+
if (trace)
{
// enables capturing markers to know which projects have been visited
@@ -228,6 +225,8 @@ private IReadOnlyList InitializeArgs(string watchTargetsFile, bool trace
private string FindTargetsFile()
{
var assemblyDir = Path.GetDirectoryName(typeof(MsBuildFileSetFactory).Assembly.Location);
+ Debug.Assert(assemblyDir != null);
+
var searchPaths = new[]
{
Path.Combine(AppContext.BaseDirectory, "assets"),
@@ -237,12 +236,7 @@ private string FindTargetsFile()
};
var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).FirstOrDefault(File.Exists);
- if (targetPath == null)
- {
- _reporter.Error("Fatal error: could not find DotNetWatch.targets");
- return null;
- }
- return targetPath;
+ return targetPath ?? throw new FileNotFoundException("Fatal error: could not find DotNetWatch.targets");
}
}
}
diff --git a/src/BuiltInTools/dotnet-watch/LaunchSettingsProfile.cs b/src/BuiltInTools/dotnet-watch/LaunchSettingsProfile.cs
index d4217e61a028..6582e43b198a 100644
--- a/src/BuiltInTools/dotnet-watch/LaunchSettingsProfile.cs
+++ b/src/BuiltInTools/dotnet-watch/LaunchSettingsProfile.cs
@@ -14,15 +14,12 @@ namespace Microsoft.DotNet.Watcher.Tools
{
internal sealed class LaunchSettingsProfile
{
- public string? ApplicationUrl { get; set; }
-
- public string? CommandName { get; set; }
-
- public bool LaunchBrowser { get; set; }
-
- public string? LaunchUrl { get; set; }
-
- public IDictionary? EnvironmentVariables { get; set; }
+ public string? ApplicationUrl { get; init; }
+ public string? CommandName { get; init; }
+ public bool LaunchBrowser { get; init; }
+ public string? LaunchUrl { get; init; }
+ public string? CommandLineArgs { get; init; }
+ public IReadOnlyDictionary? EnvironmentVariables { get; init; }
internal static LaunchSettingsProfile? ReadLaunchProfile(string projectDirectory, string? launchProfileName, IReporter reporter)
{
diff --git a/src/BuiltInTools/dotnet-watch/Program.cs b/src/BuiltInTools/dotnet-watch/Program.cs
index 7e0cc0819167..dc91915e9de0 100644
--- a/src/BuiltInTools/dotnet-watch/Program.cs
+++ b/src/BuiltInTools/dotnet-watch/Program.cs
@@ -1,15 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#nullable enable
+
using System;
-using System.Runtime.Loader;
using System.Collections.Generic;
-using System.CommandLine;
-using System.CommandLine.Binding;
-using System.CommandLine.Invocation;
-using System.CommandLine.Parsing;
+using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Runtime.Loader;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Graph;
@@ -18,49 +17,11 @@
using Microsoft.DotNet.Watcher.Tools;
using Microsoft.Extensions.Tools.Internal;
using IConsole = Microsoft.Extensions.Tools.Internal.IConsole;
-using Resources = Microsoft.DotNet.Watcher.Tools.Resources;
-using System.Diagnostics;
namespace Microsoft.DotNet.Watcher
{
internal sealed class Program : IDisposable
{
- private const string Description = @"
-Environment variables:
-
- DOTNET_USE_POLLING_FILE_WATCHER
- When set to '1' or 'true', dotnet-watch will poll the file system for
- changes. This is required for some file systems, such as network shares,
- Docker mounted volumes, and other virtual file systems.
-
- DOTNET_WATCH
- dotnet-watch sets this variable to '1' on all child processes launched.
-
- DOTNET_WATCH_ITERATION
- dotnet-watch sets this variable to '1' and increments by one each time
- a file is changed and the command is restarted.
-
- DOTNET_WATCH_SUPPRESS_EMOJIS
- When set to '1' or 'true', dotnet-watch will not show emojis in the
- console output.
-
-Remarks:
- The special option '--' is used to delimit the end of the options and
- the beginning of arguments that will be passed to the child dotnet process.
- Its use is optional. When the special option '--' is not used,
- dotnet-watch will use the first unrecognized argument as the beginning
- of all arguments passed into the child dotnet process.
-
- For example: dotnet watch -- --verbose run
-
- Even though '--verbose' is an option dotnet-watch supports, the use of '--'
- indicates that '--verbose' should be treated instead as an argument for
- dotnet-run.
-
-Examples:
- dotnet watch run
- dotnet watch test
-";
private readonly IConsole _console;
private readonly string _workingDirectory;
private readonly string _muxerPath;
@@ -89,6 +50,7 @@ public static async Task Main(string[] args)
try
{
var muxerPath = Environment.ProcessPath;
+ Debug.Assert(muxerPath != null);
Debug.Assert(Path.GetFileNameWithoutExtension(muxerPath) == "dotnet", $"Invalid muxer path {muxerPath}");
#if DEBUG
@@ -124,60 +86,14 @@ public static async Task Main(string[] args)
internal async Task RunAsync(string[] args)
{
- var rootCommand = CreateRootCommand(HandleWatch, _reporter);
- return await rootCommand.InvokeAsync(args);
- }
-
- internal static RootCommand CreateRootCommand(Func> handler, IReporter reporter)
- {
- var quiet = new Option(
- new[] { "--quiet", "-q" },
- "Suppresses all output except warnings and errors");
-
- var verbose = new Option(
- new[] { "--verbose", "-v" },
- "Show verbose output");
+ var options = CommandLineOptions.Parse(args, _reporter, out var errorCode);
- verbose.AddValidator(v =>
+ // an error reported or help printed:
+ if (options == null)
{
- if (v.FindResultFor(quiet) is not null && v.FindResultFor(verbose) is not null)
- {
- v.ErrorMessage = Resources.Error_QuietAndVerboseSpecified;
- }
- });
-
- var listOption = new Option("--list", "Lists all discovered files without starting the watcher.");
- var shortProjectOption = new Option("-p", "The project to watch.") { IsHidden = true };
- var longProjectOption = new Option("--project","The project to watch");
- var launchProfileOption = new Option(new[] { "-lp", "--launch-profile" }, "The launch profile to start the project with (case-sensitive). " +
- "This option is only supported when running 'dotnet watch' or 'dotnet watch run'.");
- var noHotReloadOption = new Option("--no-hot-reload", "Suppress hot reload for supported apps.");
- var nonInteractiveOption = new Option(
- "--non-interactive",
- "Runs dotnet-watch in non-interactive mode. This option is only supported when running with Hot Reload enabled. " +
- "Use this option to prevent console input from being captured.");
- var forwardedArguments = new Argument("forwardedArgs", "Arguments to pass to the child dotnet process.");
-
- var root = new RootCommand(Description)
- {
- quiet,
- verbose,
- noHotReloadOption,
- nonInteractiveOption,
- longProjectOption,
- shortProjectOption,
- launchProfileOption,
- listOption,
- forwardedArguments
- };
-
- var binder = new CommandLineOptionsBinder(longProjectOption, shortProjectOption, launchProfileOption, quiet, listOption, noHotReloadOption, nonInteractiveOption, verbose, forwardedArguments, reporter);
- root.SetHandler((CommandLineOptions options) => handler(options), binder);
- return root;
- }
+ return errorCode;
+ }
- private async Task HandleWatch(CommandLineOptions options)
- {
// update reporter as configured by options
var suppressEmojis = ShouldSuppressEmojis();
_reporter = CreateReporter(options.Verbose, options.Quiet, _console, suppressEmojis);
@@ -192,13 +108,11 @@ private async Task HandleWatch(CommandLineOptions options)
if (options.List)
{
- return await ListFilesAsync(_reporter,
- options.Project,
- _cts.Token);
+ return await ListFilesAsync(options, _reporter, _cts.Token);
}
else
{
- return await MainInternalAsync(options, _cts.Token);
+ return await RunAsync(options, _cts.Token);
}
}
catch (Exception ex)
@@ -215,7 +129,7 @@ private async Task HandleWatch(CommandLineOptions options)
}
}
- private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs args)
+ private void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs args)
{
// suppress CTRL+C on the first press
args.Cancel = !_cts.IsCancellationRequested;
@@ -228,7 +142,7 @@ private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs args)
_cts.Cancel();
}
- private async Task MainInternalAsync(CommandLineOptions options, CancellationToken cancellationToken)
+ private async Task RunAsync(CommandLineOptions options, CancellationToken cancellationToken)
{
// TODO multiple projects should be easy enough to add here
string projectFile;
@@ -242,75 +156,81 @@ private async Task MainInternalAsync(CommandLineOptions options, Cancellati
return 1;
}
- var args = options.RemainingArguments;
-
- var isDefaultRunCommand = false;
- if (args.Count == 1 && args[0] == "run")
- {
- isDefaultRunCommand = true;
- }
- else if (args.Count == 0)
- {
- isDefaultRunCommand = true;
- args = new[] { "run" };
- }
-
var watchOptions = DotNetWatchOptions.Default;
watchOptions.NonInteractive = options.NonInteractive;
var fileSetFactory = new MsBuildFileSetFactory(
- _reporter,
watchOptions,
+ _reporter,
_muxerPath,
projectFile,
+ options.TargetFramework,
+ options.BuildProperties,
+ outputSink: null,
waitOnError: true,
- trace: false);
+ trace: true);
- var processInfo = new ProcessSpec
+ if (FileWatcherFactory.IsPollingEnabled)
{
- Executable = _muxerPath,
- WorkingDirectory = Path.GetDirectoryName(projectFile),
- Arguments = args,
- EnvironmentVariables =
- {
- ["DOTNET_WATCH"] = "1"
- },
- };
+ _reporter.Output("Polling file watcher is enabled");
+ }
+
+ var projectDirectory = Path.GetDirectoryName(projectFile);
+ Debug.Assert(projectDirectory != null);
- if (CommandLineOptions.IsPollingEnabled)
+ var projectGraph = TryReadProject(projectFile, options);
+
+ bool enableHotReload;
+ if (options.NoHotReload)
{
- _reporter.Output("Polling file watcher is enabled");
+ _reporter.Verbose("Hot Reload disabled by command line switch.");
+ enableHotReload = false;
+ }
+ else if (projectGraph is null || !IsHotReloadSupported(projectGraph))
+ {
+ _reporter.Verbose("Project does not support Hot Reload.");
+ enableHotReload = false;
+ }
+ else
+ {
+ _reporter.Verbose("Watching with Hot Reload.");
+ enableHotReload = true;
}
- var launchProfile = LaunchSettingsProfile.ReadLaunchProfile(processInfo.WorkingDirectory, options.LaunchProfile, _reporter) ?? new();
+ var args = options.GetLaunchProcessArguments(enableHotReload, _reporter, out var noLaunchProfile, out var launchProfileName);
+ var launchProfile = (noLaunchProfile ? null : LaunchSettingsProfile.ReadLaunchProfile(projectDirectory, launchProfileName, _reporter)) ?? new();
+
+ // If no args forwarded to the app were specified use the ones in the profile.
+ var escapedArgs = (enableHotReload && args is []) ? launchProfile.CommandLineArgs : null;
var context = new DotNetWatchContext
{
- ProcessSpec = processInfo,
+ HotReloadEnabled = enableHotReload,
+ ProcessSpec = new ProcessSpec
+ {
+ WorkingDirectory = projectDirectory,
+ Arguments = args,
+ EscapedArguments = escapedArgs,
+ EnvironmentVariables =
+ {
+ ["DOTNET_WATCH"] = "1"
+ },
+ },
+ ProjectGraph = projectGraph,
Reporter = _reporter,
SuppressMSBuildIncrementalism = watchOptions.SuppressMSBuildIncrementalism,
LaunchSettingsProfile = launchProfile,
+ TargetFramework = options.TargetFramework,
+ BuildProperties = options.BuildProperties,
};
- context.ProjectGraph = TryReadProject(projectFile);
-
- if (!options.NoHotReload && isDefaultRunCommand && context.ProjectGraph is not null && IsHotReloadSupported(context.ProjectGraph))
+ if (enableHotReload)
{
- _reporter.Verbose($"Project supports hot reload and was configured to run with the default run-command. Watching with hot-reload");
-
- // Use hot-reload based watching if
- // a) watch was invoked with no args or with exactly one arg - the run command e.g. `dotnet watch` or `dotnet watch run`
- // b) The launch profile supports hot-reload based watching.
- // The watcher will complain if users configure this for runtimes that would not support it.
await using var watcher = new HotReloadDotNetWatcher(_reporter, _requester, fileSetFactory, watchOptions, _console, _workingDirectory, _muxerPath);
await watcher.WatchAsync(context, cancellationToken);
}
else
{
- _reporter.Verbose("Did not find a HotReloadProfile or running a non-default command. Watching with legacy behavior.");
-
- // We'll use the presence of a profile to decide if we're going to use the hot-reload based watching.
- // The watcher will complain if users configure this for runtimes that would not support it.
await using var watcher = new DotNetWatcher(_reporter, fileSetFactory, watchOptions, _muxerPath);
await watcher.WatchAsync(context, cancellationToken);
}
@@ -318,11 +238,25 @@ private async Task MainInternalAsync(CommandLineOptions options, Cancellati
return 0;
}
- private ProjectGraph TryReadProject(string project)
+ private ProjectGraph? TryReadProject(string project, CommandLineOptions options)
{
+ var globalOptions = new Dictionary();
+ if (options.TargetFramework != null)
+ {
+ globalOptions.Add("TargetFramework", options.TargetFramework);
+ }
+
+ if (options.BuildProperties != null)
+ {
+ foreach (var (name, value) in options.BuildProperties)
+ {
+ globalOptions[name] = value;
+ }
+ }
+
try
{
- return new ProjectGraph(project);
+ return new ProjectGraph(project, globalOptions);
}
catch (Exception ex)
{
@@ -353,15 +287,15 @@ private static bool IsHotReloadSupported(ProjectGraph projectGraph)
}
private async Task ListFilesAsync(
+ CommandLineOptions options,
IReporter reporter,
- string project,
CancellationToken cancellationToken)
{
// TODO multiple projects should be easy enough to add here
string projectFile;
try
{
- projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDirectory, project);
+ projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDirectory, options.Project);
}
catch (FileNotFoundException ex)
{
@@ -370,10 +304,13 @@ private async Task ListFilesAsync(
}
var fileSetFactory = new MsBuildFileSetFactory(
- reporter,
DotNetWatchOptions.Default,
+ reporter,
_muxerPath,
projectFile,
+ options.TargetFramework,
+ options.BuildProperties,
+ outputSink: null,
waitOnError: false,
trace: false);
@@ -433,74 +370,5 @@ private static void RegisterAssemblyResolutionEvents(string sdkRootDirectory)
return null;
};
}
- private sealed class CommandLineOptionsBinder : BinderBase
- {
- private readonly Option _longProjectOption;
- private readonly Option _shortProjectOption;
- private readonly Option _launchProfileOption;
- private readonly Option _quietOption;
- private readonly Option _listOption;
- private readonly Option _noHotReloadOption;
- private readonly Option _nonInteractiveOption;
- private readonly Option _verboseOption;
-
- private readonly Argument _argumentsToForward;
- private readonly IReporter _reporter;
-
- internal CommandLineOptionsBinder(
- Option longProjectOption,
- Option shortProjectOption,
- Option launchProfileOption,
- Option quietOption,
- Option listOption,
- Option noHotReloadOption,
- Option nonInteractiveOption,
- Option verboseOption,
- Argument argumentsToForward,
- IReporter reporter)
- {
- _longProjectOption = longProjectOption;
- _shortProjectOption = shortProjectOption;
- _launchProfileOption = launchProfileOption;
- _quietOption = quietOption;
- _listOption = listOption;
- _noHotReloadOption = noHotReloadOption;
- _nonInteractiveOption = nonInteractiveOption;
- _verboseOption = verboseOption;
- _argumentsToForward = argumentsToForward;
- _reporter = reporter;
- }
-
- protected override CommandLineOptions GetBoundValue(BindingContext bindingContext)
- {
- var parseResults = bindingContext.ParseResult;
- var projectValue = parseResults.GetValue(_longProjectOption);
- if (string.IsNullOrEmpty(projectValue))
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- var projectShortValue = parseResults.GetValue(_shortProjectOption);
-#pragma warning restore CS0618 // Type or member is obsolete
- if (!string.IsNullOrEmpty(projectShortValue))
- {
- _reporter.Warn(Resources.Warning_ProjectAbbreviationDeprecated);
- projectValue = projectShortValue;
- }
- }
-
- var options = new CommandLineOptions
- {
- Quiet = parseResults.GetValue(_quietOption),
- List = parseResults.GetValue(_listOption),
- NoHotReload = parseResults.GetValue(_noHotReloadOption),
- NonInteractive = parseResults.GetValue(_nonInteractiveOption),
- Verbose = parseResults.GetValue(_verboseOption),
- Project = projectValue,
- LaunchProfile = parseResults.GetValue(_launchProfileOption),
- RemainingArguments = parseResults.GetValue(_argumentsToForward),
- };
- return options;
- }
- }
}
-
}
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs
index 05090b91cec1..8d011659f565 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs
@@ -10,12 +10,14 @@ public static class Constants
public const string DefaultConfiguration = "Debug";
public static readonly string ProjectFileName = "project.json";
+ public static readonly string ToolManifestFileName = "dotnet-tools.json";
public static readonly string DotConfigDirectoryName = ".config";
public static readonly string ExeSuffix =
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
public static readonly string BinDirectoryName = "bin";
public static readonly string ObjDirectoryName = "obj";
+ public static readonly string GitDirectoryName = ".git";
public static readonly string MSBUILD_EXE_PATH = "MSBUILD_EXE_PATH";
public static readonly string MSBuildExtensionsPath = "MSBuildExtensionsPath";
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/FilePermissionSettingException.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/FilePermissionSettingException.cs
index b7aaaaba8fa8..4bd8b91339cc 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/FilePermissionSettingException.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/FilePermissionSettingException.cs
@@ -2,11 +2,9 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using System.Runtime.Serialization;
namespace Microsoft.DotNet.Cli.Utils
{
- [Serializable]
internal class FilePermissionSettingException : Exception
{
public FilePermissionSettingException()
@@ -20,9 +18,5 @@ public FilePermissionSettingException(string message) : base(message)
public FilePermissionSettingException(string message, Exception innerException) : base(message, innerException)
{
}
-
- protected FilePermissionSettingException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
}
}
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/LocalizableStrings.resx b/src/Cli/Microsoft.DotNet.Cli.Utils/LocalizableStrings.resx
index 229c4766abcc..434edc942091 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/LocalizableStrings.resx
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/LocalizableStrings.resx
@@ -1,17 +1,17 @@
-
@@ -183,4 +183,7 @@ dotnet tool install --global {1}
Using home directory '{0}' set by the '{1}' environment variable.
-
+
+ .NET workloads installed:
+
+
\ No newline at end of file
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs
index a071754d7bba..835e55bcefb2 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs
@@ -222,6 +222,7 @@ public static string GetRelativePath(string path1, string path2, char separator,
return path;
}
+ [Obsolete("Use System.IO.Path.GetFullPath(string, string) instead, or PathUtility.GetFullPath(string) if the base path is the current working directory.")]
public static string GetAbsolutePath(string basePath, string relativePath)
{
if (basePath == null)
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/UILanguageOverride.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/UILanguageOverride.cs
index edb58eb85afb..4bfb9ec667ef 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/UILanguageOverride.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/UILanguageOverride.cs
@@ -4,7 +4,9 @@
using System;
using System.Globalization;
using System.Runtime.InteropServices;
+using System.Security;
using System.Text;
+using Microsoft.Win32;
namespace Microsoft.DotNet.Cli.Utils
{
@@ -25,9 +27,8 @@ public static void Setup()
}
if (
- RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && // Encoding is only an issue on Windows
!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("en", StringComparison.InvariantCultureIgnoreCase) &&
- Environment.OSVersion.Version.Major >= 10 // UTF-8 is only officially supported on 10+.
+ CurrentPlatformIsWindowsAndOfficiallySupportsUTF8Encoding()
)
{
Console.OutputEncoding = DefaultMultilingualEncoding;
@@ -97,5 +98,31 @@ private static void SetIfNotAlreadySet(string environmentVariableName, int value
{
SetIfNotAlreadySet(environmentVariableName, value.ToString());
}
+
+ private static bool CurrentPlatformIsWindowsAndOfficiallySupportsUTF8Encoding()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version.Major >= 10) // UTF-8 is only officially supported on 10+.
+ {
+ try
+ {
+ using RegistryKey windowsVersionRegistry = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
+ var buildNumber = windowsVersionRegistry.GetValue("CurrentBuildNumber").ToString();
+ const int buildNumberThatOfficialySupportsUTF8 = 18363;
+ return int.Parse(buildNumber) >= buildNumberThatOfficialySupportsUTF8 || ForceUniversalEncodingOptInEnabled();
+ }
+ catch (Exception ex) when (ex is SecurityException || ex is ObjectDisposedException)
+ {
+ // We don't want to break those in VS on older versions of Windows with a non-en language.
+ // Allow those without registry permissions to force the encoding, however.
+ return ForceUniversalEncodingOptInEnabled();
+ }
+ }
+ return false;
+ }
+
+ private static bool ForceUniversalEncodingOptInEnabled()
+ {
+ return String.Equals(Environment.GetEnvironmentVariable("DOTNET_CLI_FORCE_UTF8_ENCODING"), "true", StringComparison.OrdinalIgnoreCase);
+ }
}
}
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.cs.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.cs.xlf
index f8c110d4f01a..3a9d3ad96a75 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.cs.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.cs.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Nesprávně naformátovaný text příkazu {0}
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.de.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.de.xlf
index f9afa89a6bf4..b45fe1739063 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.de.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.de.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Fehlerhafter Befehlstext "{0}".
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.es.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.es.xlf
index f77e887c2b58..a06d0c753e55 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.es.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.es.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Texto de comando con formato incorrecto "{0}"
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.fr.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.fr.xlf
index 6ceba12646e8..09282c62aae7 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.fr.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.fr.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Texte de commande incorrect '{0}'
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.it.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.it.xlf
index 87ec2c18edf9..7e059479060b 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.it.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.it.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Il testo del comando '{0}' non è corretto
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ja.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ja.xlf
index 5249c20c6cc5..0b06007cdad5 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ja.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ja.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
無効な形式のコマンド テキスト '{0}'
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ko.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ko.xlf
index 0d14eb2db612..437ae83f3871 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ko.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ko.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
형식이 잘못된 명령 텍스트 '{0}'
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.pl.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.pl.xlf
index 4449cff1052d..82692a7f1622 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.pl.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.pl.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Nieprawidłowo sformułowany tekst polecenia „{0}”
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.pt-BR.xlf
index e085bb22e6e2..a08b7782aa06 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.pt-BR.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.pt-BR.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Texto do comando malformado '{0}'
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ru.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ru.xlf
index 0ebf4969bd2e..cc3ea1be1b51 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ru.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.ru.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Неправильный формат текста команды "{0}"
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.tr.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.tr.xlf
index 5602fad87b49..dd79845c51ec 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.tr.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.tr.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
Hatalı biçimlendirilmiş komut metni: '{0}'
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.zh-Hans.xlf
index 50ab968bdd7e..ad7975f303e4 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.zh-Hans.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.zh-Hans.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
命令文本“{0}”格式错误
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.zh-Hant.xlf
index 41d0a2a37613..640b6fcb5077 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.zh-Hant.xlf
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.zh-Hant.xlf
@@ -2,6 +2,11 @@
+
+
+ .NET workloads installed:
+
+
命令文字 '{0}' 格式錯誤
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/AliasAssignmentCoordinator.cs b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/AliasAssignmentCoordinator.cs
index 8df21fe5c27f..e7d9c694367e 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/AliasAssignmentCoordinator.cs
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/AliasAssignmentCoordinator.cs
@@ -119,7 +119,7 @@ private static void HandleLongOverrides(
continue;
}
- // if paramater name is taken
+ // if parameter name is taken
optionName = "--param:" + longName;
if (!isAliasTaken(optionName))
{
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/SharedOptions.cs b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/SharedOptions.cs
index c305955b6799..f00c57db5cae 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/SharedOptions.cs
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/SharedOptions.cs
@@ -17,6 +17,8 @@ public static class SharedOptions
public static Option ProjectPathOption { get; } = new Option("--project", SymbolStrings.Option_ProjectPath).AcceptExistingOnly();
+ public static Option InteractiveOption { get; } = SharedOptionsFactory.CreateInteractiveOption();
+
internal static Option ForceOption { get; } = SharedOptionsFactory.CreateForceOption();
internal static Option NameOption { get; } = new Option(new string[] { "-n", "--name" })
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/create/InstantiateCommand.cs b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/create/InstantiateCommand.cs
index 2203b26f79c0..21d1f18dc5ae 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/create/InstantiateCommand.cs
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/create/InstantiateCommand.cs
@@ -221,7 +221,7 @@ private static async Task ExecuteIntAsync(
{
return HandleAmbiguousTemplateGroup(environmentSettings, templatePackageManager, selectedTemplateGroups, Reporter.Error, cancellationToken);
}
- return await HandleTemplateInstantationAsync(
+ return await HandleTemplateInstantiationAsync(
instantiateArgs,
environmentSettings,
templatePackageManager,
@@ -261,7 +261,7 @@ private static NewCommandStatus HandleAmbiguousType(
return NewCommandStatus.NotFound;
}
- private static async Task HandleTemplateInstantationAsync(
+ private static async Task HandleTemplateInstantiationAsync(
InstantiateCommandArgs args,
IEngineEnvironmentSettings environmentSettings,
TemplatePackageManager templatePackageManager,
@@ -326,11 +326,11 @@ private static NewCommandStatus HandleAmbiguousResult(
.DefineColumn(t => t.Name, LocalizableStrings.ColumnNameTemplateName, shrinkIfNeeded: true, minWidth: 15, showAlways: true)
.DefineColumn(t => string.Join(",", t.ShortNameList), LocalizableStrings.ColumnNameShortName, showAlways: true)
.DefineColumn(t => t.GetLanguage() ?? string.Empty, LocalizableStrings.ColumnNameLanguage, showAlways: true)
- .DefineColumn(t => t.Precedence.ToString(), out object? prcedenceColumn, LocalizableStrings.ColumnNamePrecedence, showAlways: true)
+ .DefineColumn(t => t.Precedence.ToString(), out object? precedenceColumn, LocalizableStrings.ColumnNamePrecedence, showAlways: true)
.DefineColumn(t => t.Author ?? string.Empty, LocalizableStrings.ColumnNameAuthor, showAlways: true, shrinkIfNeeded: true, minWidth: 10)
.DefineColumn(t => Task.Run(() => GetTemplatePackage(t)).GetAwaiter().GetResult(), LocalizableStrings.ColumnNamePackage, showAlways: true)
.OrderBy(identityColumn, StringComparer.CurrentCultureIgnoreCase)
- .OrderByDescending(prcedenceColumn, new NullOrEmptyIsLastStringComparer());
+ .OrderByDescending(precedenceColumn, new NullOrEmptyIsLastStringComparer());
reporter.WriteLine(formatter.Layout().Bold().Red());
reporter.WriteLine(LocalizableStrings.AmbiguousTemplatesMultiplePackagesHint.Bold().Red());
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/install/BaseInstallCommand.cs b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/install/BaseInstallCommand.cs
index c7f83a47c302..4c1d755b6949 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/install/BaseInstallCommand.cs
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/install/BaseInstallCommand.cs
@@ -32,7 +32,7 @@ internal BaseInstallCommand(
internal static Option ForceOption { get; } = SharedOptionsFactory.CreateForceOption().WithDescription(SymbolStrings.Option_Install_Force);
- internal virtual Option InteractiveOption { get; } = SharedOptionsFactory.CreateInteractiveOption();
+ internal virtual Option InteractiveOption { get; } = SharedOptions.InteractiveOption;
internal virtual Option AddSourceOption { get; } = SharedOptionsFactory.CreateAddSourceOption();
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/xlf/HelpStrings.ja.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/xlf/HelpStrings.ja.xlf
index fee9177ac5af..5d14b5ba20b4 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/Commands/xlf/HelpStrings.ja.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/Commands/xlf/HelpStrings.ja.xlf
@@ -24,7 +24,7 @@
- このテンプレートには、Microsoft 以外のパーティのテクノロジが含まれています。詳しくは、{0} をご覧ください。
+ このテンプレートには、Microsoft 以外のパーティのテクノロジーが含まれています。詳しくは、{0} をご覧ください。
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Priorita
@@ -283,6 +288,11 @@ Pokud si chcete zobrazit všechny aliasy, spusťte bez argumentů příkaz dotne
Soubory ke stažení
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Typ
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf
index 1e6192268d65..6b855237e712 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf
@@ -258,6 +258,11 @@ Führen Sie "dotnet {1}--show-aliases" ohne Argumente aus, um alle Aliase anzuze
Paket
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Rangfolge
@@ -283,6 +288,11 @@ Führen Sie "dotnet {1}--show-aliases" ohne Argumente aus, um alle Aliase anzuze
Downloads
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Typ
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf
index 42d81e382d88..532031d34444 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf
@@ -258,6 +258,11 @@ Ejecute "dotnet {1} --show-aliases" sin argumentos para mostrar todos los alias.
Paquete
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Precedencia
@@ -283,6 +288,11 @@ Ejecute "dotnet {1} --show-aliases" sin argumentos para mostrar todos los alias.
Descargas
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Tipo
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf
index dc25d60ad690..a70f52303eee 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf
@@ -258,6 +258,11 @@ Exécutez « dotnet {1} --show-aliases » sans arguments pour afficher tous le
Package
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Priorité
@@ -283,6 +288,11 @@ Exécutez « dotnet {1} --show-aliases » sans arguments pour afficher tous le
Téléchargements
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Type
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf
index ef4461fb36e0..c6263f2aa589 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf
@@ -258,6 +258,11 @@ Eseguire 'dotnet {1}--show-alias ' senza argomenti per mostrare tutti gli alias.
Pacchetto
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Precedenza
@@ -283,6 +288,11 @@ Eseguire 'dotnet {1}--show-alias ' senza argomenti per mostrare tutti gli alias.
Download
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Tipo
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf
index 74c93878da65..cf347b6c7c84 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf
@@ -258,6 +258,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
パッケージ
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
優先順位
@@ -283,6 +288,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
ダウンロード
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
種類
@@ -1049,7 +1059,7 @@ The header is followed by the list of parameters and their errors (might be seve
- このテンプレートには、Microsoft 以外のパーティのテクノロジが含まれています。詳しくは、{0} をご覧ください。
+ このテンプレートには、Microsoft 以外のパーティのテクノロジーが含まれています。詳しくは、{0} をご覧ください。
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf
index d790c078d771..f4caa2fdf08e 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf
@@ -258,6 +258,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
패키지
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
우선 순위
@@ -283,6 +288,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
다운로드
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
유형
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf
index 41472329ac45..2ab6a290cde0 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf
@@ -258,6 +258,11 @@ Uruchom polecenie "dotnet {1}--show-aliases" bez argumentów, aby wyświetlić w
Pakiet
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Pierwszeństwo
@@ -283,6 +288,11 @@ Uruchom polecenie "dotnet {1}--show-aliases" bez argumentów, aby wyświetlić w
Pliki do pobrania
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Typ
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf
index 4aa0bcd06c07..47167d7f38e7 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf
@@ -258,6 +258,11 @@ Execute 'dotnet {1} --mostrar- aliases' sem nenhum args para mostrar todos os al
Pacote
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Precedência
@@ -283,6 +288,11 @@ Execute 'dotnet {1} --mostrar- aliases' sem nenhum args para mostrar todos os al
Downloads
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Tipo
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf
index f366e1191f2a..52636bf1a416 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf
@@ -258,6 +258,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
Пакет
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Приоритет
@@ -283,6 +288,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
Скачивания
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Тип
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf
index da23b0994bf9..a7d717376cc4 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf
@@ -258,6 +258,11 @@ Tüm diğer adları göstermek için 'dotnet {1} --show-aliases' komutunu bağı
Paket
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
Öncellik
@@ -283,6 +288,11 @@ Tüm diğer adları göstermek için 'dotnet {1} --show-aliases' komutunu bağı
İndirilenler
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
Tür
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf
index 7c746fdaea97..cabdec4b6775 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf
@@ -258,6 +258,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
包
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
优先顺序
@@ -283,6 +288,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
下载
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
类型
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf
index ba5dfd26a5d6..bd46ed568bf0 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf
@@ -258,6 +258,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
套件
+
+
+ Package Name / Owners
+ information about NuGet package: its name and owner
+
優先順序
@@ -283,6 +288,11 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases.
下載
+
+
+ Trusted
+ information about NuGet package origin; if a package has PrefixReserved indicator
+
類型
diff --git a/src/Cli/dotnet/AutomaticEncodingRestorer.cs b/src/Cli/dotnet/AutomaticEncodingRestorer.cs
new file mode 100644
index 000000000000..4a5266de09ef
--- /dev/null
+++ b/src/Cli/dotnet/AutomaticEncodingRestorer.cs
@@ -0,0 +1,65 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.IO;
+using System.Security;
+using System.Text;
+
+namespace Microsoft.DotNet.Cli
+{
+ ///
+ /// A program can change the encoding of the console which would affect other programs.
+ /// We would prefer to have a pattern where the program does not affect encoding of other programs.
+ /// Create this class in a function akin to Main and let it manage the console encoding resources to return it to the state before execution upon destruction.
+ ///
+ internal class AutomaticEncodingRestorer : IDisposable
+ {
+ Encoding _originalOutputEncoding = null;
+ Encoding _originalInputEncoding = null;
+
+ bool outputEncodingAccessible = false;
+ bool inputEncodingAccessible = false;
+
+ public AutomaticEncodingRestorer()
+ {
+ try
+ {
+ if (!OperatingSystem.IsIOS() && !OperatingSystem.IsAndroid() && !OperatingSystem.IsTvOS()) // Output + Input Encoding are unavailable on these platforms per docs.
+ {
+ _originalOutputEncoding = Console.OutputEncoding;
+ outputEncodingAccessible = true;
+ if (!OperatingSystem.IsBrowser()) // Input Encoding is also unavailable in this platform.
+ {
+ _originalInputEncoding = Console.InputEncoding;
+ inputEncodingAccessible = true;
+ }
+ }
+ }
+ catch (Exception ex) when (ex is IOException || ex is SecurityException)
+ {
+ // The encoding is unavailable. Do nothing.
+ }
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ if (outputEncodingAccessible)
+ {
+ Console.OutputEncoding = _originalOutputEncoding;
+ }
+ if (inputEncodingAccessible)
+ {
+ Console.InputEncoding = _originalInputEncoding;
+ }
+ }
+ catch (Exception ex) when (ex is IOException || ex is SecurityException)
+ {
+ // The encoding is unavailable. Do nothing.
+ }
+ }
+ }
+}
diff --git a/src/Cli/dotnet/CommandLineInfo.cs b/src/Cli/dotnet/CommandLineInfo.cs
index 2309ecb643cd..d89bc53e619f 100644
--- a/src/Cli/dotnet/CommandLineInfo.cs
+++ b/src/Cli/dotnet/CommandLineInfo.cs
@@ -6,6 +6,7 @@
using Microsoft.DotNet.Cli.Utils;
using LocalizableStrings = Microsoft.DotNet.Cli.Utils.LocalizableStrings;
using RuntimeEnvironment = Microsoft.DotNet.Cli.Utils.RuntimeEnvironment;
+using WorkloadCommandParser = Microsoft.DotNet.Cli.WorkloadCommandParser;
namespace Microsoft.DotNet.Cli
{
@@ -30,6 +31,15 @@ public static void PrintInfo()
Reporter.Output.WriteLine($" OS Platform: {RuntimeEnvironment.OperatingSystemPlatform}");
Reporter.Output.WriteLine($" RID: {GetDisplayRid(versionFile)}");
Reporter.Output.WriteLine($" Base Path: {AppContext.BaseDirectory}");
+ PrintWorkloadsInfo();
+
+ }
+
+ private static void PrintWorkloadsInfo()
+ {
+ Reporter.Output.WriteLine();
+ Reporter.Output.WriteLine($"{LocalizableStrings.DotnetWorkloadInfoLabel}");
+ WorkloadCommandParser.ShowWorkloadsInfo();
}
private static string GetDisplayRid(DotnetVersionFile versionFile)
diff --git a/src/Cli/dotnet/CommonLocalizableStrings.resx b/src/Cli/dotnet/CommonLocalizableStrings.resx
index 7a2cfe25a05d..83f629036c43 100644
--- a/src/Cli/dotnet/CommonLocalizableStrings.resx
+++ b/src/Cli/dotnet/CommonLocalizableStrings.resx
@@ -708,4 +708,19 @@ The default is 'true' if a runtime identifier is specified.
The solution file '{0}' is missing EndProject tags or has invalid child-parent project folder mappings around project GUID: '{1}'. Manually repair the solution or try to open and save it in Visual Studio."
+
+ .NET Cli Options:
+
+
+ ARCH
+
+
+ OS
+
+
+ The artifacts path. All output from the project, including build, publish, and pack output, will go in subfolders under the specified path.
+
+
+ ARTIFACTS_DIR
+
diff --git a/src/Cli/dotnet/CommonOptions.cs b/src/Cli/dotnet/CommonOptions.cs
index 97a35ee092a4..3659607ce37c 100644
--- a/src/Cli/dotnet/CommonOptions.cs
+++ b/src/Cli/dotnet/CommonOptions.cs
@@ -51,8 +51,24 @@ public static Option FrameworkOption(string description) =>
}.ForwardAsSingle(o => $"-property:TargetFramework={o}")
.AddCompletions(Complete.TargetFrameworksFromProjectFile);
+ public static Option ArtifactsPathOption =
+ new ForwardedOption(
+ // --artifacts-path is pretty verbose, should we use --artifacts instead (or possibly support both)?
+ new string[] { "--artifacts-path" },
+ description: CommonLocalizableStrings.ArtifactsPathOptionDescription)
+ {
+ ArgumentHelpName = CommonLocalizableStrings.ArtifactsPathArgumentName
+ }.ForwardAsSingle(o => $"-property:ArtifactsPath={CommandDirectoryContext.GetFullPath(o)}");
+
private static string RuntimeArgName = CommonLocalizableStrings.RuntimeIdentifierArgumentName;
- private static Func> RuntimeArgFunc = o => new string[] { $"-property:RuntimeIdentifier={o}", "-property:_CommandLineDefinedRuntimeIdentifier=true" };
+ public static IEnumerable RuntimeArgFunc(string rid)
+ {
+ if (GetArchFromRid(rid) == "amd64")
+ {
+ rid = GetOsFromRid(rid) + "-x64";
+ }
+ return new string[] { $"-property:RuntimeIdentifier={rid}", "-property:_CommandLineDefinedRuntimeIdentifier=true" };
+ }
private static Func> RuntimeCompletions = Complete.RunTimesFromProjectFile;
public static Option RuntimeOption =
@@ -130,13 +146,17 @@ public static Argument DefaultToCurrentDirectory(this Argument a
new ForwardedOption(
new string[] { "--arch", "-a" },
CommonLocalizableStrings.ArchitectureOptionDescription)
- .SetForwardingFunction(ResolveArchOptionToRuntimeIdentifier);
+ {
+ ArgumentHelpName = CommonLocalizableStrings.ArchArgumentName
+ }.SetForwardingFunction(ResolveArchOptionToRuntimeIdentifier);
public static Option LongFormArchitectureOption =
new ForwardedOption(
new string[] { "--arch" },
CommonLocalizableStrings.ArchitectureOptionDescription)
- .SetForwardingFunction(ResolveArchOptionToRuntimeIdentifier);
+ {
+ ArgumentHelpName = CommonLocalizableStrings.ArchArgumentName
+ }.SetForwardingFunction(ResolveArchOptionToRuntimeIdentifier);
internal static string ArchOptionValue(ParseResult parseResult) =>
string.IsNullOrEmpty(parseResult.GetValue(CommonOptions.ArchitectureOption)) ?
@@ -147,7 +167,9 @@ internal static string ArchOptionValue(ParseResult parseResult) =>
new ForwardedOption(
"--os",
CommonLocalizableStrings.OperatingSystemOptionDescription)
- .SetForwardingFunction(ResolveOsOptionToRuntimeIdentifier);
+ {
+ ArgumentHelpName = CommonLocalizableStrings.OSArgumentName
+ }.SetForwardingFunction(ResolveOsOptionToRuntimeIdentifier);
public static Option DebugOption = new Option("--debug");
@@ -168,7 +190,7 @@ internal static string ArchOptionValue(ParseResult parseResult) =>
public static readonly Option TestFrameworkOption = new Option("--Framework");
- public static readonly Option TestLoggerOption = new Option("--logger");
+ public static readonly Option TestLoggerOption = new Option("--logger");
public static void ValidateSelfContainedOptions(bool hasSelfContainedOption, bool hasNoSelfContainedOption)
{
@@ -224,6 +246,7 @@ private static IEnumerable ResolveRidShorthandOptions(string os, string
internal static string ResolveRidShorthandOptionsToRuntimeIdentifier(string os, string arch)
{
var currentRid = GetCurrentRuntimeId();
+ arch = arch == "amd64" ? "x64" : arch;
os = string.IsNullOrEmpty(os) ? GetOsFromRid(currentRid) : os;
arch = string.IsNullOrEmpty(arch) ? GetArchFromRid(currentRid) : arch;
return $"{os}-{arch}";
diff --git a/src/Cli/dotnet/NuGetForwardingApp.cs b/src/Cli/dotnet/NuGetForwardingApp.cs
index e3babec48eb0..4b0d060b6121 100644
--- a/src/Cli/dotnet/NuGetForwardingApp.cs
+++ b/src/Cli/dotnet/NuGetForwardingApp.cs
@@ -19,6 +19,8 @@ public NuGetForwardingApp(IEnumerable argsToForward)
_forwardingApp = new ForwardingApp(
GetNuGetExePath(),
argsToForward);
+
+ NuGetSignatureVerificationEnabler.ConditionallyEnable(_forwardingApp);
}
public int Execute()
diff --git a/src/Cli/dotnet/NuGetSignatureVerificationEnabler.cs b/src/Cli/dotnet/NuGetSignatureVerificationEnabler.cs
new file mode 100644
index 000000000000..021f0ef24370
--- /dev/null
+++ b/src/Cli/dotnet/NuGetSignatureVerificationEnabler.cs
@@ -0,0 +1,61 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#nullable enable
+
+using System;
+using System.Runtime.InteropServices;
+using Microsoft.DotNet.Cli;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.DotNet.Tools.MSBuild;
+
+namespace Microsoft.DotNet.Tools
+{
+ public static class NuGetSignatureVerificationEnabler
+ {
+ private static readonly EnvironmentProvider s_environmentProvider = new();
+
+ internal static readonly string DotNetNuGetSignatureVerification = "DOTNET_NUGET_SIGNATURE_VERIFICATION";
+
+ public static void ConditionallyEnable(ForwardingApp forwardingApp, IEnvironmentProvider? environmentProvider = null)
+ {
+ ArgumentNullException.ThrowIfNull(forwardingApp, nameof(forwardingApp));
+
+ if (!IsLinux())
+ {
+ return;
+ }
+
+ string value = GetSignatureVerificationEnablementValue(environmentProvider);
+
+ forwardingApp.WithEnvironmentVariable(DotNetNuGetSignatureVerification, value);
+ }
+
+ public static void ConditionallyEnable(MSBuildForwardingApp forwardingApp, IEnvironmentProvider? environmentProvider = null)
+ {
+ ArgumentNullException.ThrowIfNull(forwardingApp, nameof(forwardingApp));
+
+ if (!IsLinux())
+ {
+ return;
+ }
+
+ string value = GetSignatureVerificationEnablementValue(environmentProvider);
+
+ forwardingApp.EnvironmentVariable(DotNetNuGetSignatureVerification, value);
+ }
+
+ private static string GetSignatureVerificationEnablementValue(IEnvironmentProvider? environmentProvider)
+ {
+ string? value = (environmentProvider ?? s_environmentProvider).GetEnvironmentVariable(DotNetNuGetSignatureVerification);
+
+ return string.Equals(bool.FalseString, value, StringComparison.OrdinalIgnoreCase)
+ ? bool.FalseString : bool.TrueString;
+ }
+
+ private static bool IsLinux()
+ {
+ return RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
+ }
+ }
+}
diff --git a/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs b/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs
index 5a67539a7661..cf53b576271c 100644
--- a/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs
+++ b/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs
@@ -46,7 +46,8 @@ internal class NuGetPackageDownloader : INuGetPackageDownloader
private bool _verifySignatures;
- public NuGetPackageDownloader(DirectoryPath packageInstallDir,
+ public NuGetPackageDownloader(
+ DirectoryPath packageInstallDir,
IFilePermissionSetter filePermissionSetter = null,
IFirstPartyNuGetPackageSigningVerifier firstPartyNuGetPackageSigningVerifier = null,
ILogger verboseLogger = null,
diff --git a/src/Cli/dotnet/Parser.cs b/src/Cli/dotnet/Parser.cs
index 95fde70e5db7..1b061f36f894 100644
--- a/src/Cli/dotnet/Parser.cs
+++ b/src/Cli/dotnet/Parser.cs
@@ -118,17 +118,8 @@ public static bool TokenPerLine(string tokenToReplace, out IReadOnlyList
var lines = File.ReadAllLines(filePath);
var trimmedLines =
lines
- // Remove content in the lines that contain #, starting from the point of the #
- .Select(line => {
- var hashPos = line.IndexOf('#');
- if (hashPos == -1) {
- return line;
- } else if (hashPos == 0) {
- return "";
- } else {
- return line.Substring(0, hashPos).Trim();
- }
- })
+ // Remove content in the lines that start with # after trimmer leading whitespace
+ .Select(line => line.TrimStart().StartsWith('#') ? string.Empty : line)
// trim leading/trailing whitespace to not pass along dead spaces
.Select(x => x.Trim())
// Remove empty lines
@@ -281,6 +272,28 @@ private static void SetHelpCustomizations(HelpBuilder builder)
}
}
+ public void additionalOption(HelpContext context)
+ {
+ List options = new();
+ HashSet