diff --git a/eng/Versions.props b/eng/Versions.props index cbccaa36829570..c156052dd09503 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -9,6 +9,7 @@ 8.0.100 6.0.10 + 7.0.0-rtm.22476.8 alpha 1 + <_WorkloadManifestValues Include="PackageVersionForTemplates7" Value="$(PackageVersionForTemplates7)" Condition="'$(PackageVersionNet7)' == ''" /> + <_WorkloadManifestValues Include="PackageVersionForTemplates7" Value="$(PackageVersionNet7)" Condition="'$(PackageVersionNet7)' != ''" /> + <_WorkloadManifestValues Include="EmscriptenVersion" Value="$(MicrosoftNETRuntimeEmscriptenVersion)" /> <_WorkloadManifestValues Include="NetCoreAppCurrent" Value="$(NetCoreAppCurrent)" /> diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in index de062e613b417c..6ce2373bc0c988 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in @@ -170,7 +170,7 @@ }, "Microsoft.NET.Runtime.WebAssembly.Templates.net7": { "kind": "template", - "version": "${PackageVersionNet7}", + "version": "${PackageVersionForTemplates7}", "alias-to": { "any": "Microsoft.NET.Runtime.WebAssembly.Templates" } diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 494c7fe365e271..9188f97550f9c5 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -140,6 +140,8 @@ build-dbg-proxy: $(DOTNET) build $(TOP)/src/mono/wasm/debugger/BrowserDebugHost $(MSBUILD_ARGS) build-dbg-testsuite: $(DOTNET) build $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) +build-app-host: + $(DOTNET) build $(TOP)/src/mono/wasm/host $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS) patch-deterministic: cd emsdk/upstream/emscripten/ && patch -p1 < ../../../runtime/deterministic.diff diff --git a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs index 13a4ff96ab761a..718e7f90a843df 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.Playwright; using Wasm.Tests.Internal; +using Xunit.Abstractions; namespace Wasm.Build.Tests; @@ -29,6 +30,9 @@ internal class BrowserRunner : IAsyncDisposable public Task? RunTask { get; private set; } public IList OutputLines { get; private set; } = new List(); private TaskCompletionSource _exited = new(); + private readonly ITestOutputHelper _testOutput; + + public BrowserRunner(ITestOutputHelper testOutput) => _testOutput = testOutput; // FIXME: options public async Task RunAsync(ToolCommand cmd, string args, bool headless = true) @@ -78,7 +82,7 @@ public async Task RunAsync(ToolCommand cmd, string args, bool headless = var url = new Uri(urlAvailable.Task.Result); Playwright = await Microsoft.Playwright.Playwright.CreateAsync(); string[] chromeArgs = new[] { $"--explicitly-allowed-ports={url.Port}" }; - Console.WriteLine($"Launching chrome ('{s_chromePath.Value}') via playwright with args = {string.Join(',', chromeArgs)}"); + _testOutput.WriteLine($"Launching chrome ('{s_chromePath.Value}') via playwright with args = {string.Join(',', chromeArgs)}"); Browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions{ ExecutablePath = s_chromePath.Value, Headless = headless, @@ -99,7 +103,7 @@ public async Task WaitForExitMessageAsync(TimeSpan timeout) await Task.WhenAny(RunTask!, _exited.Task, Task.Delay(timeout)); if (_exited.Task.IsCompleted) { - Console.WriteLine ($"Exited with {await _exited.Task}"); + _testOutput.WriteLine ($"Exited with {await _exited.Task}"); return; } @@ -114,7 +118,7 @@ public async Task WaitForProcessExitAsync(TimeSpan timeout) await Task.WhenAny(RunTask!, _exited.Task, Task.Delay(timeout)); if (RunTask.IsCanceled) { - Console.WriteLine ($"Exited with {(await RunTask).ExitCode}"); + _testOutput.WriteLine ($"Exited with {(await RunTask).ExitCode}"); return; } diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildEnvironment.cs b/src/mono/wasm/Wasm.Build.Tests/BuildEnvironment.cs index d8ec1e5005b5d7..f921b870375730 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BuildEnvironment.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BuildEnvironment.cs @@ -27,6 +27,7 @@ public class BuildEnvironment public static readonly string RelativeTestAssetsPath = @"..\testassets\"; public static readonly string TestAssetsPath = Path.Combine(AppContext.BaseDirectory, "testassets"); public static readonly string TestDataPath = Path.Combine(AppContext.BaseDirectory, "data"); + public static readonly string TmpPath = Path.Combine(Path.GetTempPath(), "wasmbuildtests"); private static readonly Dictionary s_runtimePackVersions = new(); @@ -141,6 +142,10 @@ public BuildEnvironment() { LogRootPath = Environment.CurrentDirectory; } + + if (Directory.Exists(TmpPath)) + Directory.Delete(TmpPath, recursive: true); + Directory.CreateDirectory(TmpPath); } // FIXME: error checks diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs index e34917b222624f..f4a73bdbb0fe5b 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs @@ -290,13 +290,25 @@ protected void InitPaths(string id) Directory.CreateDirectory(_logPath); } - protected static void InitProjectDir(string dir) + protected static void InitProjectDir(string dir, bool addNuGetSourceForLocalPackages = false) { Directory.CreateDirectory(dir); File.WriteAllText(Path.Combine(dir, "Directory.Build.props"), s_buildEnv.DirectoryBuildPropsContents); File.WriteAllText(Path.Combine(dir, "Directory.Build.targets"), s_buildEnv.DirectoryBuildTargetsContents); - File.Copy(Path.Combine(BuildEnvironment.TestDataPath, NuGetConfigFileNameForDefaultFramework), Path.Combine(dir, "nuget.config")); + string targetNuGetConfigPath = Path.Combine(dir, "nuget.config"); + if (addNuGetSourceForLocalPackages) + { + File.WriteAllText(targetNuGetConfigPath, + GetNuGetConfigWithLocalPackagesPath( + Path.Combine(BuildEnvironment.TestDataPath, NuGetConfigFileNameForDefaultFramework), + s_buildEnv.BuiltNuGetsPath)); + } + else + { + File.Copy(Path.Combine(BuildEnvironment.TestDataPath, NuGetConfigFileNameForDefaultFramework), + targetNuGetConfigPath); + } Directory.CreateDirectory(Path.Combine(dir, ".nuget")); } @@ -444,10 +456,10 @@ private static string GetNuGetConfigWithLocalPackagesPath(string templatePath, s return contents.Replace(s_nugetInsertionTag, $@""); } - public string CreateWasmTemplateProject(string id, string template = "wasmbrowser") + public string CreateWasmTemplateProject(string id, string template = "wasmbrowser", string extraArgs = "") { InitPaths(id); - InitProjectDir(id); + InitProjectDir(id, addNuGetSourceForLocalPackages: true); File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.props"), ""); File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.targets"), @@ -464,7 +476,7 @@ public string CreateWasmTemplateProject(string id, string template = "wasmbrowse new DotNetCommand(s_buildEnv, _testOutput, useDefaultArgs: false) .WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"new {template}") + .ExecuteWithCapturedOutput($"new {template} {extraArgs}") .EnsureSuccessful(); return Path.Combine(_projectDir!, $"{id}.csproj"); diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs index e96ed8b797e8c5..02f223e27e3242 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs @@ -185,10 +185,19 @@ public void ConsoleBuildThenPublish(string config) [InlineData("Debug", true)] [InlineData("Release", false)] [InlineData("Release", true)] - public void ConsoleBuildAndRun(string config, bool relinking) + public void ConsoleBuildAndRunDefault(string config, bool relinking) + => ConsoleBuildAndRun(config, relinking, string.Empty); + + [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))] + [InlineData("Debug", "-f net7.0")] + [InlineData("Debug", "-f net8.0")] + public void ConsoleBuildAndRunForSpecificTFM(string config, string extraNewArgs) + => ConsoleBuildAndRun(config, false, extraNewArgs); + + private void ConsoleBuildAndRun(string config, bool relinking, string extraNewArgs) { string id = $"{config}_{Path.GetRandomFileName()}"; - string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); + string projectFile = CreateWasmTemplateProject(id, "wasmconsole", extraNewArgs); string projectName = Path.GetFileNameWithoutExtension(projectFile); UpdateProgramCS(); @@ -234,9 +243,9 @@ void AddTestData(bool forConsole, bool runOutsideProjectDirectory) //data.Add(runOutsideProjectDirectory, forConsole, string.Empty); data.Add(runOutsideProjectDirectory, forConsole, - $"{Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())}"); + $"{Path.Combine(BuildEnvironment.TmpPath, Path.GetRandomFileName())}"); data.Add(runOutsideProjectDirectory, forConsole, - $"{Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())}"); + $"{Path.Combine(BuildEnvironment.TmpPath, Path.GetRandomFileName())}"); } return data; @@ -259,13 +268,13 @@ private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, st if (!string.IsNullOrEmpty(extraProperties)) AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties); - string workingDir = runOutsideProjectDirectory ? Path.GetTempPath() : _projectDir!; + string workingDir = runOutsideProjectDirectory ? BuildEnvironment.TmpPath : _projectDir!; { using var runCommand = new RunCommand(s_buildEnv, _testOutput) .WithWorkingDirectory(workingDir); - await using var runner = new BrowserRunner(); + await using var runner = new BrowserRunner(_testOutput); var page = await runner.RunAsync(runCommand, $"run -c {config} --project {projectFile} --forward-console"); await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2)); Assert.Contains("Hello, Browser!", string.Join(Environment.NewLine, runner.OutputLines)); @@ -275,7 +284,7 @@ private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, st using var runCommand = new RunCommand(s_buildEnv, _testOutput) .WithWorkingDirectory(workingDir); - await using var runner = new BrowserRunner(); + await using var runner = new BrowserRunner(_testOutput); var page = await runner.RunAsync(runCommand, $"run -c {config} --no-build --project {projectFile} --forward-console"); await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2)); Assert.Contains("Hello, Browser!", string.Join(Environment.NewLine, runner.OutputLines)); @@ -293,7 +302,7 @@ private Task ConsoleRunWithAndThenWithoutBuildAsync(string config, string extraP if (!string.IsNullOrEmpty(extraProperties)) AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties); - string workingDir = runOutsideProjectDirectory ? Path.GetTempPath() : _projectDir!; + string workingDir = runOutsideProjectDirectory ? BuildEnvironment.TmpPath : _projectDir!; { string runArgs = $"run -c {config} --project {projectFile}"; @@ -420,7 +429,7 @@ public async Task BlazorRunTest() using var runCommand = new RunCommand(s_buildEnv, _testOutput) .WithWorkingDirectory(_projectDir!); - await using var runner = new BrowserRunner(); + await using var runner = new BrowserRunner(_testOutput); var page = await runner.RunAsync(runCommand, $"run -c {config} --no-build"); await page.Locator("text=Counter").ClickAsync(); @@ -432,12 +441,15 @@ public async Task BlazorRunTest() Assert.Equal("Current count: 1", txt); } - [ConditionalFact(typeof(BuildTestBase), nameof(IsUsingWorkloads))] - public async Task BrowserTest() + [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))] + [InlineData("")] + [InlineData("-f net7.0")] + [InlineData("-f net8.0")] + public async Task BrowserBuildAndRun(string extraNewArgs) { string config = "Debug"; string id = $"browser_{config}_{Path.GetRandomFileName()}"; - CreateWasmTemplateProject(id, "wasmbrowser"); + CreateWasmTemplateProject(id, "wasmbrowser", extraNewArgs); UpdateBrowserMainJs(DefaultTargetFramework); @@ -449,7 +461,7 @@ public async Task BrowserTest() using var runCommand = new RunCommand(s_buildEnv, _testOutput) .WithWorkingDirectory(_projectDir!); - await using var runner = new BrowserRunner(); + await using var runner = new BrowserRunner(_testOutput); var page = await runner.RunAsync(runCommand, $"run -c {config} --no-build -r browser-wasm --forward-console"); await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2)); Assert.Contains("Hello, Browser!", string.Join(Environment.NewLine, runner.OutputLines)); diff --git a/src/mono/wasm/debugger/BrowserDebugHost/DebugProxyHost.cs b/src/mono/wasm/debugger/BrowserDebugHost/DebugProxyHost.cs index be3095eeffc74a..b97ffe7ef0fc78 100644 --- a/src/mono/wasm/debugger/BrowserDebugHost/DebugProxyHost.cs +++ b/src/mono/wasm/debugger/BrowserDebugHost/DebugProxyHost.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.IO; using System.Runtime.ExceptionServices; diff --git a/src/mono/wasm/host/BrowserHost.cs b/src/mono/wasm/host/BrowserHost.cs index f546127426cd2f..a592ca7386fff3 100644 --- a/src/mono/wasm/host/BrowserHost.cs +++ b/src/mono/wasm/host/BrowserHost.cs @@ -71,9 +71,9 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke debugging: _args.CommonConfig.Debugging); runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json")); - var urls = new string[] { $"http://localhost:{_args.CommonConfig.HostProperties.WebServerPort}", "https://localhost:0" }; - if (envVars["ASPNETCORE_URLS"] is not null) - urls = envVars["ASPNETCORE_URLS"].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + string[] urls = envVars.TryGetValue("ASPNETCORE_URLS", out string? aspnetUrls) + ? aspnetUrls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries) + : new string[] { $"http://127.0.0.1:{_args.CommonConfig.HostProperties.WebServerPort}", "https://127.0.0.1:0" }; (ServerURLs serverURLs, IWebHost host) = await StartWebServerAsync(_args.CommonConfig.AppPath, _args.ForwardConsoleOutput ?? false, diff --git a/src/mono/wasm/host/WebServer.cs b/src/mono/wasm/host/WebServer.cs index aed1948470334c..44d024320025cf 100644 --- a/src/mono/wasm/host/WebServer.cs +++ b/src/mono/wasm/host/WebServer.cs @@ -1,13 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -20,7 +16,7 @@ public class WebServer { internal static async Task<(ServerURLs, IWebHost)> StartAsync(WebServerOptions options, ILogger logger, CancellationToken token) { - string[] urls = options.Urls; + TaskCompletionSource realUrlsAvailableTcs = new(); IWebHostBuilder builder = new WebHostBuilder() .UseKestrel() @@ -43,9 +39,10 @@ public class WebServer } services.AddSingleton(logger); services.AddSingleton(Options.Create(options)); + services.AddSingleton(realUrlsAvailableTcs); services.AddRouting(); }) - .UseUrls(urls); + .UseUrls(options.Urls); if (options.ContentRootPath != null) builder.UseContentRoot(options.ContentRootPath); @@ -53,27 +50,11 @@ public class WebServer IWebHost? host = builder.Build(); await host.StartAsync(token); - ICollection? addresses = host.ServerFeatures - .Get()? - .Addresses; + if (token.CanBeCanceled) + token.Register(async () => await host.StopAsync()); - string? ipAddress = - addresses? - .Where(a => a.StartsWith("http:", StringComparison.InvariantCultureIgnoreCase)) - .Select(a => new Uri(a)) - .Select(uri => uri.ToString()) - .FirstOrDefault(); - - string? ipAddressSecure = - addresses? - .Where(a => a.StartsWith("https:", StringComparison.OrdinalIgnoreCase)) - .Select(a => new Uri(a)) - .Select(uri => uri.ToString()) - .FirstOrDefault(); - - return ipAddress == null || ipAddressSecure == null - ? throw new InvalidOperationException("Failed to determine web server's IP address or port") - : (new ServerURLs(ipAddress, ipAddressSecure), host); + ServerURLs serverUrls = await realUrlsAvailableTcs.Task; + return (serverUrls, host); } } diff --git a/src/mono/wasm/host/WebServerStartup.cs b/src/mono/wasm/host/WebServerStartup.cs index e09cdd61963fb2..64bf9e7cccbac5 100644 --- a/src/mono/wasm/host/WebServerStartup.cs +++ b/src/mono/wasm/host/WebServerStartup.cs @@ -5,19 +5,20 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Net; +using System.Linq; using System.Net.WebSockets; -using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Web; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Microsoft.WebAssembly.Diagnostics; #nullable enable @@ -28,6 +29,7 @@ internal sealed class WebServerStartup private readonly IWebHostEnvironment _hostingEnvironment; private static readonly object LaunchLock = new object(); private static string LaunchedDebugProxyUrl = ""; + private ILogger? _logger; public WebServerStartup(IWebHostEnvironment hostingEnvironment) => _hostingEnvironment = hostingEnvironment; public static int StartDebugProxy(string devToolsHost) @@ -52,8 +54,13 @@ public static int StartDebugProxy(string devToolsHost) return generateRandomPort; } - public void Configure(IApplicationBuilder app, IOptions optionsContainer) + public void Configure(IApplicationBuilder app, + IOptions optionsContainer, + TaskCompletionSource realUrlsAvailableTcs, + ILogger logger, + IHostApplicationLifetime applicationLifetime) { + _logger = logger; var provider = new FileExtensionContentTypeProvider(); provider.Mappings[".wasm"] = "application/wasm"; provider.Mappings[".cjs"] = "text/javascript"; @@ -144,5 +151,43 @@ public void Configure(IApplicationBuilder app, IOptions option return Task.CompletedTask; }); }); + + + applicationLifetime.ApplicationStarted.Register(() => + { + TaskCompletionSource tcs = realUrlsAvailableTcs; + try + { + ICollection? addresses = app.ServerFeatures + .Get() + ?.Addresses; + + string? ipAddress = null; + string? ipAddressSecure = null; + if (addresses is not null) + { + ipAddress = GetHttpServerAddress(addresses, secure: false); + ipAddressSecure = GetHttpServerAddress(addresses, secure: true); + } + + if (ipAddress == null) + tcs.SetException(new InvalidOperationException("Failed to determine web server's IP address or port")); + else + tcs.SetResult(new ServerURLs(ipAddress, ipAddressSecure)); + } + catch (Exception ex) + { + _logger?.LogError($"Failed to get urls for the webserver: {ex}"); + tcs.TrySetException(ex); + throw; + } + + static string? GetHttpServerAddress(ICollection addresses, bool secure) + => addresses? + .Where(a => a.StartsWith(secure ? "https:" : "http:", StringComparison.InvariantCultureIgnoreCase)) + .Select(a => new Uri(a)) + .Select(uri => uri.ToString()) + .FirstOrDefault(); + }); } } diff --git a/src/mono/wasm/templates/templates/browser/.template.config/template.json b/src/mono/wasm/templates/templates/browser/.template.config/template.json index 5fa2bac372a72f..902e5d4622b954 100644 --- a/src/mono/wasm/templates/templates/browser/.template.config/template.json +++ b/src/mono/wasm/templates/templates/browser/.template.config/template.json @@ -3,7 +3,10 @@ "author": "Microsoft", "classifications": [ "Web", "WebAssembly", "Browser" ], "generatorVersions": "[1.0.0.0-*)", - "identity": "WebAssembly.Browser", + "groupIdentity": "WebAssembly.Browser", + "precedence": 8000, + "identity": "WebAssembly.Browser.8.0", + "description": "WebAssembly Browser App", "name": "WebAssembly Browser App", "shortName": "wasmbrowser", "sourceName": "browser.0", @@ -20,7 +23,7 @@ "low": 5000, "high": 5300 }, - "replaces": "5000" + "replaces": "5000" }, "kestrelHttpsPortGenerated": { "type": "generated", @@ -29,7 +32,21 @@ "low": 7000, "high": 7300 }, - "replaces": "5001" + "replaces": "5001" + }, + "framework": { + "type": "parameter", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "net8.0", + "description": "Target net8.0", + "displayName": ".NET 8.0" + } + ], + "defaultValue": "net8.0", + "displayName": "framework" } } } diff --git a/src/mono/wasm/templates/templates/console/.template.config/template.json b/src/mono/wasm/templates/templates/console/.template.config/template.json index 8ead39edc0f8c2..d2a453e1272211 100644 --- a/src/mono/wasm/templates/templates/console/.template.config/template.json +++ b/src/mono/wasm/templates/templates/console/.template.config/template.json @@ -2,7 +2,10 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "Web", "WebAssembly", "Console" ], - "identity": "WebAssembly.Console", + "groupIdentity": "WebAssembly.Console", + "precedence": 8000, + "identity": "WebAssembly.Console.8.0", + "description": "WebAssembly Console App", "name": "WebAssembly Console App", "shortName": "wasmconsole", "sourceName": "console.0", @@ -10,5 +13,21 @@ "tags": { "language": "C#", "type": "project" + }, + "symbols": { + "framework": { + "type": "parameter", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "net8.0", + "description": "Target net8.0", + "displayName": ".NET 8.0" + } + ], + "defaultValue": "net8.0", + "displayName": "framework" + } } } diff --git a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs index d8793586273fbb..94e255df990ed2 100644 --- a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs +++ b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs @@ -97,9 +97,14 @@ public override bool Execute() } string cachePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + string lastTargetPath = string.Empty; foreach (InstallWorkloadRequest req in selectedRequests) { - Log.LogMessage(MessageImportance.High, $"** Installing workload {req.WorkloadId} in {req.TargetPath} **"); + if (req.TargetPath != lastTargetPath) + Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Preparing {req.TargetPath} **"); + lastTargetPath = req.TargetPath; + + Log.LogMessage(MessageImportance.High, $" - {req.WorkloadId}: Installing workload"); if (!req.Validate(Log)) return false; @@ -159,11 +164,11 @@ private bool InstallAllManifests() if (manifestsInstalled.Contains(req.ManifestName)) { - Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Manifests for workload {req.WorkloadId} are already installed **{Environment.NewLine}"); + Log.LogMessage(MessageImportance.High, $"** {req.WorkloadId}: Manifests are already installed **"); continue; } - Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Installing manifests for workload {req.WorkloadId} **"); + Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** {req.WorkloadId}: Installing manifests **"); if (!InstallWorkloadManifest(workload, req.ManifestName, req.Version, @@ -230,13 +235,13 @@ private bool InstallPacks(InstallWorkloadRequest req, string nugetConfigContents Path.Combine(req.TargetPath, "dotnet"), $"workload install --skip-manifest-update --no-cache --configfile \"{nugetConfigPath}\" {req.WorkloadId}", workingDir: Path.GetTempPath(), - silent: false, logStdErrAsMessage: req.IgnoreErrors, - debugMessageImportance: MessageImportance.High); + debugMessageImportance: MessageImportance.Normal); if (exitCode != 0) { if (req.IgnoreErrors) { + Log.LogMessage(MessageImportance.High, output); Log.LogMessage(MessageImportance.High, $"{Environment.NewLine} ** Ignoring workload installation failure exit code {exitCode}. **{Environment.NewLine}"); } @@ -245,6 +250,7 @@ private bool InstallPacks(InstallWorkloadRequest req, string nugetConfigContents Log.LogError($"workload install failed with exit code {exitCode}: {output}"); } + Log.LogMessage(MessageImportance.Low, $"List of the relevant paths in {req.TargetPath}"); foreach (string dir in Directory.EnumerateDirectories(Path.Combine(req.TargetPath, "sdk-manifests"), "*", SearchOption.AllDirectories)) Log.LogMessage(MessageImportance.Low, $"\t{Path.Combine(req.TargetPath, "sdk-manifests", dir)}"); @@ -257,7 +263,7 @@ private bool InstallPacks(InstallWorkloadRequest req, string nugetConfigContents private void UpdateAppRef(string sdkPath, string version) { - Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Updating Targeting pack **{Environment.NewLine}"); + Log.LogMessage(MessageImportance.Normal, $" - Updating Targeting pack"); string pkgPath = Path.Combine(LocalNuGetsPath, $"Microsoft.NETCore.App.Ref.{version}.nupkg"); if (!File.Exists(pkgPath)) @@ -291,7 +297,7 @@ private string GetNuGetConfig() private bool InstallWorkloadManifest(ITaskItem workloadId, string name, string version, string sdkDir, string nugetConfigContents, bool stopOnMissing) { - Log.LogMessage(MessageImportance.High, $" ** Installing manifest: {name}/{version}"); + Log.LogMessage(MessageImportance.High, $" - Installing manifest: {name}/{version}"); // Find any existing directory with the manifest name, ignoring the case // Multiple directories for a manifest, differing only in case causes