diff --git a/eng/Versions.props b/eng/Versions.props
index 0b744bf6591a6..c3c03de846f9a 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -263,5 +263,6 @@
$(runtimewinx64MicrosoftNETCoreRuntimeWasmNodeTransportPackageVersion)
3.1.56
+ 9.0.0-rc.1.24413.1
diff --git a/eng/testing/scenarios/BuildWasiAppsJobsList.txt b/eng/testing/scenarios/BuildWasiAppsJobsList.txt
index 86c0517585a48..4ddb5b555ba1a 100644
--- a/eng/testing/scenarios/BuildWasiAppsJobsList.txt
+++ b/eng/testing/scenarios/BuildWasiAppsJobsList.txt
@@ -1,7 +1 @@
-Wasi.Build.Tests.InvariantTests
-Wasi.Build.Tests.ILStripTests
-Wasi.Build.Tests.SdkMissingTests
-Wasi.Build.Tests.RuntimeConfigTests
-Wasi.Build.Tests.WasiTemplateTests
-Wasi.Build.Tests.PInvokeTableGeneratorTests
-Wasi.Build.Tests.WasiLibraryModeTests
+Wasi.Build.Tests.NativeAOTTests
diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt
index 818ff9e8edd3c..e2b91416b20bc 100644
--- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt
+++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt
@@ -1,52 +1,2 @@
-Wasm.Build.NativeRebuild.Tests.FlagsChangeRebuildTests
-Wasm.Build.NativeRebuild.Tests.NoopNativeRebuildTest
-Wasm.Build.NativeRebuild.Tests.OptimizationFlagChangeTests
-Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest
-Wasm.Build.NativeRebuild.Tests.SimpleSourceChangeRebuildTest
-Wasm.Build.Tests.TestAppScenarios.InterpPgoTests
-Wasm.Build.Templates.Tests.NativeBuildTests
-Wasm.Build.Tests.Blazor.AppsettingsTests
-Wasm.Build.Tests.Blazor.BuildPublishTests
-Wasm.Build.Tests.Blazor.SimpleRunTests
-Wasm.Build.Tests.Blazor.CleanTests
-Wasm.Build.Tests.Blazor.MiscTests
-Wasm.Build.Tests.Blazor.MiscTests2
-Wasm.Build.Tests.Blazor.MiscTests3
-Wasm.Build.Tests.Blazor.NativeTests
-Wasm.Build.Tests.Blazor.NoopNativeRebuildTest
-Wasm.Build.Tests.Blazor.WorkloadRequiredTests
-Wasm.Build.Tests.Blazor.IcuTests
-Wasm.Build.Tests.Blazor.IcuShardingTests
-Wasm.Build.Tests.Blazor.SignalRClientTests
-Wasm.Build.Tests.BuildPublishTests
-Wasm.Build.Tests.ConfigSrcTests
-Wasm.Build.Tests.HybridGlobalizationTests
-Wasm.Build.Tests.IcuShardingTests
-Wasm.Build.Tests.IcuShardingTests2
-Wasm.Build.Tests.IcuTests
-Wasm.Build.Tests.InvariantGlobalizationTests
-Wasm.Build.Tests.InvariantTimezoneTests
-Wasm.Build.Tests.MainWithArgsTests
-Wasm.Build.Tests.NativeBuildTests
-Wasm.Build.Tests.NativeLibraryTests
-Wasm.Build.Tests.NonWasmTemplateBuildTests
-Wasm.Build.Tests.PInvokeTableGeneratorTests
-Wasm.Build.Tests.RebuildTests
-Wasm.Build.Tests.SatelliteAssembliesTests
-Wasm.Build.Tests.TestAppScenarios.AppSettingsTests
-Wasm.Build.Tests.TestAppScenarios.DownloadThenInitTests
-Wasm.Build.Tests.TestAppScenarios.LazyLoadingTests
-Wasm.Build.Tests.TestAppScenarios.LibraryInitializerTests
-Wasm.Build.Tests.TestAppScenarios.SatelliteLoadingTests
-Wasm.Build.Tests.TestAppScenarios.ModuleConfigTests
-Wasm.Build.Tests.TestAppScenarios.MemoryTests
-Wasm.Build.Tests.AspNetCore.SignalRClientTests
-Wasm.Build.Tests.WasmBuildAppTest
-Wasm.Build.Tests.WasmNativeDefaultsTests
-Wasm.Build.Tests.WasmRunOutOfAppBundleTests
-Wasm.Build.Tests.WasmSIMDTests
-Wasm.Build.Tests.WasmTemplateTests
-Wasm.Build.Tests.WorkloadTests
-Wasm.Build.Tests.MT.Blazor.SimpleMultiThreadedTests
-Wasm.Build.Tests.TestAppScenarios.WasmSdkDebugLevelTests
-Wasm.Build.Tests.TestAppScenarios.WasmAppBuilderDebugLevelTests
+Wasm.Build.Tests.NativeAOTTests
+
diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest.pkgproj b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest.pkgproj
index f489f65e443a6..2c68ce9127dce 100644
--- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest.pkgproj
+++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest.pkgproj
@@ -53,6 +53,7 @@
<_WorkloadManifestValues Include="PackageVersionNet6" Value="$(PackageVersionNet6)" />
<_WorkloadManifestValues Include="NetCoreAppCurrent" Value="$(NetCoreAppCurrent)" />
<_WorkloadManifestValues Include="EmscriptenVersion" Value="$(MicrosoftNETRuntimeEmscriptenVersion)" />
+ <_WorkloadManifestValues Include="WasmExperimentalNativeAOTLLVMILCompilerVersion" Value="$(WasmExperimentalNativeAOTLLVMILCompilerVersion)" />
+ <_IsUsingNativeAOT Condition="'$(PublishAot)' == 'true'">true
<_RuntimePackInWorkloadVersionCurrent>${PackageVersion}
<_RuntimePackInWorkloadVersion8>${PackageVersionNet8}
<_RuntimePackInWorkloadVersion7>${PackageVersionNet7}
@@ -66,8 +67,27 @@
$(WasmNativeWorkloadAvailable)
+
+ false
+ false
+ false
+ true
+ false
+ ${WasmExperimentalNativeAOTLLVMILCompilerVersion}
+
+
+
+
+
+
+
-
+
<_IsAndroidLibraryMode Condition="'$(RuntimeIdentifier)' == 'android-arm64' or '$(RuntimeIdentifier)' == 'android-arm' or '$(RuntimeIdentifier)' == 'android-x64' or '$(RuntimeIdentifier)' == 'android-x86'">true
<_IsAppleMobileLibraryMode Condition="'$(RuntimeIdentifier)' == 'ios-arm64' or '$(RuntimeIdentifier)' == 'iossimulator-arm64' or '$(RuntimeIdentifier)' == 'iossimulator-x64' or '$(RuntimeIdentifier)' == 'maccatalyst-arm64' or '$(RuntimeIdentifier)' == 'maccatalyst-x64' or '$(RuntimeIdentifier)' == 'tvos-arm64'">true
<_IsiOSLibraryMode Condition="'$(RuntimeIdentifier)' == 'ios-arm64' or '$(RuntimeIdentifier)' == 'iossimulator-arm64' or '$(RuntimeIdentifier)' == 'iossimulator-x64'">true
@@ -187,7 +207,7 @@
Microsoft.NETCore.App.Runtime.Mono.multithread.**RID**
-
+
$(_MonoWorkloadRuntimePackPackageVersion)
diff --git a/src/mono/wasi/Wasi.Build.Tests/NativeAOTTests.cs b/src/mono/wasi/Wasi.Build.Tests/NativeAOTTests.cs
new file mode 100644
index 0000000000000..967f291b45036
--- /dev/null
+++ b/src/mono/wasi/Wasi.Build.Tests/NativeAOTTests.cs
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Wasm.Build.Tests;
+using Xunit;
+using Xunit.Abstractions;
+using Xunit.Sdk;
+
+#nullable enable
+
+namespace Wasi.Build.Tests;
+
+public class NativeAOTTests : BuildTestBase
+{
+ public NativeAOTTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
+ : base(output, buildContext)
+ {
+ }
+
+ [Fact]
+ public void PublishAndRun()
+ {
+ const string config = "Release";
+ string id = $"nativeaot_{GetRandomId()}";
+ string projectFile = CreateWasmTemplateProject(id, "wasiconsole");
+ string projectName = Path.GetFileNameWithoutExtension(projectFile);
+
+ string programCsContent = File.ReadAllText(Path.Combine(BuildEnvironment.TestAssetsPath, "SimpleMainWithArgs.cs"));
+ programCsContent = programCsContent.Replace("return 42;", "return 0;");
+ File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programCsContent);
+ File.Delete(Path.Combine(_projectDir!, "runtimeconfig.template.json"));
+
+ var buildArgs = ExpandBuildArgs(new BuildArgs(projectName, config, AOT: false, id, null));
+
+ AddItemsPropertiesToProject(projectFile, extraProperties:
+ """
+ $(RestoreAdditionalProjectSources);https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json
+ true
+ """
+ );
+
+ try
+ {
+ bool isWindowsPlatform = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ (_, string buildOutput) = BuildProject(
+ buildArgs,
+ id: id,
+ new BuildProjectOptions(
+ AssertAppBundle: false,
+ CreateProject: false,
+ Publish: true,
+ TargetFramework: DefaultTargetFramework,
+ ExpectSuccess: isWindowsPlatform
+ )
+ );
+
+ if (isWindowsPlatform)
+ {
+ string outputDir = Path.Combine(_projectDir!, "bin", config, DefaultTargetFramework, BuildEnvironment.DefaultRuntimeIdentifier, "native");
+ string outputFileName = $"{id}.wasm";
+
+ Assert.True(File.Exists(Path.Combine(outputDir, outputFileName)), $"Expected {outputFileName} to exist in {outputDir}");
+ Assert.Contains("Generating native code", buildOutput);
+
+ using var runCommand = new ToolCommand(BuildEnvironment.GetExecutableName(@"wasmtime"), _testOutput)
+ .WithWorkingDirectory(outputDir);
+
+ var result = runCommand.Execute(outputFileName).EnsureSuccessful();
+ Assert.Contains("Hello, Wasi Console!", result.Output);
+ }
+ else
+ {
+ Assert.Contains("NETSDK1204", buildOutput); // Ahead-of-time compilation is not supported on the current platform 'linux-x64'
+ }
+ }
+ finally
+ {
+ _testOutput.WriteLine($"Content of {_nugetPackagesDir}");
+ foreach (string file in Directory.EnumerateFiles(_nugetPackagesDir, "*", SearchOption.AllDirectories))
+ _testOutput.WriteLine(file);
+ }
+ }
+}
diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
index 3dc64bc556d53..bf95b81e070e0 100644
--- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
@@ -166,7 +166,10 @@ public BuildTestBase(ProjectProviderBase providerBase, ITestOutputHelper output,
var cmd = new DotNetCommand(s_buildEnv, _testOutput)
.WithWorkingDirectory(_projectDir!)
.WithEnvironmentVariable("NUGET_PACKAGES", _nugetPackagesDir)
- .WithEnvironmentVariables(buildProjectOptions.ExtraBuildEnvironmentVariables);
+ .WithEnvironmentVariables(buildProjectOptions.ExtraBuildEnvironmentVariables)
+ .WithEnvironmentVariable("COREHOST_TRACE", "1")
+ .WithEnvironmentVariable("COREHOST_TRACEFILE", Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT") ?? string.Empty)
+ .WithEnvironmentVariable("COREHOST_TRACE_VERBOSITY", "4");
if (UseWBTOverridePackTargets && s_buildEnv.IsWorkload)
cmd.WithEnvironmentVariable("WBTOverrideRuntimePack", "true");
diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs b/src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs
index 0b71e4d663015..fe9084b71c2f1 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs
@@ -140,9 +140,7 @@ public BuildEnvironment()
EnvVars["WasmFingerprintAssets"] = "false";
}
- DotNet = Path.Combine(sdkForWorkloadPath!, "dotnet");
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- DotNet += ".exe";
+ DotNet = GetExecutableName(Path.Combine(sdkForWorkloadPath!, "dotnet"));
if (!string.IsNullOrEmpty(EnvironmentVariables.TestLogPath))
{
@@ -185,5 +183,13 @@ public bool IsMultiThreadingRuntimePackAvailableFor(string tfm)
protected static string s_directoryBuildPropsForLocal = File.ReadAllText(Path.Combine(TestDataPath, "Local.Directory.Build.props"));
protected static string s_directoryBuildTargetsForLocal = File.ReadAllText(Path.Combine(TestDataPath, "Local.Directory.Build.targets"));
+
+ public static string GetExecutableName(string nameOrPath)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ nameOrPath += ".exe";
+
+ return nameOrPath;
+ }
}
}
diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/NativeAOTTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/NativeAOTTests.cs
new file mode 100644
index 0000000000000..32c1069fdc4d2
--- /dev/null
+++ b/src/mono/wasm/Wasm.Build.Tests/Templates/NativeAOTTests.cs
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Wasm.Build.Tests.Blazor;
+using Xunit;
+using Xunit.Abstractions;
+using Xunit.Sdk;
+
+#nullable enable
+
+namespace Wasm.Build.Tests;
+
+public class NativeAOTTests : BlazorWasmTestBase
+{
+ public NativeAOTTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
+ : base(output, buildContext)
+ {
+ }
+
+ [Theory]
+ [InlineData("NativeAOT")]
+ public async Task PublishAndRun(string assetName)
+ {
+ string config = "Release";
+ string id = $"browser_{config}_{GetRandomId()}";
+
+ InitBlazorWasmProjectDir(id);
+ Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, assetName), Path.Combine(_projectDir!));
+ string projectName = Path.GetFileNameWithoutExtension(_projectDir!);
+
+ try
+ {
+ bool isWindowsPlatform = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ (_, string buildOutput) = BuildTemplateProject(
+ ExpandBuildArgs(new BuildArgs(projectName, config, AOT: false, id, null)),
+ id: id,
+ new BuildProjectOptions(
+ AssertAppBundle: false,
+ CreateProject: false,
+ Publish: true,
+ TargetFramework: DefaultTargetFramework,
+ ExpectSuccess: isWindowsPlatform
+ )
+ );
+
+ if (isWindowsPlatform)
+ {
+ string outputDir = Path.Combine(_projectDir!, "bin", config, DefaultTargetFramework, BuildEnvironment.DefaultRuntimeIdentifier, "native");
+
+ List consoleOutput = new();
+ BlazorRunOptions blazorRunOptions = new(
+ CheckCounter: false,
+ Config: config,
+ OnConsoleMessage: (_, message) => consoleOutput.Add(message.Text),
+ Host: BlazorRunHost.WebServer
+ );
+ await BlazorRunTest($"{s_xharnessRunnerCommand} wasm webserver --app=. --web-server-use-default-files", outputDir, blazorRunOptions);
+
+ Assert.True(consoleOutput.Contains("Hello, NativeAOT!"), $"Expected 'Hello, NativeAOT!' wasn't emitted by the test app. Output was: {String.Join(", ", consoleOutput)}");
+ }
+ else
+ {
+ Assert.Contains("NETSDK1204", buildOutput); // Ahead-of-time compilation is not supported on the current platform 'linux-x64'
+ }
+ }
+ finally
+ {
+ _testOutput.WriteLine($"Is64BitProcess '{Environment.Is64BitProcess}', Is64BitOperatingSystem '{Environment.Is64BitOperatingSystem}', OSVersion '{Environment.OSVersion}'");
+ _testOutput.WriteLine($"Content of {_nugetPackagesDir}");
+ foreach (string file in Directory.EnumerateFiles(_nugetPackagesDir, "*", SearchOption.AllDirectories))
+ _testOutput.WriteLine(file);
+ }
+ }
+}
diff --git a/src/mono/wasm/testassets/NativeAOT/NativeAOT.csproj b/src/mono/wasm/testassets/NativeAOT/NativeAOT.csproj
new file mode 100644
index 0000000000000..cdcc4f99d47f9
--- /dev/null
+++ b/src/mono/wasm/testassets/NativeAOT/NativeAOT.csproj
@@ -0,0 +1,13 @@
+
+
+ net9.0
+ browser-wasm
+ Exe
+ true
+ true
+ true
+
+
+
+
+
diff --git a/src/mono/wasm/testassets/NativeAOT/Program.cs b/src/mono/wasm/testassets/NativeAOT/Program.cs
new file mode 100644
index 0000000000000..f78a98e8ec484
--- /dev/null
+++ b/src/mono/wasm/testassets/NativeAOT/Program.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.JavaScript;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+Console.WriteLine("Hello, NativeAOT!");
+Console.WriteLine($"Args {String.Join(", ", args)}");
diff --git a/src/mono/wasm/testassets/NativeAOT/wwwroot/index.html b/src/mono/wasm/testassets/NativeAOT/wwwroot/index.html
new file mode 100644
index 0000000000000..1d1ae6ccf4495
--- /dev/null
+++ b/src/mono/wasm/testassets/NativeAOT/wwwroot/index.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mono/wasm/testassets/NativeAOT/wwwroot/main.js b/src/mono/wasm/testassets/NativeAOT/wwwroot/main.js
new file mode 100644
index 0000000000000..7864eb322ca1f
--- /dev/null
+++ b/src/mono/wasm/testassets/NativeAOT/wwwroot/main.js
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import { dotnet } from './dotnet.js'
+
+await dotnet
+ .withApplicationArguments("A", "B", "C")
+ .withMainAssembly("NativeAOT")
+ .create();
+
+await dotnet.run();