[wasm] Move some defaults out of the templates (#72626)
authorLarry Ewing <lewing@microsoft.com>
Mon, 25 Jul 2022 21:08:25 +0000 (16:08 -0500)
committerGitHub <noreply@github.com>
Mon, 25 Jul 2022 21:08:25 +0000 (16:08 -0500)
* Move some defaults out of the template
* Fix build for template tests, and satellite assembly tests

- Running with `node` fails when relinking, or AOT'ing in Debug config
- this seems to be when linking is done with `-O0`
  - it seems to work fine with emsdk `3.1.7` though
  - For `Debug` config we automatically set `_WasmDevel=true`, which
  then sets `-O0`

  - This is not seen on CI, since we don't run non-template tests in
  `Debug`. But for local runs, we do.
  - The template tests are explicitly run for Debug, and Release, and
  they break because of this
  - So, setting `_WasmDevel=false` for now, till this gets fixed

- Also, set `OutputType=Exe` in the project file itself, so it gets set
before `Microsoft.NET.Sdk` gets imported, or early enough.

* Wasm.Build.Tests: add relinking tests for templates

* Revert unintended change

* Fix WasmTemplateTests on windows

* Wasm.Build.Tests: Explicitly allow web server port in chrome, on windows

Fixes https://github.com/dotnet/runtime/issues/72436

Co-authored-by: Ankit Jain <radical@gmail.com>
12 files changed:
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Microsoft.NET.Runtime.WebAssembly.Sdk.pkgproj
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/AutoImport.props
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props [new file with mode: 0644]
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.targets.in
src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in
src/mono/wasm/build/WasmApp.Native.targets
src/mono/wasm/templates/templates/browser/browser.0.csproj
src/mono/wasm/templates/templates/console/console.0.csproj
src/tests/BuildWasmApps/Wasm.Build.Tests/BrowserRunner.cs
src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs
src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs
src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs

index 1a864b3..ec82f4d 100644 (file)
@@ -11,6 +11,7 @@
     <ProjectReference Include="$(RepoRoot)src\mono\wasm\host\WasmAppHost.csproj" />
 
     <PackageFile Include="Sdk\AutoImport.props" TargetPath="Sdk" />
+    <PackageFile Include="Sdk\Sdk.props" TargetPath="Sdk" />
     <PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.props" TargetPath="Sdk" />
     <PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.targets" TargetPath="Sdk" />
     <PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.Native.*" TargetPath="Sdk" />
index f29ea9a..9831506 100644 (file)
@@ -2,4 +2,4 @@
   <PropertyGroup>
     <WasmNativeWorkload>true</WasmNativeWorkload>
   </PropertyGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props b/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props
new file mode 100644 (file)
index 0000000..2890daa
--- /dev/null
@@ -0,0 +1,9 @@
+<Project>
+  <PropertyGroup Condition="'$(UsingMicrosoftNETSdkBlazorWebAssembly)' != 'true'">
+    <TargetArchitecture>wasm</TargetArchitecture>
+    <TargetOS>browser</TargetOS>
+    <UseMonoRuntime>true</UseMonoRuntime>
+    <OutputType>Exe</OutputType>
+    <PublishTrimmed Condition="'$(PublishTrimmed)' == ''">true</PublishTrimmed>
+  </PropertyGroup>
+</Project>
index a6a33a5..0f9edfb 100644 (file)
@@ -7,6 +7,9 @@
     <WasmAppBuilderTasksAssemblyPath>$(_TasksDir)WasmAppBuilder.dll</WasmAppBuilderTasksAssemblyPath>
     <WasmBuildTasksAssemblyPath>$(_TasksDir)WasmBuildTasks.dll</WasmBuildTasksAssemblyPath>
     <WasmAppHostDir>$([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), '..', 'WasmAppHost'))</WasmAppHostDir>
+
+    <!-- only for non-blazor projects -->
+    <WasmEmitSymbolMap Condition="'$(UsingMicrosoftNETSdkBlazorWebAssembly)' != 'true' and '$(WasmEmitSymbolMap)' == '' and '$(RunAOTCompilation)' != 'true'">true</WasmEmitSymbolMap>
   </PropertyGroup>
 
   <Import Project="$(MSBuildThisFileDirectory)\WasmApp.props" />
index df6b5c9..be11ba3 100644 (file)
@@ -80,6 +80,7 @@
 
     <ImportGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm' and '$(UsingBrowserRuntimeWorkload)' == 'true'">
         <Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.MonoTargets.Sdk" />
