diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets
index 1e1c86695796ed4c6f4e2031795992234ae0a3b5..de4432bee9f5eae9c96dc2af3bd680cd44300c2e 100644
--- a/eng/testing/tests.wasm.targets
+++ b/eng/testing/tests.wasm.targets
@@ -69,8 +69,7 @@
-
-
+
@@ -131,17 +130,17 @@
-1
-
-
-
+
+ <_SatelliteAssemblies Include="$(PublishDir)*\*.resources.dll" />
+ <_SatelliteAssemblies CultureName="$([System.IO.Directory]::GetParent('%(Identity)').Name)" />
+ <_SatelliteAssemblies TargetPath="%(CultureName)\%(FileName)%(Extension)" />
-
+
+
+
+
-
<_CopyLocalPaths
Include="@(PublishItemsOutputGroupOutputs)"
diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets
index b16195a618af12d64e59a286cd9982581c9c0bb2..b6897fbd2b413b389c2a42733863e11c385894f8 100644
--- a/src/mono/wasm/build/WasmApp.Native.targets
+++ b/src/mono/wasm/build/WasmApp.Native.targets
@@ -353,6 +353,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_
@(MonoAOTCompilerDefaultAotArguments, ';')
@(MonoAOTCompilerDefaultProcessArguments, ';')
+
<_AOT_InternalForceInterpretAssemblies Include="@(_WasmAssembliesInternal->WithMetadataValue('_InternalForceInterpret', 'true'))" />
<_WasmAssembliesInternal Remove="@(_WasmAssembliesInternal)" />
@@ -422,9 +423,6 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_
<_WasmNativeFileForLinking Include="@(_BitcodeFile)" />
-
-
diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets
index b886f327d716265f4491c98cd1074c9fbd7871eb..034287436892bf7fd4a5ef8f9616f9a793e0a147 100644
--- a/src/mono/wasm/build/WasmApp.targets
+++ b/src/mono/wasm/build/WasmApp.targets
@@ -61,7 +61,6 @@
Public items:
- @(WasmExtraFilesToDeploy) - Files to copy to $(WasmAppDir).
(relative path can be set via %(TargetPath) metadata)
- - @(WasmSatelliteAssemblies)
- @(WasmFilesToIncludeInFileSystem) - Files to include in the vfs
- @(WasmNativeAsset) - Native files to be added to `NativeAssets` in the bundle.
@@ -115,6 +114,13 @@
<_WasmAssembliesInternal Include="@(WasmAssembliesToBundle->Distinct())" />
+
+ <_WasmSatelliteAssemblies Include="@(_WasmAssembliesInternal)" />
+ <_WasmSatelliteAssemblies Remove="@(_WasmSatelliteAssemblies)" Condition="!$([System.String]::Copy('%(Identity)').EndsWith('.resources.dll'))" />
+
+ <_WasmSatelliteAssemblies CultureName="$([System.IO.Directory]::GetParent('%(Identity)').Name)" />
+
+ <_WasmAssembliesInternal Remove="@(_WasmSatelliteAssemblies)" />
@@ -142,7 +148,7 @@
MainJS="$(WasmMainJSPath)"
Assemblies="@(_WasmAssembliesInternal)"
InvariantGlobalization="$(InvariantGlobalization)"
- SatelliteAssemblies="@(WasmSatelliteAssemblies)"
+ SatelliteAssemblies="@(_WasmSatelliteAssemblies)"
FilesToIncludeInFileSystem="@(WasmFilesToIncludeInFileSystem)"
IcuDataFileName="$(WasmIcuDataFileName)"
RemoteSources="@(WasmRemoteSources)"
@@ -193,11 +199,5 @@
-
-
-
diff --git a/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj b/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj
index 0a0b915ad43cea2844a8865e5cd8f2bc9790843e..cdd5e95a4e2108d1dcbdabce31ed4b960495bbfe 100644
--- a/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj
+++ b/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj
@@ -33,17 +33,15 @@
-
-
-
-
+
<_ExtraFiles Include="$(ExtraFilesPath)**\*" />
- <_SatelliteAssembliesForVFS Include="@(WasmSatelliteAssemblies)" />
+ <_SatelliteAssembliesForVFS Include="$(OriginalPublishDir)**\*.resources.dll" />
+ <_SatelliteAssembliesForVFS CultureName="$([System.IO.Directory]::GetParent('%(Identity)').Name)" />
<_SatelliteAssembliesForVFS TargetPath="%(CultureName)\%(FileName)%(Extension)" />
diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
index 49d984490a64b2c0faf5a8a0cbe7f94fae584814..660272e268aa41f4092edf1311b151a274c3b296 100644
--- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
+++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
@@ -189,6 +189,13 @@ public override bool Execute ()
{
string culture = assembly.GetMetadata("CultureName") ?? string.Empty;
string fullPath = assembly.GetMetadata("Identity");
+ if (string.IsNullOrEmpty(culture))
+ {
+ Log.LogWarning($"Missing CultureName metadata for satellite assembly {fullPath}");
+ continue;
+ }
+ // FIXME: validate the culture?
+
string name = Path.GetFileName(fullPath);
string directory = Path.Combine(AppDir, config.AssemblyRoot, culture);
Directory.CreateDirectory(directory);
diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs
index 99e721dfa65f78336c0ed546f1633969f23d1b3e..b87ff5c70bfc24ed1e74e23891e73f5ed2712e10 100644
--- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs
+++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs
@@ -8,9 +8,11 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Text;
using Xunit;
using Xunit.Abstractions;
+using Xunit.Sdk;
#nullable enable
@@ -29,7 +31,6 @@ public abstract class BuildTestBase : IClassFixture test, string? buildDir=null, int expectedExitCode=0, string? args=null)
+ protected string RunAndTestWasmApp(BuildArgs buildArgs,
+ RunHost host,
+ string id,
+ Action? test=null,
+ string? buildDir = null,
+ int expectedExitCode = 0,
+ string? args = null,
+ Dictionary? envVars = null)
{
buildDir ??= _projectDir;
- Dictionary? envVars = new();
+ envVars ??= new();
envVars["XHARNESS_DISABLE_COLORED_OUTPUT"] = "true";
if (buildArgs.AOT)
{
@@ -180,6 +188,11 @@ protected void RunAndTestWasmApp(BuildArgs buildArgs, RunHost host, string id, A
Assert.DoesNotContain("AOT: image 'System.Private.CoreLib' found.", output);
Assert.DoesNotContain($"AOT: image '{buildArgs.ProjectName}' found.", output);
}
+
+ if (test != null)
+ test(output);
+
+ return output;
}
protected static string RunWithXHarness(string testCommand, string testLogPath, string projectName, string bundleDir,
@@ -209,6 +222,8 @@ protected void RunAndTestWasmApp(BuildArgs buildArgs, RunHost host, string id, A
args.Append($" --run {projectName}.dll");
args.Append($" {appArgs ?? string.Empty}");
+ _testOutput.WriteLine(string.Empty);
+ _testOutput.WriteLine($"---------- Running with {testCommand} ---------");
var (exitCode, output) = RunProcess("dotnet", _testOutput,
args: args.ToString(),
workingDir: bundleDir,
@@ -251,14 +266,21 @@ protected static void InitProjectDir(string dir)
runtime-test.js
##EXTRA_PROPERTIES##
+
+ ##EXTRA_ITEMS##
+
+ ##INSERT_AT_END##
";
- protected static BuildArgs GetBuildArgsWith(BuildArgs buildArgs, string? extraProperties=null, string projectTemplate=SimpleProjectTemplate)
+ protected static BuildArgs ExpandBuildArgs(BuildArgs buildArgs, string extraProperties="", string extraItems="", string insertAtEnd="", string projectTemplate=SimpleProjectTemplate)
{
if (buildArgs.AOT)
- extraProperties = $"{extraProperties}\ntrue\n";
+ extraProperties = $"{extraProperties}\ntrue\nfalse\n";
- string projectContents = projectTemplate.Replace("##EXTRA_PROPERTIES##", extraProperties ?? string.Empty);
+ string projectContents = projectTemplate
+ .Replace("##EXTRA_PROPERTIES##", extraProperties)
+ .Replace("##EXTRA_ITEMS##", extraItems)
+ .Replace("##INSERT_AT_END##", insertAtEnd);
return buildArgs with { ProjectFileContents = projectContents };
}
@@ -273,10 +295,10 @@ protected static BuildArgs GetBuildArgsWith(BuildArgs buildArgs, string? extraPr
{
if (useCache && _buildContext.TryGetBuildFor(buildArgs, out BuildProduct? product))
{
- Console.WriteLine ($"Using existing build found at {product.BuildPath}, with build log at {product.LogFile}");
+ Console.WriteLine ($"Using existing build found at {product.ProjectDir}, with build log at {product.LogFile}");
- Assert.True(product.Result, $"Found existing build at {product.BuildPath}, but it had failed. Check build log at {product.LogFile}");
- _projectDir = product.BuildPath;
+ Assert.True(product.Result, $"Found existing build at {product.ProjectDir}, but it had failed. Check build log at {product.LogFile}");
+ _projectDir = product.ProjectDir;
// use this test's id for the run logs
_logPath = Path.Combine(s_logRoot, id);
@@ -297,7 +319,6 @@ protected static BuildArgs GetBuildArgsWith(BuildArgs buildArgs, string? extraPr
throw new Exception("_projectDir should be set, to use createProject=false");
}
-
StringBuilder sb = new();
sb.Append("publish");
sb.Append(s_defaultBuildArgs);
@@ -305,6 +326,7 @@ protected static BuildArgs GetBuildArgsWith(BuildArgs buildArgs, string? extraPr
sb.Append($" /p:Configuration={buildArgs.Config}");
string logFilePath = Path.Combine(_logPath, $"{buildArgs.ProjectName}.binlog");
+ _testOutput.WriteLine($"-------- Building ---------");
_testOutput.WriteLine($"Binlog path: {logFilePath}");
sb.Append($" /bl:\"{logFilePath}\" /v:minimal /nologo");
if (buildArgs.ExtraBuildArgs != null)
@@ -378,8 +400,14 @@ protected static void AssertDotNetWasmJs(string bundleDir, bool fromRuntimePack)
{
string nativeDir = GetRuntimeNativeDir();
- AssertFile(Path.Combine(nativeDir, "dotnet.wasm"), Path.Combine(bundleDir, "dotnet.wasm"), "Expected dotnet.wasm to be same as the runtime pack", same: fromRuntimePack);
- AssertFile(Path.Combine(nativeDir, "dotnet.js"), Path.Combine(bundleDir, "dotnet.js"), "Expected dotnet.js to be same as the runtime pack", same: fromRuntimePack);
+ AssertNativeFile("dotnet.wasm");
+ AssertNativeFile("dotnet.js");
+
+ void AssertNativeFile(string file)
+ => AssertFile(Path.Combine(nativeDir, file),
+ Path.Combine(bundleDir, file),
+ $"Expected {file} to be {(fromRuntimePack ? "the same as" : "different from")} the runtime pack",
+ same: fromRuntimePack);
}
protected static void AssertFilesDontExist(string dir, string[] filenames, string? label = null)
@@ -464,6 +492,7 @@ protected static string GetRuntimeNativeDir()
_testOutput.WriteLine($"Running {path} {args}");
Console.WriteLine($"Running: {path}: {args}");
Console.WriteLine($"WorkingDirectory: {workingDir}");
+ _testOutput.WriteLine($"WorkingDirectory: {workingDir}");
StringBuilder outputBuilder = new ();
var processStartInfo = new ProcessStartInfo
{
@@ -584,7 +613,7 @@ public static int Main()
-
+
@@ -594,5 +623,5 @@ public static int Main()
}
public record BuildArgs(string ProjectName, string Config, bool AOT, string ProjectFileContents, string? ExtraBuildArgs);
- public record BuildProduct(string BuildPath, string LogFile, bool Result);
+ public record BuildProduct(string ProjectDir, string LogFile, bool Result);
}
diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs
index 6d01f20a8420e89f3976393104c7d487873acbfe..753f8c40c2af7dd9af1c93ffc63b935135d934e9 100644
--- a/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs
+++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs
@@ -49,7 +49,7 @@ public void RelinkingWithoutAOT(BuildArgs buildArgs, bool? invariantGlobalizatio
extraProperties = $"{extraProperties}{invariantGlobalization}";
buildArgs = buildArgs with { ProjectName = projectName };
- buildArgs = GetBuildArgsWith(buildArgs, extraProperties);
+ buildArgs = ExpandBuildArgs(buildArgs, extraProperties);
if (dotnetWasmFromRuntimePack == null)
dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release");
@@ -76,8 +76,8 @@ public static int Main()
hasIcudt: invariantGlobalization == null || invariantGlobalization.Value == false);
string expectedOutputString = invariantGlobalization == true
- ? "False - en (ES)"
- : "True - Invariant Language (Invariant Country)";
+ ? "True - Invariant Language (Invariant Country)"
+ : "False - es (ES)";
RunAndTestWasmApp(buildArgs, expectedExitCode: 42,
test: output => Assert.Contains(expectedOutputString, output), host: host, id: id);
}
diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs
index df920577cea01b006d3e29e85e4e068c2248a50c..b97a0490d2e872759247fd71662458193098aa02 100644
--- a/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs
+++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs
@@ -77,7 +77,7 @@ public static int Main(string[] args)
string programText = projectContents.Replace("##CODE##", code);
buildArgs = buildArgs with { ProjectName = projectName, ProjectFileContents = programText };
- buildArgs = GetBuildArgsWith(buildArgs);
+ buildArgs = ExpandBuildArgs(buildArgs);
if (dotnetWasmFromRuntimePack == null)
dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release");
diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs
index da7b33d0a0c351ad4f66afc43033c1fd90e8e124..9f87757175c970416d21fd0ba5b39eb096ad7d11 100644
--- a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs
+++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs
@@ -39,7 +39,7 @@ public void Relinking_ErrorWhenMissingEMSDK(BuildArgs buildArgs, string emsdkPat
ProjectName = projectName,
ExtraBuildArgs = $"/p:EMSDK_PATH={emsdkPath}"
};
- buildArgs = GetBuildArgsWith(buildArgs, extraProperties: "true");
+ buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "true");
(_, string buildOutput) = BuildProject(buildArgs,
initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42),
@@ -54,7 +54,7 @@ private void NativeBuild(string projectNamePrefix, string projectContents, Build
string projectName = $"{projectNamePrefix}_{buildArgs.Config}_{buildArgs.AOT}";
buildArgs = buildArgs with { ProjectName = projectName, ProjectFileContents = projectContents };
- buildArgs = GetBuildArgsWith(buildArgs, extraProperties: "true");
+ buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "true");
Console.WriteLine ($"-- args: {buildArgs}, name: {projectName}");
BuildProject(buildArgs,
diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs
index aebaa43ba5d97dccf2607e3c7c0b0de184f8ab69..ecbcbdd75c05c29b490bc88f2cbc0e7d147b7387 100644
--- a/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs
+++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs
@@ -27,7 +27,7 @@ public void NoOpRebuild(BuildArgs buildArgs, bool nativeRelink, RunHost host, st
bool dotnetWasmFromRuntimePack = !nativeRelink && !buildArgs.AOT;
buildArgs = buildArgs with { ProjectName = projectName };
- buildArgs = GetBuildArgsWith(buildArgs, $"{(nativeRelink ? "true" : "false")}");
+ buildArgs = ExpandBuildArgs(buildArgs, $"{(nativeRelink ? "true" : "false")}");
BuildProject(buildArgs,
initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42),
diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e9d973650dcae62955b05af0bcec72bc67a6c177
--- /dev/null
+++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs
@@ -0,0 +1,179 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Xunit;
+using Xunit.Abstractions;
+
+#nullable enable
+
+namespace Wasm.Build.Tests
+{
+ public class SatelliteAssembliesTests : BuildTestBase
+ {
+ public SatelliteAssembliesTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
+ : base(output, buildContext)
+ {
+ }
+
+ public static IEnumerable