Skip to content

Commit a128c15

Browse files
authored
[wasm/wasi] Consolidate build targets (#95775)
* [wasm/wasi] Consolidate build targets Current state of build files: ``` wasm: WasmApp.props, WasmApp.targets, WasmApp.Native.targets wasi: WasiApp.props, WasiApp.targets, WasiApp.Native.targets `` The wasm, and wasi build have lot of shared code but that is not representative in the actual files, since the wasi targets started life as a quick-copy-comment-out-bits of the wasm targets. This commit consolidates these into: ``` common: WasmApp.Common.props, WasmApp.Common.targets wasm : WasmApp.props, WasmApp.targets wasi : WasiApp.props, WasiApp.targets ``` ## `WasmApp.Common.{props,targets}` This has all the common parts of the build for browser-wasm, and wasi, and includes bits from `WasmApp.{props,targets}`, and `WasmApp.Native.{props,targets}`. - The top level target remains the same - `WasmBuildApp`. - There are a few "public" targets that can be hooked into: - `PrepareInputsForWasmBuild` - `WasmGenerateAppBundle` - `PrepareForWasmBuildNative` - `WasmLinkDotNet` - all these public targets have corresponding `*DependsOn` properties which can be used for extending the build note: this commit does not add a public target for AOT, but it might be added in future. ## WasmApp.{props,targets} This is for `browser-wasm` projects. The file might be renamed in future. ## WasiApp.{props,targets} This is for `wasi-wasm` projects. `ILStrip` becomes usable as a feature for `wasi-wasm` because of this consolidation. * [wasi] WBT: Use TestOutputWrapper * [wasm] WBT: Track target name changes * [wasi] WBT: Add new tests * cleanup * cleanup * address feedback * address feedback
1 parent 46bf1af commit a128c15

26 files changed

+1945
-2156
lines changed

Directory.Build.props

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@
183183
<WasmtimeDir Condition="'$(WasmtimeDir)' == '' and '$(WASMTIME_PATH)' != '' and Exists($(WASMTIME_PATH))">$(WASMTIME_PATH)</WasmtimeDir>
184184
<WasmtimeDir Condition="'$(WasmtimeDir)' == ''">$([MSBuild]::NormalizeDirectory($(ArtifactsObjDir), 'wasmtime'))</WasmtimeDir>
185185
<InstallWasmtimeForTests Condition="'$(InstallWasmtimeForTests)' == '' and !Exists($(WasmtimeDir))">true</InstallWasmtimeForTests>
186+
<WasmCommonTargetsPath>$([MSBuild]::NormalizeDirectory($(MonoProjectRoot), 'wasm', 'build'))</WasmCommonTargetsPath>
186187
</PropertyGroup>
187188

188189
<PropertyGroup Label="CalculatePortableBuild">
@@ -331,7 +332,7 @@
331332

332333
<!-- this property is used by the SDK to pull in mono-based runtime packs -->
333334
<UseMonoRuntime Condition="'$(UseMonoRuntime)' == '' and '$(RuntimeFlavor)' == 'Mono'">true</UseMonoRuntime>
334-
335+
335336
<!-- For enabling the use of XUnitLogChecker in coreclr and libraries test runs. -->
336337
<!-- TODO: Enable XUnitLogChecker for NativeAOT tests https://github.com/dotnet/runtime/issues/94722 -->
337338
<IsXUnitLogCheckerSupported Condition="'$(IsXUnitLogCheckerSupported)' == ''">false</IsXUnitLogCheckerSupported>
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
Wasi.Build.Tests.InvariantTests
2-
Wasi.Build.Tests.WasiTemplateTests
2+
Wasi.Build.Tests.ILStripTests
3+
Wasi.Build.Tests.SdkMissingTests
4+
Wasi.Build.Tests.RuntimeConfigTests
5+
Wasi.Build.Tests.WasiTemplateTests

eng/testing/tests.wasm.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@
109109
<BundleFiles Include="$(RuntimeConfigFilePath)" TargetDir="publish" />
110110

111111
<BundleFiles Include="$(WasmSharedPath)data\aot-tests\*" TargetDir="publish" />
112+
<!-- FIXME: what would be the correct place to do this? -->
113+
<BundleFiles Include="$(MonoProjectRoot)src\mono\wasm\build\WasmApp.Common*" TargetDir="publish" />
112114
</ItemGroup>
113115

114116
<ItemGroup Condition="'$(DebuggerSupport)' == 'true'">

src/libraries/sendtohelix-wasi.targets

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
<EnableDefaultBuildHelixWorkItems>false</EnableDefaultBuildHelixWorkItems>
4848

4949
<WASI_SDK_PATH Condition="'$(WASI_SDK_PATH)' == ''">$(RepoRoot)src\mono\wasi\wasi-sdk\</WASI_SDK_PATH>
50-
<WasmBuildTargetsDir>$([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasi', 'build'))</WasmBuildTargetsDir>
50+
<WasiBuildTargetsDir>$([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasi', 'build'))</WasiBuildTargetsDir>
51+
<WasmBuildTargetsDir>$([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'build'))</WasmBuildTargetsDir>
5152
<WasmSharedDir>$([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'shared'))</WasmSharedDir>
5253
<WasiSdkDirForHelixPayload>$(HelixDependenciesStagingPath)\wasi-sdk</WasiSdkDirForHelixPayload>
5354
<WasmtimeDirForHelixPayload>$(HelixDependenciesStagingPath)\wasmtime</WasmtimeDirForHelixPayload>
@@ -123,6 +124,7 @@
123124

124125
<HelixCorrelationPayload Include="$(MicrosoftNetCoreAppRuntimePackDir)" Destination="build/microsoft.netcore.app.runtime.wasi-wasm" />
125126

127+
<HelixCorrelationPayload Include="$(WasiBuildTargetsDir)" Destination="build/wasm" />
126128
<HelixCorrelationPayload Include="$(WasmBuildTargetsDir)" Destination="build/wasm" />
127129
<HelixCorrelationPayload Include="$(WasmAppBuilderDir)" Destination="build/WasmAppBuilder" />
128130
<HelixCorrelationPayload Include="$(MonoAOTCompilerDir)" Destination="build/MonoAOTCompiler" />

src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Microsoft.NET.Runtime.WebAssembly.Sdk.pkgproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
<PackageFile Include="Sdk\Sdk.props" TargetPath="Sdk" />
1515
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\ILLink.Substitutions.*.xml" TargetPath="Sdk" />
1616
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\ILLink.Descriptors.*.xml" TargetPath="Sdk" />
17+
1718
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.props" TargetPath="Sdk" />
1819
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.targets" TargetPath="Sdk" />
19-
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.Native.*" TargetPath="Sdk" />
20+
21+
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.Common.props" TargetPath="Sdk" />
22+
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.Common.targets" TargetPath="Sdk" />
23+
2024
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\EmSdkRepo.Defaults.props" TargetPath="Sdk" />
2125
</ItemGroup>
2226

src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
<PackageFile Include="Sdk\Sdk.props" TargetPath="Sdk" />
1515
<PackageFile Include="$(RepoRoot)\src\mono\wasi\build\WasiApp.props" TargetPath="Sdk" />
1616
<PackageFile Include="$(RepoRoot)\src\mono\wasi\build\WasiApp.targets" TargetPath="Sdk" />
17-
<PackageFile Include="$(RepoRoot)\src\mono\wasi\build\WasiApp.Native.*" TargetPath="Sdk" />
17+
18+
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.Common.props" TargetPath="Sdk" />
19+
<PackageFile Include="$(RepoRoot)\src\mono\wasm\build\WasmApp.Common.targets" TargetPath="Sdk" />
20+
1821
<PackageFile Include="$(RepoRoot)\src\mono\wasi\build\WasiSdk.Defaults.props" TargetPath="Sdk" />
1922
</ItemGroup>
2023

src/mono/wasi/Wasi.Build.Tests/BuildTestBase.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public BuildTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture bu
9393
{
9494
_testIdx = Interlocked.Increment(ref s_testCounter);
9595
_buildContext = buildContext;
96-
_testOutput = output;
96+
_testOutput = new TestOutputWrapper(output);
9797
_logPath = s_buildEnv.LogRootPath; // FIXME:
9898
}
9999

@@ -603,8 +603,6 @@ void LogData(string label, string? message)
603603
}
604604
outputBuilder.AppendLine($"{label} {message}");
605605
}
606-
if (EnvironmentVariables.ShowBuildOutput)
607-
Console.WriteLine($"{label} {message}");
608606
}
609607
}
610608

@@ -703,6 +701,7 @@ public static int Main()
703701
.MultiplyWithSingleArgs(true, false) /*propertyValue*/
704702
.MultiplyWithSingleArgs(true, false) /*aot*/
705703
.UnwrapItemsAsArrays();
704+
706705
protected CommandResult RunWithoutBuild(string config, string id)
707706
{
708707
string runArgs = $"run --no-build -c {config}";
@@ -721,7 +720,7 @@ protected CommandResult RunWithoutBuild(string config, string id)
721720
return res;
722721
}
723722
}
724-
723+
725724
public record BuildArgs(string ProjectName,
726725
string Config,
727726
bool AOT,
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.IO;
5+
using Xunit;
6+
using Xunit.Abstractions;
7+
using Wasm.Build.Tests;
8+
9+
#nullable enable
10+
11+
namespace Wasi.Build.Tests;
12+
13+
public class ILStripTests : BuildTestBase
14+
{
15+
public ILStripTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
16+
: base(output, buildContext)
17+
{
18+
}
19+
20+
[Theory]
21+
[InlineData("", /*expectILStripping*/ true, /*singleFileBundle*/false)] // Default case
22+
[InlineData("", /*expectILStripping*/ true, /*singleFileBundle*/true)] // Default case
23+
[InlineData("false", /*expectILStripping*/ false, /*singleFileBundle*/false)] // the opposite of the default case
24+
[InlineData("false", /*expectILStripping*/ false, /*singleFileBundle*/true)] // the opposite of the default case
25+
public void WasmStripILAfterAOT_TestDefaultAndOverride(string stripILAfterAOT, bool expectILStripping, bool singleFileBundle)
26+
{
27+
string config = "Release";
28+
string id = $"{config}_{GetRandomId()}";
29+
string projectFile = CreateWasmTemplateProject(id, "wasiconsole");
30+
string projectName = Path.GetFileNameWithoutExtension(projectFile);
31+
32+
string extraProperties = "<RunAOTCompilation>true</RunAOTCompilation>";
33+
if (singleFileBundle)
34+
extraProperties += "<WasmSingleFileBundle>true</WasmSingleFileBundle>";
35+
if (!string.IsNullOrEmpty(stripILAfterAOT))
36+
extraProperties += $"<WasmStripILAfterAOT>{stripILAfterAOT}</WasmStripILAfterAOT>";
37+
AddItemsPropertiesToProject(projectFile, extraProperties);
38+
39+
var buildArgs = new BuildArgs(projectName, config, AOT: true, ProjectFileContents: id, ExtraBuildArgs: null);
40+
buildArgs = ExpandBuildArgs(buildArgs);
41+
42+
BuildProject(buildArgs,
43+
id: id,
44+
new BuildProjectOptions(
45+
DotnetWasmFromRuntimePack: false,
46+
CreateProject: false,
47+
Publish: true,
48+
TargetFramework: BuildTestBase.DefaultTargetFramework,
49+
UseCache: false));
50+
51+
string runArgs = $"run --no-silent --no-build -c {config}";
52+
new RunCommand(s_buildEnv, _testOutput, label: id)
53+
.WithWorkingDirectory(_projectDir!)
54+
.ExecuteWithCapturedOutput(runArgs)
55+
.EnsureSuccessful();
56+
57+
string frameworkDir = singleFileBundle ? "" : Path.Combine(_projectDir!, "bin", config, DefaultTargetFramework, "wasi-wasm", "AppBundle", "managed");
58+
string objBuildDir = Path.Combine(_projectDir!, "obj", config, DefaultTargetFramework, "wasi-wasm", "wasm", "for-publish");
59+
TestWasmStripILAfterAOTOutput(objBuildDir, frameworkDir, expectILStripping, singleFileBundle, _testOutput);
60+
}
61+
62+
private static void TestWasmStripILAfterAOTOutput(string objBuildDir, string appBundleFrameworkDir, bool expectILStripping, bool singleFileBundle, ITestOutputHelper testOutput)
63+
{
64+
string origAssemblyDir = Path.Combine(objBuildDir, "aot-in");
65+
string strippedAssemblyDir = Path.Combine(objBuildDir, "stripped");
66+
Assert.True(Directory.Exists(origAssemblyDir), $"Could not find the original AOT input assemblies dir: {origAssemblyDir}");
67+
if (expectILStripping)
68+
Assert.True(Directory.Exists(strippedAssemblyDir), $"Could not find the stripped assemblies dir: {strippedAssemblyDir}");
69+
else
70+
Assert.False(Directory.Exists(strippedAssemblyDir), $"Expected {strippedAssemblyDir} to not exist");
71+
72+
string assemblyToExamine = "System.Private.CoreLib.dll";
73+
string originalAssembly = Path.Combine(objBuildDir, origAssemblyDir, assemblyToExamine);
74+
string strippedAssembly = Path.Combine(objBuildDir, strippedAssemblyDir, assemblyToExamine);
75+
string includedAssembly = Path.Combine(appBundleFrameworkDir, assemblyToExamine);
76+
77+
Assert.True(File.Exists(originalAssembly), $"Expected {nameof(originalAssembly)} {originalAssembly} to exist");
78+
if (!singleFileBundle)
79+
Assert.True(File.Exists(includedAssembly), $"Expected {nameof(includedAssembly)} {includedAssembly} to exist");
80+
if (expectILStripping)
81+
Assert.True(File.Exists(strippedAssembly), $"Expected {nameof(strippedAssembly)} {strippedAssembly} to exist");
82+
else
83+
Assert.False(File.Exists(strippedAssembly), $"Expected {strippedAssembly} to not exist");
84+
85+
string compressedOriginalAssembly = Utils.GZipCompress(originalAssembly);
86+
string? compressedIncludedAssembly = null;
87+
FileInfo compressedOriginalAssembly_fi = new FileInfo(compressedOriginalAssembly);
88+
FileInfo? compressedincludedAssembly_fi = null;
89+
90+
testOutput.WriteLine ($"compressedOriginalAssembly_fi: {compressedOriginalAssembly_fi.Length}, {compressedOriginalAssembly}");
91+
if (!singleFileBundle)
92+
{
93+
compressedIncludedAssembly = Utils.GZipCompress(includedAssembly)!;
94+
compressedincludedAssembly_fi = new FileInfo(compressedIncludedAssembly);
95+
testOutput.WriteLine ($"compressedincludedAssembly_fi: {compressedincludedAssembly_fi.Length}, {compressedIncludedAssembly}");
96+
}
97+
98+
if (expectILStripping)
99+
{
100+
string compressedStrippedAssembly = Utils.GZipCompress(strippedAssembly);
101+
FileInfo compressedStrippedAssembly_fi = new FileInfo(compressedStrippedAssembly);
102+
testOutput.WriteLine ($"compressedStrippedAssembly_fi: {compressedStrippedAssembly_fi.Length}, {compressedStrippedAssembly}");
103+
104+
// original > stripped assembly
105+
Assert.True(compressedOriginalAssembly_fi.Length > compressedStrippedAssembly_fi.Length,
106+
$"Expected original assembly ({compressedOriginalAssembly}) size ({compressedOriginalAssembly_fi.Length}) " +
107+
$"to be bigger than the stripped assembly ({compressedStrippedAssembly}) size ({compressedStrippedAssembly_fi.Length})");
108+
109+
if (!singleFileBundle)
110+
{
111+
// included == stripped assembly
112+
Assert.True(compressedincludedAssembly_fi!.Length == compressedStrippedAssembly_fi.Length,
113+
$"Expected included assembly ({compressedIncludedAssembly}) size ({compressedincludedAssembly_fi.Length}) " +
114+
$"to be the same as the stripped assembly ({compressedStrippedAssembly}) size ({compressedStrippedAssembly_fi.Length})");
115+
}
116+
}
117+
else
118+
{
119+
if (!singleFileBundle)
120+
{
121+
// original == included assembly
122+
Assert.True(compressedincludedAssembly_fi!.Length == compressedOriginalAssembly_fi.Length,
123+
$"Expected included assembly ({compressedIncludedAssembly}) size ({compressedincludedAssembly_fi.Length}) " +
124+
$"to be the same as the original assembly ({compressedOriginalAssembly}) size ({compressedOriginalAssembly_fi.Length})");
125+
}
126+
}
127+
}
128+
}

src/mono/wasi/Wasi.Build.Tests/InvariantTests.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33

44
using System;
55
using System.IO;
6-
using System.Runtime.InteropServices;
76
using Xunit;
87
using Xunit.Abstractions;
9-
using Xunit.Sdk;
108
using Wasm.Build.Tests;
119

1210
#nullable enable
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.IO;
5+
using Xunit;
6+
using Xunit.Abstractions;
7+
using Wasm.Build.Tests;
8+
9+
#nullable enable
10+
11+
namespace Wasi.Build.Tests;
12+
13+
public class RuntimeConfigTests : BuildTestBase
14+
{
15+
public RuntimeConfigTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
16+
: base(output, buildContext)
17+
{
18+
}
19+
20+
[Theory]
21+
[ActiveIssue("https://github.com/dotnet/runtime/issues/95345")]
22+
[InlineData(false)]
23+
[InlineData(true)]
24+
public void MissingRuntimeConfigTemplateJson(bool singleFileBundle)
25+
{
26+
string config = "Release";
27+
string id = $"{config}_{GetRandomId()}";
28+
string projectFile = CreateWasmTemplateProject(id, "wasiconsole");
29+
string projectName = Path.GetFileNameWithoutExtension(projectFile);
30+
31+
File.Delete(Path.Combine(_projectDir!, "runtimeconfig.template.json"));
32+
33+
var buildArgs = new BuildArgs(projectName, config, AOT: true, ProjectFileContents: id, ExtraBuildArgs: null);
34+
buildArgs = ExpandBuildArgs(buildArgs);
35+
AddItemsPropertiesToProject(projectFile, singleFileBundle ? "<WasmSingleFileBundle>true</WasmSingleFileBundle>" : "");
36+
37+
BuildProject(buildArgs,
38+
id: id,
39+
new BuildProjectOptions(
40+
DotnetWasmFromRuntimePack: false,
41+
CreateProject: false,
42+
Publish: true,
43+
TargetFramework: BuildTestBase.DefaultTargetFramework,
44+
UseCache: false));
45+
46+
string runArgs = $"run --no-silent --no-build -c {config}";
47+
new RunCommand(s_buildEnv, _testOutput, label: id)
48+
.WithWorkingDirectory(_projectDir!)
49+
.ExecuteWithCapturedOutput(runArgs)
50+
.EnsureSuccessful();
51+
}
52+
}

0 commit comments

Comments
 (0)