+        <Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.WebAssembly.Sdk" />
         <Import Project="Sdk.targets" Sdk="Microsoft.NET.Runtime.WebAssembly.Sdk" />
         <Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.browser-wasm" />
         <Import Project="Sdk.targets" Sdk="Microsoft.NET.Runtime.MonoTargets.Sdk" />
index 97cd008..b20f012 100644 (file)
 
       <_DriverGenCNeeded Condition="'$(_DriverGenCNeeded)' == '' and '$(_WasmShouldAOT)' == 'true'">true</_DriverGenCNeeded>
 
-      <_WasmDevel Condition="'$(WasmBuildNative)' == 'true' and '$(Configuration)' == 'Debug'">true</_WasmDevel>
+      <_WasmDevel Condition="'$(_WasmDevel)' == '' and '$(WasmBuildNative)' == 'true' and '$(Configuration)' == 'Debug'">true</_WasmDevel>
 
       <_EmccAssertionLevelDefault Condition="'$(_EmccAssertionLevelDefault)' == ''">0</_EmccAssertionLevelDefault>
-      <_EmccOptimizationFlagDefault Condition="'$(_WasmDevel)' == 'true'">-O0 -s ASSERTIONS=$(_EmccAssertionLevelDefault)</_EmccOptimizationFlagDefault>
+      <_EmccOptimizationFlagDefault Condition="'$(_WasmDevel)' == 'true'">-O0</_EmccOptimizationFlagDefault>
       <_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(Configuration)' == 'Debug' and '$(WasmBuildingForNestedPublish)' != 'true'">-O1</_EmccOptimizationFlagDefault>
       <_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == ''">-Oz</_EmccOptimizationFlagDefault>
 
 
       <!-- Adding optimization flag at the top, so it gets precedence -->
       <_EmccCFlags Include="$(EmccCompileOptimizationFlag)" />
+      <_EmccCFlags Include="-s ASSERTIONS=$(_EmccAssertionLevelDefault)" Condition="'$(_WasmDevel)' == 'true'" />
       <_EmccCFlags Include="@(_EmccCommonFlags)" />
 
       <_EmccCFlags Include="-DDISABLE_PERFTRACING_LISTEN_PORTS=1" />
 
       <!-- Adding optimization flag at the top, so it gets precedence -->
       <_EmccLDFlags Include="$(EmccLinkOptimizationFlag)" />
+      <_EmccLDFlags Include="-s ASSERTIONS=$(_EmccAssertionLevelDefault)" Condition="'$(_WasmDevel)' == 'true'" />
       <_EmccLDFlags Include="@(_EmccCommonFlags)" />
       <_EmccLDFlags Include="-Wl,--allow-undefined" />
       <_EmccLDSFlags Include="-s INITIAL_MEMORY=$(EmccInitialHeapSize)" />
index 9b49cb0..cce0b07 100644 (file)
@@ -1,14 +1,9 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>net7.0</TargetFramework>
-    <TargetArchitecture>wasm</TargetArchitecture>
-    <TargetOS>browser</TargetOS>
     <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
-    <UseMonoRuntime>true</UseMonoRuntime>
     <WasmMainJSPath>main.js</WasmMainJSPath>
     <OutputType>Exe</OutputType>
-    <PublishTrimmed>true</PublishTrimmed>
-    <WasmEmitSymbolMap Condition="'$(RunAOTCompilation)' != 'true'">true</WasmEmitSymbolMap>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
 
index b2ebf81..2d83290 100644 (file)
@@ -1,14 +1,9 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>net7.0</TargetFramework>
-    <TargetArchitecture>wasm</TargetArchitecture>
-    <TargetOS>browser</TargetOS>
     <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
-    <UseMonoRuntime>true</UseMonoRuntime>
     <WasmMainJSPath>main.mjs</WasmMainJSPath>
     <OutputType>Exe</OutputType>
-    <PublishTrimmed>true</PublishTrimmed>
-    <WasmEmitSymbolMap Condition="'$(RunAOTCompilation)' != 'true'">true</WasmEmitSymbolMap>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
 
index b80ab48..c39818f 100644 (file)
@@ -75,10 +75,14 @@ internal class BrowserRunner : IAsyncDisposable
         if (!urlAvailable.Task.IsCompleted)
             throw new Exception("Timed out waiting for the app host url");
 
+        var url = new Uri(urlAvailable.Task.Result);
         Playwright = await Microsoft.Playwright.Playwright.CreateAsync();
         Browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions{
             ExecutablePath = s_chromePath.Value,
-            Headless = headless
+            Headless = headless,
+            Args = OperatingSystem.IsWindows()
+                        ? new[] { $"--explicitly-allowed-ports={url.Port}" }
+                        : Array.Empty<string>()
         });
 
         IPage page = await Browser.NewPageAsync();
