Skip to content

Commit

Permalink
[wasm] Avoid unnecessary relinking when publishing a blazor project f…
Browse files Browse the repository at this point in the history
…or AOT (#82748)

* [wasm] Wasm.Build.Tests: Add blazor+aot run test

* cleanup

* [wasm] Wasm.Build.Tests: Use $(_IsPublishing) to avoid unncessary

.. relinking during "Build", when publishing.

`Publish` target triggers `Build` target to run. When publishing, we
don't want to run relinking step during the `Build`, as it will be run
for `Publish` anyway. Earlier there wasn't a good way to differentiate
the two cases of `build` when building, and `build` when publishing, but
now the sdk sets `$(_IsPublishing)=true`, which can be used here.

* fix blazor tests

* Wasm.Build.Tests: Add support for running published blazor projects

`dotnet run` uses the regular build output. Published blazor app, like
when using AOT, needs to be run more "manually" by starting a web server
in the publish folder. This is accomplished here by using the new
xharness command `wasm webserver`.

* Detect runtime assertions in blazor runs

* Update test to track changes

* cleanup

* Disable BlazorPublishRunTest because of #82481

* Update test to track changes

* Update xharness dependency

Updating 'Microsoft.DotNet.XHarness.CLI': '1.0.0-prerelease.23117.1' => '1.0.0-prerelease.23151.1' (from build '20230301.1' of 'https://github.com/dotnet/xharness')
Updating 'Microsoft.DotNet.XHarness.TestRunners.Common': '1.0.0-prerelease.23117.1' => '1.0.0-prerelease.23151.1' (from build '20230301.1' of 'https://github.com/dotnet/xharness')
Updating 'Microsoft.DotNet.XHarness.TestRunners.Xunit': '1.0.0-prerelease.23117.1' => '1.0.0-prerelease.23151.1' (from build '20230301.1' of 'https://github.com/dotnet/xharness')
  • Loading branch information
radical authored Mar 2, 2023
1 parent b8a4f02 commit 8162ac9
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
]
},
"microsoft.dotnet.xharness.cli": {
"version": "1.0.0-prerelease.23117.1",
"version": "1.0.0-prerelease.23151.1",
"commands": [
"xharness"
]
Expand Down
12 changes: 6 additions & 6 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -284,17 +284,17 @@
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>252018c3d3fffdb592413cf61d5b80cf751e0a59</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XHarness.TestRunners.Common" Version="1.0.0-prerelease.23117.1">
<Dependency Name="Microsoft.DotNet.XHarness.TestRunners.Common" Version="1.0.0-prerelease.23151.1">
<Uri>https://github.com/dotnet/xharness</Uri>
<Sha>8d789cbeecb6c89bf470fdc7727a8f501724fc8a</Sha>
<Sha>05d4d5fc8634fa68ec53a9a3b31271797f4a0c7c</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XHarness.TestRunners.Xunit" Version="1.0.0-prerelease.23117.1">
<Dependency Name="Microsoft.DotNet.XHarness.TestRunners.Xunit" Version="1.0.0-prerelease.23151.1">
<Uri>https://github.com/dotnet/xharness</Uri>
<Sha>8d789cbeecb6c89bf470fdc7727a8f501724fc8a</Sha>
<Sha>05d4d5fc8634fa68ec53a9a3b31271797f4a0c7c</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XHarness.CLI" Version="1.0.0-prerelease.23117.1">
<Dependency Name="Microsoft.DotNet.XHarness.CLI" Version="1.0.0-prerelease.23151.1">
<Uri>https://github.com/dotnet/xharness</Uri>
<Sha>8d789cbeecb6c89bf470fdc7727a8f501724fc8a</Sha>
<Sha>05d4d5fc8634fa68ec53a9a3b31271797f4a0c7c</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.PackageTesting" Version="8.0.0-beta.23123.2">
<Uri>https://github.com/dotnet/arcade</Uri>
Expand Down
6 changes: 3 additions & 3 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@
<!-- Testing -->
<MicrosoftNETCoreCoreDisToolsVersion>1.1.0</MicrosoftNETCoreCoreDisToolsVersion>
<MicrosoftNETTestSdkVersion>17.4.0-preview-20220707-01</MicrosoftNETTestSdkVersion>
<MicrosoftDotNetXHarnessTestRunnersCommonVersion>1.0.0-prerelease.23117.1</MicrosoftDotNetXHarnessTestRunnersCommonVersion>
<MicrosoftDotNetXHarnessTestRunnersXunitVersion>1.0.0-prerelease.23117.1</MicrosoftDotNetXHarnessTestRunnersXunitVersion>
<MicrosoftDotNetXHarnessCLIVersion>1.0.0-prerelease.23117.1</MicrosoftDotNetXHarnessCLIVersion>
<MicrosoftDotNetXHarnessTestRunnersCommonVersion>1.0.0-prerelease.23151.1</MicrosoftDotNetXHarnessTestRunnersCommonVersion>
<MicrosoftDotNetXHarnessTestRunnersXunitVersion>1.0.0-prerelease.23151.1</MicrosoftDotNetXHarnessTestRunnersXunitVersion>
<MicrosoftDotNetXHarnessCLIVersion>1.0.0-prerelease.23151.1</MicrosoftDotNetXHarnessCLIVersion>
<MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>1.1.0-alpha.0.23113.1</MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>
<XUnitVersion>2.4.2</XUnitVersion>
<XUnitAnalyzersVersion>1.0.0</XUnitAnalyzersVersion>
Expand Down
82 changes: 67 additions & 15 deletions src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ public void DefaultTemplate_WithoutWorkload(string config)
CreateBlazorWasmTemplateProject(id);

// Build
BuildInternal(id, config, publish: false);
BlazorBuildInternal(id, config, publish: false);
AssertBlazorBootJson(config, isPublish: false);

// Publish
BuildInternal(id, config, publish: true);
BlazorBuildInternal(id, config, publish: true);
AssertBlazorBootJson(config, isPublish: true);
}

