Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 64 additions & 43 deletions src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using Xunit;
using Xunit.Abstractions;

Expand All @@ -12,6 +13,7 @@ namespace Wasm.Build.Tests
{
public class WasmNativeDefaultsTests : TestMainJsTestBase
{
private static Regex s_regex = new("\\*\\* WasmBuildNative:.*");
public WasmNativeDefaultsTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
: base(output, buildContext)
{
Expand Down Expand Up @@ -39,19 +41,20 @@ public static TheoryData<string, string, bool, bool, bool> SettingDifferentFromV
// Config=Release always causes relinking when publishing
bool publishValue = forPublish && config == "Release" ? true : false;
// Setting the default value from the runtime pack shouldn't trigger relinking
data.Add(config, $"<{defaultPair.propertyName}>{defaultPair.defaultValueInRuntimePack}</{defaultPair.propertyName}>",
data.Add(config, $"<{defaultPair.propertyName}>{defaultPair.defaultValueInRuntimePack.ToString().ToLower()}</{defaultPair.propertyName}>",
/*aot*/ false, /*build*/ false, /*publish*/ publishValue);
// Leaving the property unset, so checking the default
data.Add(config, "", /*aot*/ false, /*build*/ false, /*publish*/ publishValue);

// Setting the !default value should trigger relinking
data.Add(config, $"<{defaultPair.propertyName}>{!defaultPair.defaultValueInRuntimePack}</{defaultPair.propertyName}>",
data.Add(config, $"<{defaultPair.propertyName}>{(!defaultPair.defaultValueInRuntimePack).ToString().ToLower()}</{defaultPair.propertyName}>",
/*aot*/ false, /*build*/ true, /*publish*/ true);
}
}

return data;
}

public static TheoryData<string, string, bool, bool, bool> DefaultsTestData(bool forPublish)
{
TheoryData<string, string, bool, bool, bool> data = new()
Expand Down Expand Up @@ -93,45 +96,34 @@ public static TheoryData<string, string, bool, bool, bool> DefaultsTestData(bool
return data;
}

#pragma warning disable xUnit1026 // For unused *buildValue*, and *publishValue* parameters
[Theory]
[MemberData(nameof(DefaultsTestData), parameters: false)]
[MemberData(nameof(SettingDifferentFromValuesInRuntimePack), parameters: false)]
public void DefaultsWithBuild(string config, string extraProperties, bool aot, bool expectWasmBuildNativeForBuild, bool expectWasmBuildNativeForPublish)
{
string output = CheckWasmNativeDefaultValue("native_defaults_build", config, extraProperties, aot, dotnetWasmFromRuntimePack: !expectWasmBuildNativeForPublish, publish: false);

bool expectedWasmNativeStripValue = true;
if (/*isBuild && */ expectWasmBuildNativeForBuild && config == "Debug")
expectedWasmNativeStripValue = false;
(string output, string? line) = CheckWasmNativeDefaultValue("native_defaults_build", config, extraProperties, aot, dotnetWasmFromRuntimePack: !expectWasmBuildNativeForBuild, publish: false);

// bool expectedWasmNativeStripValue = !(wasmBuildNativeForBuild && config == "Debug");
// for build
Assert.Contains($"** WasmBuildNative: '{expectWasmBuildNativeForBuild.ToString().ToLower()}', WasmNativeStrip: '{expectedWasmNativeStripValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output);
Assert.Contains("Stopping the build", output);
InferAndCheckPropertyValues(line, isPublish: false, wasmBuildNative: expectWasmBuildNativeForBuild, config: config);
}

#pragma warning disable xUnit1026 // For unused *buildValue* parameter
[Theory]
[MemberData(nameof(DefaultsTestData), parameters: true)]
[MemberData(nameof(SettingDifferentFromValuesInRuntimePack), parameters: true)]
public void DefaultsWithPublish(string config, string extraProperties, bool aot, bool expectWasmBuildNativeForBuild, bool expectWasmBuildNativeForPublish)
{
string output = CheckWasmNativeDefaultValue("native_defaults_publish", config, extraProperties, aot, dotnetWasmFromRuntimePack: !expectWasmBuildNativeForPublish, publish: true);
(string output, string? line) = CheckWasmNativeDefaultValue("native_defaults_publish", config, extraProperties, aot, dotnetWasmFromRuntimePack: !expectWasmBuildNativeForPublish, publish: true);

// for build
// Assert.DoesNotContain($"** WasmBuildNative: '{buildValue.ToString().ToLower()}', WasmNativeStrip: 'true', WasmBuildingForNestedPublish: ''", output);
// for publish
Assert.Contains($"** WasmBuildNative: '{expectWasmBuildNativeForPublish.ToString().ToLower()}', WasmNativeStrip: 'true', WasmBuildingForNestedPublish: 'true'", output);
Assert.Contains("Stopping the build", output);
InferAndCheckPropertyValues(line, isPublish: true, wasmBuildNative: expectWasmBuildNativeForPublish, config: config);
}
#pragma warning restore xunit1026

public static TheoryData<string, string, bool, bool> SetWasmNativeStripExplicitlyTestData(bool publish) => new()
{
{"Debug", "<WasmNativeStrip>true</WasmNativeStrip>", false, true },
{"Release", "<WasmNativeStrip>true</WasmNativeStrip>", publish, true },
{"Debug", "<WasmNativeStrip>false</WasmNativeStrip>", true, false },
{"Release", "<WasmNativeStrip>false</WasmNativeStrip>", true, false }
{"Debug", "<WasmNativeStrip>true</WasmNativeStrip>", /*wasmBuildNative*/ false, /*wasmNativeStrip*/ true },
{"Release", "<WasmNativeStrip>true</WasmNativeStrip>", /*wasmBuildNative*/ publish, /*wasmNativeStrip*/ true },
{"Debug", "<WasmNativeStrip>false</WasmNativeStrip>", /*wasmBuildNative*/ true, /*wasmNativeStrip*/ false },
{"Release", "<WasmNativeStrip>false</WasmNativeStrip>", /*wasmBuildNative*/ true, /*wasmNativeStrip*/ false }
};

public static TheoryData<string, string, bool, bool> SetWasmNativeStripExplicitlyWithWasmBuildNativeTestData() => new()
Expand All @@ -147,48 +139,52 @@ public void DefaultsWithPublish(string config, string extraProperties, bool aot,
[MemberData(nameof(SetWasmNativeStripExplicitlyWithWasmBuildNativeTestData))]
public void WasmNativeStripDefaultWithBuild(string config, string extraProperties, bool expectedWasmBuildNativeValue, bool expectedWasmNativeStripValue)
{
string output = CheckWasmNativeDefaultValue("native_strip_defaults", config, extraProperties, aot: false, dotnetWasmFromRuntimePack: !expectedWasmBuildNativeValue, publish: false);
(string output, string? line) = CheckWasmNativeDefaultValue("native_strip_defaults", config, extraProperties, aot: false, dotnetWasmFromRuntimePack: !expectedWasmBuildNativeValue, publish: false);

Assert.Contains($"** WasmBuildNative: '{expectedWasmBuildNativeValue.ToString().ToLower()}', WasmNativeStrip: '{expectedWasmNativeStripValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output);
Assert.Contains("Stopping the build", output);
CheckPropertyValues(line,
wasmBuildNative: expectedWasmBuildNativeValue,
wasmNativeStrip: expectedWasmNativeStripValue,
wasmNativeDebugSymbols: true,
wasmBuildingForNestedPublish: null);
}

[Theory]
[MemberData(nameof(SetWasmNativeStripExplicitlyTestData), parameters: /*publish*/ true)]
[MemberData(nameof(SetWasmNativeStripExplicitlyWithWasmBuildNativeTestData))]
public void WasmNativeStripDefaultWithPublish(string config, string extraProperties, bool expectedWasmBuildNativeValue, bool expectedWasmNativeStripValue)
{
string output = CheckWasmNativeDefaultValue("native_strip_defaults", config, extraProperties, aot: false, dotnetWasmFromRuntimePack: !expectedWasmBuildNativeValue, publish: true);
(string output, string? line) = CheckWasmNativeDefaultValue("native_strip_defaults", config, extraProperties, aot: false, dotnetWasmFromRuntimePack: !expectedWasmBuildNativeValue, publish: true);

Assert.Contains($"** WasmBuildNative: '{expectedWasmBuildNativeValue.ToString().ToLower()}', WasmNativeStrip: '{expectedWasmNativeStripValue.ToString().ToLower()}', WasmBuildingForNestedPublish: 'true'", output);
Assert.Contains("Stopping the build", output);
CheckPropertyValues(line,
wasmBuildNative: expectedWasmBuildNativeValue,
wasmNativeStrip: expectedWasmNativeStripValue,
wasmNativeDebugSymbols: true,
wasmBuildingForNestedPublish: true);
}

[Theory]
/* always relink */
[InlineData("Debug", "", /*build*/ true, /*publish*/ true)]
[InlineData("Release", "", /*build*/ true, /*publish*/ true)]
[InlineData("Release", "<PublishTrimmed>false</PublishTrimmed>", /*build*/ true, /*publish*/ true)]
public void WithNativeReference(string config, string extraProperties, bool buildValue, bool publishValue)
[InlineData("Debug", "", /*publish*/ false)]
[InlineData("Debug", "", /*publish*/ true)]
[InlineData("Release", "", /*publish*/ false)]
[InlineData("Release", "", /*publish*/ true)]
[InlineData("Release", "<PublishTrimmed>false</PublishTrimmed>", /*publish*/ true)]
public void WithNativeReference(string config, string extraProperties, bool publish)
{
string nativeLibPath = Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", "native-lib.o");
string nativeRefItem = @$"<NativeFileReference Include=""{nativeLibPath}"" />";
string output = CheckWasmNativeDefaultValue("native_defaults_publish",
(string output, string? line) = CheckWasmNativeDefaultValue("native_defaults_publish",
config,
extraProperties,
aot: false,
dotnetWasmFromRuntimePack: !publishValue,
publish: true,
dotnetWasmFromRuntimePack: !publish,
publish: publish,
extraItems: nativeRefItem);

// for build - FIXME:
Assert.DoesNotContain($"** WasmBuildNative: '{buildValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output);
// for publish
Assert.Contains($"** WasmBuildNative: '{publishValue.ToString().ToLower()}', WasmNativeStrip: 'true', WasmBuildingForNestedPublish: 'true'", output);
Assert.Contains("Stopping the build", output);
InferAndCheckPropertyValues(line, isPublish: publish, wasmBuildNative: true, config: config);
}

private string CheckWasmNativeDefaultValue(string projectName,
private (string, string?) CheckWasmNativeDefaultValue(string projectName,
string config,
string extraProperties,
bool aot,
Expand All @@ -201,7 +197,7 @@ private string CheckWasmNativeDefaultValue(string projectName,

string printValueTarget = @"
<Target Name=""PrintWasmBuildNative"" AfterTargets=""_BeforeWasmBuildApp"">
<Message Text=""** WasmBuildNative: '$(WasmBuildNative)', WasmNativeStrip: '$(WasmNativeStrip)', WasmBuildingForNestedPublish: '$(WasmBuildingForNestedPublish)'"" Importance=""High"" />
<Message Text=""** WasmBuildNative: '$(WasmBuildNative)', WasmNativeStrip: '$(WasmNativeStrip)', WasmNativeDebugSymbols: '$(WasmNativeDebugSymbols)', WasmBuildingForNestedPublish: '$(WasmBuildingForNestedPublish)'"" Importance=""High"" />
" + (publish
? @"<Error Text=""Stopping the build"" Condition=""$(WasmBuildingForNestedPublish) == 'true'"" />"
: @"<Error Text=""Stopping the build"" />")
Expand All @@ -223,7 +219,32 @@ private string CheckWasmNativeDefaultValue(string projectName,
BuildOnlyAfterPublish: false,
Publish: publish));

return output;
Assert.Contains("Stopping the build", output);

Match m = s_regex.Match(output);
Assert.Equal(1, m.Groups.Count);
return (output, m.Success ? m.Groups[0]?.ToString() : null);
}

private void InferAndCheckPropertyValues(string? line, bool isPublish, bool wasmBuildNative, string config)
{
bool expectedWasmNativeStripValue;
if (!isPublish && wasmBuildNative && config == "Debug")
expectedWasmNativeStripValue = false;
else
expectedWasmNativeStripValue = true;

CheckPropertyValues(line, wasmBuildNative, expectedWasmNativeStripValue, /*wasmNativeDebugSymbols*/true, isPublish);
}

private void CheckPropertyValues(string? line, bool wasmBuildNative, bool wasmNativeStrip, bool wasmNativeDebugSymbols, bool? wasmBuildingForNestedPublish)
{
Assert.NotNull(line);
Assert.Contains($"** WasmBuildNative: '{wasmBuildNative.ToString().ToLower()}', " +
$"WasmNativeStrip: '{wasmNativeStrip.ToString().ToLower()}', " +
$"WasmNativeDebugSymbols: '{wasmNativeDebugSymbols.ToString().ToLower()}', " +
$"WasmBuildingForNestedPublish: '{(wasmBuildingForNestedPublish.HasValue && wasmBuildingForNestedPublish == true ? "true" : "")}'",
line);
}
}
}
28 changes: 16 additions & 12 deletions src/mono/wasm/build/WasmApp.Native.targets
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
$(_BeforeWasmBuildAppDependsOn);
_SetupEmscripten;
_SetWasmBuildNativeDefaults;
_SetWasmNativeStripDefault;
_ReadEmccProps
</_BeforeWasmBuildAppDependsOn>

Expand Down Expand Up @@ -119,6 +118,7 @@
<_BoolPropertiesThatTriggerRelinking Include="InvariantTimezone" DefaultValueInRuntimePack="false" />
<_BoolPropertiesThatTriggerRelinking Include="InvariantGlobalization" DefaultValueInRuntimePack="false" />
<_BoolPropertiesThatTriggerRelinking Include="WasmNativeStrip" DefaultValueInRuntimePack="true" />
<!--<_BoolPropertiesThatTriggerRelinking Include="WasmNativeDebugSymbols" DefaultValueInRuntimePack="true" />-->
</ItemGroup>

<PropertyGroup>
Expand All @@ -133,7 +133,6 @@
<WasmBuildNative Condition="'$(RunAOTCompilation)' == 'true' and '$(RunAOTCompilationAfterBuild)' == 'true'">true</WasmBuildNative>

<WasmBuildNative Condition="'$(WasmBuildNative)' == '' and @(NativeFileReference->Count()) > 0" >true</WasmBuildNative>
<WasmBuildNative Condition="'$(WasmBuildNative)' == ''">false</WasmBuildNative>
</PropertyGroup>

<!-- When Publishing -->
Expand All @@ -147,10 +146,23 @@

<!-- default to relinking in Release config -->
<WasmBuildNative Condition="'$(WasmBuildNative)' == '' and '$(Configuration)' == 'Release'">true</WasmBuildNative>
</PropertyGroup>

<PropertyGroup>
<WasmBuildNative Condition="'$(WasmBuildNative)' == ''">false</WasmBuildNative>
</PropertyGroup>

<!-- Default with nothing set: Build+relink+config=debug -->
<PropertyGroup Condition="'$(WasmNativeDebugSymbols)' == '' and '$(WasmNativeStrip)' == '' and '$(WasmBuildingForNestedPublish)' != 'true' and '$(WasmBuildNative)' == 'true' and '$(Configuration)' == 'Debug'">
<WasmNativeDebugSymbols>true</WasmNativeDebugSymbols>
<WasmNativeStrip>false</WasmNativeStrip>
</PropertyGroup>

<PropertyGroup>
<WasmNativeDebugSymbols Condition="'$(WasmNativeDebugSymbols)' == ''">true</WasmNativeDebugSymbols>
<WasmNativeStrip Condition="'$(WasmNativeStrip)' == ''">true</WasmNativeStrip>
</PropertyGroup>

<!-- If we want to default to true, and sdk is missing, then just warn, and set it to false -->
<Warning Condition="'$(WasmBuildNative)' == 'true' and '$(_IsEMSDKMissing)' == 'true'"
Text="$(_EMSDKMissingErrorMessage) Emscripten SDK is required for building native files." />
Expand All @@ -160,14 +172,6 @@
</PropertyGroup>
</Target>

<Target Name="_SetWasmNativeStripDefault" Condition="'$(WasmNativeStrip)' == ''">
<PropertyGroup>
<!-- Build+relink+config=debug -->
<WasmNativeStrip Condition="'$(WasmBuildingForNestedPublish)' != 'true' and '$(WasmBuildNative)' == 'true' and '$(Configuration)' == 'Debug'">false</WasmNativeStrip>
<WasmNativeStrip Condition="'$(WasmNativeStrip)' == ''">true</WasmNativeStrip>
</PropertyGroup>
</Target>

<Target Name="_WasmBuildNativeCore" DependsOnTargets="$(_WasmBuildNativeCoreDependsOn)" Condition="'$(WasmBuildNative)' == 'true'" />

<Target Name="_PrepareForWasmBuildNative">
Expand All @@ -178,7 +182,6 @@
<_MonoAotCrossCompilerPath>@(MonoAotCrossCompiler->WithMetadataValue('RuntimeIdentifier','browser-wasm'))</_MonoAotCrossCompilerPath>
<_EmccDefaultFlagsRsp>$([MSBuild]::NormalizePath($(_WasmRuntimePackSrcDir), 'emcc-default.rsp'))</_EmccDefaultFlagsRsp>
<_EmccDefaultLinkFlagsRsp>$([MSBuild]::NormalizePath($(_WasmRuntimePackSrcDir), 'emcc-link.rsp'))</_EmccDefaultLinkFlagsRsp>
<WasmNativeDebugSymbols Condition="'$(WasmNativeDebugSymbols)' == ''">true</WasmNativeDebugSymbols>
<WasmLinkIcalls Condition="'$(WasmLinkIcalls)' == ''">$(WasmBuildNative)</WasmLinkIcalls>

<_WasmICallTablePath>$(_WasmIntermediateOutputPath)icall-table.h</_WasmICallTablePath>
Expand Down Expand Up @@ -221,7 +224,7 @@

<_EmccCommonFlags Include="$(_DefaultEmccFlags)" />
<_EmccCommonFlags Include="$(EmccFlags)" />
<_EmccCommonFlags Include="-g" Condition="'$(WasmNativeDebugSymbols)' == 'true'" />
<_EmccCommonFlags Include="-g" Condition="'$(WasmNativeStrip)' == 'false'" />
<_EmccCommonFlags Include="-v" Condition="'$(EmccVerbose)' != 'false'" />
<_EmccCommonFlags Include="-s DISABLE_EXCEPTION_CATCHING=0" Condition="'$(WasmEnableExceptionHandling)' == 'false'" />
<_EmccCommonFlags Include="-fwasm-exceptions" Condition="'$(WasmEnableExceptionHandling)' == 'true'" />
Expand Down Expand Up @@ -249,6 +252,7 @@
<_EmccCFlags Include="-emit-llvm" />

<_EmccCFlags Include="&quot;-I%(_EmccIncludePaths.Identity)&quot;" />
<_EmccCFlags Include="-g" Condition="'$(WasmNativeDebugSymbols)' == 'true'" />

<!-- Adding optimization flag at the top, so it gets precedence -->
<_EmccLDFlags Include="$(EmccLinkOptimizationFlag)" />
Expand Down
4 changes: 3 additions & 1 deletion src/mono/wasm/runtime/es6/dotnet.es6.pre.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
if (_nativeModuleLoaded) throw new Error("Native module already loaded");
_nativeModuleLoaded = true;
createDotnetRuntime = Module = createDotnetRuntime(Module);
createDotnetRuntime = Module = createDotnetRuntime(Module);
Module["getWasmIndirectFunctionTable"] = function () { return wasmTable; }
Module["getMemory"] = function () { return wasmMemory; }
Loading