index 983f484..5fd0572 100644 (file)
@@ -413,6 +413,17 @@ namespace Wasm.Build.Tests
         {
             InitPaths(id);
             InitProjectDir(id);
+
+            File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.props"), "<Project />");
+            File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.targets"),
+                """
+                <Project>
+                  <ItemGroup>
+                      <EmscriptenEnvVars Include="FROZEN_CACHE=" Condition="'$(OS)' == 'Windows_NT'" />
+                  </ItemGroup>
+                </Project>
+                """);
+
             new DotNetCommand(s_buildEnv, _testOutput, useDefaultArgs: false)
                     .WithWorkingDirectory(_projectDir!)
                     .ExecuteWithCapturedOutput($"new {template}")
index 1723e65..b7c95aa 100644 (file)
@@ -42,13 +42,15 @@ namespace Wasm.Build.Tests
             // Release+publish defaults to native relinking
             bool dotnetWasmFromRuntimePack = !nativeRelink && !buildArgs.AOT && buildArgs.Config != "Release";
 
+            string extraProperties = (nativeRelink ? $"<WasmBuildNative>true</WasmBuildNative>" : string.Empty)
+                                        // make ASSERTIONS=1 so that we test with it
+                                        + $"<EmccCompileOptimizationFlag>-O0 -sASSERTIONS=1</EmccCompileOptimizationFlag>"
+                                        + $"<EmccLinkOptimizationFlag>-O1</EmccLinkOptimizationFlag>";
+
             buildArgs = buildArgs with { ProjectName = projectName };
             buildArgs = ExpandBuildArgs(buildArgs,
                                         projectTemplate: s_resourcesProjectTemplate,
-                                        extraProperties: (nativeRelink ? $"<WasmBuildNative>true</WasmBuildNative>" : string.Empty)
-                                        // make ASSERTIONS=1 so that we test with it
-                                        + $"<EmccCompileOptimizationFlag>{ (buildArgs.Config == "Debug" ? "-O0 -sASSERTIONS=1" : "-O0 -sASSERTIONS=1")}</EmccCompileOptimizationFlag>"
-                                        );
+                                        extraProperties: extraProperties);
 
             BuildProject(buildArgs,
                             id: id,
@@ -65,7 +67,7 @@ namespace Wasm.Build.Tests
                             args: argCulture,
                             host: host, id: id,
                             // check that downloading assets doesn't have timing race conditions
-                            extraXHarnessMonoArgs: "--fetch-random-delay=200");
+                            extraXHarnessMonoArgs: host is RunHost.Chrome ? "--fetch-random-delay=200" : string.Empty);
         }
 
         [Theory]
@@ -81,10 +83,15 @@ namespace Wasm.Build.Tests
             string projectName = $"SatelliteAssemblyFromProjectRef";
             bool dotnetWasmFromRuntimePack = !nativeRelink && !buildArgs.AOT;
 
+            string extraProperties = $"<WasmBuildNative>{(nativeRelink ? "true" : "false")}</WasmBuildNative>"
+                                        // make ASSERTIONS=1 so that we test with it
+                                        + $"<EmccCompileOptimizationFlag>-O0 -sASSERTIONS=1</EmccCompileOptimizationFlag>"
+                                        + $"<EmccLinkOptimizationFlag>-O1</EmccLinkOptimizationFlag>";
+
             buildArgs = buildArgs with { ProjectName = projectName };
             buildArgs = ExpandBuildArgs(buildArgs,
                                         projectTemplate: s_resourcesProjectTemplate,
-                                        extraProperties: $"<WasmBuildNative>{(nativeRelink ? "true" : "false")}</WasmBuildNative>",
+                                        extraProperties: extraProperties,
                                         extraItems: $"<ProjectReference Include=\"..\\LibraryWithResources\\LibraryWithResources.csproj\" />");
 
             BuildProject(buildArgs,
@@ -97,8 +104,18 @@ namespace Wasm.Build.Tests
                                     _projectDir = Path.Combine(rootDir, projectName);
 
                                     Directory.CreateDirectory(_projectDir);
-                                    Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, "SatelliteAssemblyFromProjectRef"), rootDir);
+                                    Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, projectName), rootDir);
+
+                                    // D.B.* used for wasm projects should be moved next to the wasm project, so it doesn't
+                                    // affect the non-wasm library project
+                                    File.Move(Path.Combine(rootDir, "Directory.Build.props"), Path.Combine(_projectDir, "Directory.Build.props"));
+                                    File.Move(Path.Combine(rootDir, "Directory.Build.targets"), Path.Combine(_projectDir, "Directory.Build.targets"));
+
                                     CreateProgramForCultureTest(_projectDir, "LibraryWithResources.resx.words", "LibraryWithResources.Class1");