Expand All @@ -52,11 +52,11 @@ public void DefaultTemplate_NoAOT_WithWorkload(string config)
if (config == "Release")
{
// relinking in publish for Release config
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked, ExpectRelinkDirWhenPublishing: true));
}
else
{
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack, ExpectRelinkDirWhenPublishing: true));
}
}

Expand All @@ -82,12 +82,23 @@ public void DefaultTemplate_NoAOT_WithWorkload(string config)
//}

[Theory]
[InlineData("Debug")]
[InlineData("Release")]
public async Task WithDllImportInMainAssembly(string config)
[InlineData("Debug", /*build*/true, /*publish*/false)]
[InlineData("Debug", /*build*/false, /*publish*/true)]
[InlineData("Debug", /*build*/true, /*publish*/true)]
[InlineData("Release", /*build*/true, /*publish*/false)]
[InlineData("Release", /*build*/false, /*publish*/true)]
[InlineData("Release", /*build*/true, /*publish*/true)]
public async Task WithDllImportInMainAssembly(string config, bool build, bool publish)
{
// Based on https://github.com/dotnet/runtime/issues/59255
string id = $"blz_dllimp_{config}";
string id = $"blz_dllimp_{config}_";
if (build && publish)
id += "build_then_publish";
else if (build)
id += "build";
else
id += "publish";

string projectFile = CreateProjectWithNativeReference(id);
string nativeSource = @"
#include <stdio.h>
Expand Down Expand Up @@ -118,18 +129,29 @@ public static class MyDllImports
outputText = $"{result}";
""");

BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));
CheckNativeFileLinked(forPublish: false);
if (build)
{
BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));
CheckNativeFileLinked(forPublish: false);
}

if (publish)
{
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked, ExpectRelinkDirWhenPublishing: build));
CheckNativeFileLinked(forPublish: true);
}

BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));
CheckNativeFileLinked(forPublish: true);
if (publish)
await BlazorRunForPublishWithWebServer(config, TestDllImport);
else
await BlazorRunForBuildWithDotnetRun(config, TestDllImport);

await BlazorRun(config, async (page) =>
async Task TestDllImport(IPage page)
{
await page.Locator("text=\"cpp_add\"").ClickAsync();
var txt = await page.Locator("p[role='test']").InnerHTMLAsync();
Assert.Equal("Output: 22", txt);
});
}

void CheckNativeFileLinked(bool forPublish)
{
Expand Down Expand Up @@ -181,7 +203,7 @@ public void BugRegression_60479_WithRazorClassLib()
BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));

// will relink
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked, ExpectRelinkDirWhenPublishing: true));

// publish/wwwroot/_framework/blazor.boot.json
string frameworkDir = FindBlazorBinFrameworkDir(config, forPublish: true);
Expand All @@ -197,4 +219,34 @@ public void BugRegression_60479_WithRazorClassLib()

Assert.Contains("RazorClassLibrary.dll", lazyVal.EnumerateObject().Select(jp => jp.Name));
}

[ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
[InlineData("Debug")]
[InlineData("Release")]
public async Task BlazorBuildRunTest(string config)
{
string id = $"blazor_{config}_{Path.GetRandomFileName()}";
string projectFile = CreateWasmTemplateProject(id, "blazorwasm");

BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));
await BlazorRunForBuildWithDotnetRun(config);
}

[ActiveIssue("https://github.com/dotnet/runtime/issues/82481")]
[ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
[InlineData("Debug", false)]
[InlineData("Debug", true)]
[InlineData("Release", false)]
[InlineData("Release", true)]
public async Task BlazorPublishRunTest(string config, bool aot)
{
string id = $"blazor_{config}_{Path.GetRandomFileName()}";
string projectFile = CreateWasmTemplateProject(id, "blazorwasm");
if (aot)
AddItemsPropertiesToProject(projectFile, "<RunAOTCompilation>true</RunAOTCompilation>");

BlazorPublish(new BlazorBuildOptions(id, config, aot ? NativeFilesType.AOT : NativeFilesType.Relinked));
await BlazorRunForPublishWithWebServer(config);
}

}
4 changes: 2 additions & 2 deletions src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void NativeBuild_WithDeployOnBuild_UsedByVS(string config, bool nativeRel
AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties);

// build with -p:DeployOnBuild=true, and that will trigger a publish
(CommandResult res, _) = BuildInternal(id, config, publish: false, setWasmDevel: false, "-p:DeployOnBuild=true");
(CommandResult res, _) = BlazorBuildInternal(id, config, publish: false, setWasmDevel: false, "-p:DeployOnBuild=true");

var expectedFileType = nativeRelink ? NativeFilesType.Relinked : NativeFilesType.AOT;

Expand Down Expand Up @@ -83,7 +83,7 @@ public void DefaultTemplate_AOT_InProjectFile(string config)
BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));

// will aot
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.AOT));
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.AOT, ExpectRelinkDirWhenPublishing: true));

// build again
BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));
Expand Down
6 changes: 3 additions & 3 deletions src/mono/wasm/Wasm.Build.Tests/Blazor/NativeRefTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void WithNativeReference_AOTInProjectFile(string config)

BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));

BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.AOT));
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.AOT, ExpectRelinkDirWhenPublishing: true));

// will relink
BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));
Expand All @@ -53,10 +53,10 @@ public void WithNativeReference_AOTOnCommandLine(string config)

BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));

BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.AOT), "-p:RunAOTCompilation=true");
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.AOT, ExpectRelinkDirWhenPublishing: true), "-p:RunAOTCompilation=true");

// no aot!
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked));
BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked, ExpectRelinkDirWhenPublishing: true));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public async Task<IPage> RunAsync(ToolCommand cmd, string args, bool headless =
throw new Exception($"Process ended before the url was found");
}
if (!urlAvailable.Task.IsCompleted)
throw new Exception("Timed out waiting for the app host url");
throw new Exception("Timed out waiting for the web server url");

var url = new Uri(urlAvailable.Task.Result);
Playwright = await Microsoft.Playwright.Playwright.CreateAsync();
Expand Down
1 change: 0 additions & 1 deletion src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public void BuildThenPublishNoAOT(BuildArgs buildArgs, RunHost host, string id)
Publish: false
));


Run();

if (!_buildContext.TryGetBuildFor(buildArgs, out BuildProduct? product))
Expand Down
43 changes: 36 additions & 7 deletions src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ public string CreateBlazorWasmTemplateProject(string id)
if (options.WarnAsError)
extraArgs = extraArgs.Append("/warnaserror").ToArray();

var res = BuildInternal(options.Id, options.Config, publish: false, setWasmDevel: false, extraArgs);
var res = BlazorBuildInternal(options.Id, options.Config, publish: false, setWasmDevel: false, extraArgs);
_testOutput.WriteLine($"BlazorBuild, options.tfm: {options.TargetFramework}");
AssertDotNetNativeFiles(options.ExpectedFileType, options.Config, forPublish: false, targetFramework: options.TargetFramework);
AssertBlazorBundle(options.Config,
Expand All @@ -557,7 +557,7 @@ public string CreateBlazorWasmTemplateProject(string id)

protected (CommandResult, string) BlazorPublish(BlazorBuildOptions options, params string[] extraArgs)
{
var res = BuildInternal(options.Id, options.Config, publish: true, setWasmDevel: false, extraArgs);
var res = BlazorBuildInternal(options.Id, options.Config, publish: true, setWasmDevel: false, extraArgs);
AssertDotNetNativeFiles(options.ExpectedFileType, options.Config, forPublish: true, targetFramework: options.TargetFramework);
AssertBlazorBundle(options.Config,
isPublish: true,
Expand All @@ -572,11 +572,20 @@ public string CreateBlazorWasmTemplateProject(string id)

// make sure this assembly gets skipped
Assert.DoesNotContain("Microsoft.JSInterop.WebAssembly.dll -> Microsoft.JSInterop.WebAssembly.dll.bc", res.Item1.Output);

}

string objBuildDir = Path.Combine(_projectDir!, "obj", options.Config, options.TargetFramework, "wasm", "for-build");
// Check that we linked only for publish
if (options.ExpectRelinkDirWhenPublishing)
Assert.True(Directory.Exists(objBuildDir), $"Could not find expected {objBuildDir}, which gets created when relinking during Build. This is liokely a test authoring error");
else
Assert.False(Directory.Exists(objBuildDir), $"Found unexpected {objBuildDir}, which gets created when relinking during Build");

return res;
}

protected (CommandResult, string) BuildInternal(string id, string config, bool publish=false, bool setWasmDevel=true, params string[] extraArgs)
protected (CommandResult, string) BlazorBuildInternal(string id, string config, bool publish=false, bool setWasmDevel=true, params string[] extraArgs)
{
string label = publish ? "publish" : "build";
_testOutput.WriteLine($"{Environment.NewLine}** {label} **{Environment.NewLine}");
Expand Down Expand Up @@ -922,13 +931,26 @@ public void BlazorAddRazorButton(string buttonText, string customCode, string me
File.WriteAllText(counterRazorPath, oldContent + additionalCode);
}

public async Task BlazorRun(string config, Func<IPage, Task>? test=null, string extraArgs="--no-build")
// Keeping these methods with explicit Build/Publish in the name
// so in the test code it is evident which is being run!
public Task BlazorRunForBuildWithDotnetRun(string config, Func<IPage, Task>? test=null, string extraArgs="--no-build")
=> BlazorRunTest($"run -c {config} {extraArgs}", _projectDir!, test);

public Task BlazorRunForPublishWithWebServer(string config, Func<IPage, Task>? test=null, string extraArgs="")
=> BlazorRunTest($"{s_xharnessRunnerCommand} wasm webserver --app=. --web-server-use-default-files {extraArgs}",
Path.GetFullPath(Path.Combine(FindBlazorBinFrameworkDir(config, forPublish: true), "..")),
test);

public async Task BlazorRunTest(string runArgs,
string workingDirectory,
Func<IPage, Task>? test = null,
bool detectRuntimeFailures = true)
{
using var runCommand = new RunCommand(s_buildEnv, _testOutput)
.WithWorkingDirectory(_projectDir!);
.WithWorkingDirectory(workingDirectory);

await using var runner = new BrowserRunner(_testOutput);
var page = await runner.RunAsync(runCommand, $"run -c {config} {extraArgs}", onConsoleMessage: OnConsoleMessage);
var page = await runner.RunAsync(runCommand, runArgs, onConsoleMessage: OnConsoleMessage);

await page.Locator("text=Counter").ClickAsync();
var txt = await page.Locator("p[role='status']").InnerHTMLAsync();
Expand All @@ -946,6 +968,12 @@ void OnConsoleMessage(IConsoleMessage msg)
if (EnvironmentVariables.ShowBuildOutput)
Console.WriteLine($"[{msg.Type}] {msg.Text}");
_testOutput.WriteLine($"[{msg.Type}] {msg.Text}");

if (detectRuntimeFailures)
{
if (msg.Text.Contains("[MONO] * Assertion") || msg.Text.Contains("Error: [MONO] "))
throw new XunitException($"Detected a runtime failure at line: {msg.Text}");
}
}
}

Expand Down Expand Up @@ -1210,7 +1238,8 @@ public record BlazorBuildOptions
string Config,
NativeFilesType ExpectedFileType,
string TargetFramework = BuildTestBase.DefaultTargetFrameworkForBlazor,
bool WarnAsError = true
bool WarnAsError = true,
bool ExpectRelinkDirWhenPublishing=false
);

public enum GlobalizationMode
Expand Down
4 changes: 2 additions & 2 deletions src/mono/wasm/Wasm.Build.Tests/CleanTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ private void Blazor_BuildNativeNonNative_ThenCleanTest(string config, bool first
AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties);

bool relink = firstBuildNative;
BuildInternal(id, config, publish: false,
BlazorBuildInternal(id, config, publish: false,
extraArgs: relink ? "-p:WasmBuildNative=true" : string.Empty);

string relinkDir = Path.Combine(_projectDir!, "obj", config, DefaultTargetFrameworkForBlazor, "wasm", "for-build");
if (relink)
Assert.True(Directory.Exists(relinkDir), $"Could not find expected relink dir: {relinkDir}");

relink = !firstBuildNative;
BuildInternal(id, config, publish: false,
BlazorBuildInternal(id, config, publish: false,
extraArgs: relink ? "-p:WasmBuildNative=true" : string.Empty);

if (relink)
Expand Down
8 changes: 6 additions & 2 deletions src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ public void Defaults(string config, string extraProperties, bool aot, bool build
{
string output = CheckWasmNativeDefaultValue("native_defaults_publish", config, extraProperties, aot, dotnetWasmFromRuntimePack: !publishValue);

Assert.Contains($"** WasmBuildNative: '{buildValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output);
// for build
Assert.DoesNotContain($"** WasmBuildNative: '{buildValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output);
// for publish
Assert.Contains($"** WasmBuildNative: '{publishValue.ToString().ToLower()}', WasmBuildingForNestedPublish: 'true'", output);
Assert.Contains("Stopping the build", output);
}
Expand All @@ -61,7 +63,9 @@ public void WithNativeReference(string config, string extraProperties, bool buil
dotnetWasmFromRuntimePack: !publishValue,
extraItems: nativeRefItem);

Assert.Contains($"** WasmBuildNative: '{buildValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output);
// for build
Assert.DoesNotContain($"** WasmBuildNative: '{buildValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output);
// for publish
Assert.Contains($"** WasmBuildNative: '{publishValue.ToString().ToLower()}', WasmBuildingForNestedPublish: 'true'", output);
Assert.Contains("Stopping the build", output);
}
Expand Down
Loading

0 comments on commit 8162ac9

Please sign in to comment.