+
+                                    // The root D.B* should be empty
+                                    File.WriteAllText(Path.Combine(rootDir, "Directory.Build.props"), "<Project />");
+                                    File.WriteAllText(Path.Combine(rootDir, "Directory.Build.targets"), "<Project />");
                                 }));
 
             RunAndTestWasmApp(buildArgs,
index 3a6e405..9bb7d0a 100644 (file)
@@ -133,15 +133,19 @@ namespace Wasm.Build.Tests
         }
 
         [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
-        [InlineData("Debug")]
-        [InlineData("Release")]
-        public void ConsoleBuildAndRun(string config)
+        [InlineData("Debug", false)]
+        [InlineData("Debug", true)]
+        [InlineData("Release", false)]
+        [InlineData("Release", true)]
+        public void ConsoleBuildAndRun(string config, bool relinking)
         {
             string id = $"{config}_{Path.GetRandomFileName()}";
             string projectFile = CreateWasmTemplateProject(id, "wasmconsole");
             string projectName = Path.GetFileNameWithoutExtension(projectFile);
 
             updateProgramCS();
+            if (relinking)
+                AddItemsPropertiesToProject(projectFile, "<WasmBuildNative>true</WasmBuildNative>");
 
             var buildArgs = new BuildArgs(projectName, config, false, id, null);
             buildArgs = ExpandBuildArgs(buildArgs);
@@ -149,7 +153,7 @@ namespace Wasm.Build.Tests
             BuildProject(buildArgs,
                         id: id,
                         new BuildProjectOptions(
-                            DotnetWasmFromRuntimePack: true,
+                            DotnetWasmFromRuntimePack: !relinking,
                             CreateProject: false,
                             HasV8Script: false,
                             MainJS: "main.mjs",
@@ -157,7 +161,7 @@ namespace Wasm.Build.Tests
                             TargetFramework: "net7.0"
                             ));
 
-            AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: true);
+            AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: !relinking);
 
             (int exitCode, string output) = RunProcess(s_buildEnv.DotNet, _testOutput, args: $"run --no-build -c {config} x y z", workingDir: _projectDir);
             Assert.Equal(42, exitCode);
@@ -167,25 +171,28 @@ namespace Wasm.Build.Tests
         }
 
         [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
-        [InlineData("Debug", false)]
-        [InlineData("Debug", true)]
-        [InlineData("Release", false)]
-        [InlineData("Release", true)]
-        public void ConsolePublishAndRun(string config, bool aot)
+        [InlineData("Debug", false, false)]
+        [InlineData("Debug", false, true)]
+        [InlineData("Debug", true, false)]
+        [InlineData("Release", false, false)] // Release relinks by default
+        [InlineData("Release", true, false)]
+        public void ConsolePublishAndRun(string config, bool aot, bool relinking)
         {
             string id = $"{config}_{Path.GetRandomFileName()}";
             string projectFile = CreateWasmTemplateProject(id, "wasmconsole");
             string projectName = Path.GetFileNameWithoutExtension(projectFile);
 
             updateProgramCS();
-            
+
             if (aot)
                 AddItemsPropertiesToProject(projectFile, "<RunAOTCompilation>true</RunAOTCompilation>");
+            else if (relinking)
+                AddItemsPropertiesToProject(projectFile, "<WasmBuildNative>true</WasmBuildNative>");
 
             var buildArgs = new BuildArgs(projectName, config, aot, id, null);
             buildArgs = ExpandBuildArgs(buildArgs);
 
-            bool expectRelinking = config == "Release" || aot;
+            bool expectRelinking = config == "Release" || aot || relinking;
             BuildProject(buildArgs,
                         id: id,
                         new BuildProjectOptions(
@@ -197,7 +204,15 @@ namespace Wasm.Build.Tests
                             TargetFramework: "net7.0",
                             UseCache: false));
 
-            AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: !expectRelinking);
+            if (!aot)
+            {
+                // These are disabled for AOT explicitly
+                AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: !expectRelinking);
+            }
+            else
+            {
+                AssertFilesDontExist(Path.Combine(GetBinDir(config), "AppBundle"), new[] { "dotnet.js.symbols" });
+            }
 
             // FIXME: pass envvars via the environment, once that is supported
             string runArgs = $"run --no-build -c {config}";