From 6253f18d9ac15d526a72fc5f259b588e041b2cc2 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Tue, 28 Oct 2025 23:50:03 +0300 Subject: [PATCH] Add support for `Static` Refactor the targets and sink more WASM specifics into the WASM-specific targets. --- .../Microsoft.NETCore.Native.Wasm.targets | 44 ++++++-- .../Microsoft.NETCore.Native.targets | 34 +++--- .../HelloWasm/Directory.Build.props | 8 ++ .../ExceptionHandlingTests.Cpp.csproj | 1 - .../HelloWasm/PackagingTests.csproj | 1 - .../SmokeTests/HelloWasm/WasmStaticLib.cs | 101 ++++++++++++++++++ .../SmokeTests/HelloWasm/WasmStaticLib.csproj | 34 ++++++ .../HelloWasm/WasmStaticLibDriver.cpp | 30 ++++++ 8 files changed, 221 insertions(+), 32 deletions(-) create mode 100644 src/tests/nativeaot/SmokeTests/HelloWasm/Directory.Build.props create mode 100644 src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLib.cs create mode 100644 src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLib.csproj create mode 100644 src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLibDriver.cpp diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Wasm.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Wasm.targets index 6ef7d6fb565f..7d84f988c81f 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Wasm.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Wasm.targets @@ -13,25 +13,27 @@ The .NET Foundation licenses this file to you under the MIT license. *********************************************************************************************** --> - - - - - - - - - - + + + <_NativeWasmSdkBinPath Condition="'$(EMSDK)' != ''">$([MSBuild]::NormalizeDirectory('$(EMSDK)', 'upstream', 'bin')) + <_NativeWasmSdkBinPath Condition="'$(EMSDK)' == ''">$([MSBuild]::NormalizeDirectory('$(EmscriptenSdkToolsPath)', 'bin')) + <_EmscriptenScriptsPath Condition="'$(EMSDK)' != ''">$([MSBuild]::NormalizeDirectory('$(EMSDK)', 'upstream', 'emscripten')) + <_EmscriptenScriptsPath Condition="'$(EMSDK)' == ''">$([MSBuild]::NormalizeDirectory('$(EmscriptenSdkToolsPath)', 'emscripten')) + <_EmccScriptExt Condition="$([System.OperatingSystem]::IsWindows())">.bat + + "$(_NativeWasmSdkBinPath)clang" + "$(_EmscriptenScriptsPath)emcc$(_EmccScriptExt)" + - @@ -45,6 +47,26 @@ The .NET Foundation licenses this file to you under the MIT license. + + + <_NativeWasmSdkBinPath>$([MSBuild]::NormalizeDirectory('$(WASI_SDK_PATH)', 'bin')) + + "$(_NativeWasmSdkBinPath)clang" + $(CppCompiler) + + + + + + + <_HostToolExeExt Condition="$([System.OperatingSystem]::IsWindows())">.exe + $(_NativeWasmSdkBinPath)llvm-ar$(_HostToolExeExt) + + + + + + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 3b06dceaeac0..a8be56fa6117 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -85,9 +85,9 @@ The .NET Foundation licenses this file to you under the MIT license. .so .lib .a - .html - .js - .wasm + .html + .js + .wasm .dSYM .pdb @@ -408,7 +408,7 @@ The .NET Foundation licenses this file to you under the MIT license. @@ -424,25 +424,13 @@ The .NET Foundation licenses this file to you under the MIT license. $(CompileWasmArgs) -mllvm -enable-emscripten-cxx-exceptions - - .bat - - "$(EMSDK)/upstream/bin/clang++" - "$(EmscriptenSdkToolsPath)bin/clang++" - "$(EMSDK)/upstream/emscripten/emcc$(EmccScriptExt)" - "$(EmscriptenSdkToolsPath)emscripten/emcc$(EmccScriptExt)" - - - - "$(WASI_SDK_PATH)/bin/clang++" - "$(WASI_SDK_PATH)/bin/clang" - ExecCommand=$(WasmCompilerPath) "%(LlvmObjects.Identity)" -o "%(LlvmObjects.NativeObject)" $(CompileWasmArgs) + ExecCommand=$(CppCompiler) "%(LlvmObjects.Identity)" -o "%(LlvmObjects.NativeObject)" $(CompileWasmArgs) @@ -621,8 +609,16 @@ The .NET Foundation licenses this file to you under the MIT license. - - + + + + + + + + + + + + + + true + + + diff --git a/src/tests/nativeaot/SmokeTests/HelloWasm/ExceptionHandlingTests.Cpp.csproj b/src/tests/nativeaot/SmokeTests/HelloWasm/ExceptionHandlingTests.Cpp.csproj index 0b5053951ed5..8e3a4d1d41ea 100644 --- a/src/tests/nativeaot/SmokeTests/HelloWasm/ExceptionHandlingTests.Cpp.csproj +++ b/src/tests/nativeaot/SmokeTests/HelloWasm/ExceptionHandlingTests.Cpp.csproj @@ -2,7 +2,6 @@ Exe BuildAndRun - true false diff --git a/src/tests/nativeaot/SmokeTests/HelloWasm/PackagingTests.csproj b/src/tests/nativeaot/SmokeTests/HelloWasm/PackagingTests.csproj index f621b7c44c43..7084b8580812 100644 --- a/src/tests/nativeaot/SmokeTests/HelloWasm/PackagingTests.csproj +++ b/src/tests/nativeaot/SmokeTests/HelloWasm/PackagingTests.csproj @@ -3,7 +3,6 @@ BuildOnly - true diff --git a/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLib.cs b/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLib.cs new file mode 100644 index 000000000000..76ced3c4074a --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLib.cs @@ -0,0 +1,101 @@ +// 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.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +public class StaticLibrary +{ + static int s_primitiveInt = 10; + + [UnmanagedCallersOnly(EntryPoint = "ReturnsPrimitiveInt")] + public static int ReturnsPrimitiveInt() + { + return s_primitiveInt; + } + + [UnmanagedCallersOnly(EntryPoint = "ReturnsPrimitiveBool")] + public static bool ReturnsPrimitiveBool() + { + return true; + } + + [UnmanagedCallersOnly(EntryPoint = "ReturnsPrimitiveChar")] + public static char ReturnsPrimitiveChar() + { + return 'a'; + } + + [UnmanagedCallersOnly(EntryPoint = "EnsureManagedClassLoaders")] + public static void EnsureManagedClassLoaders() + { + Random random = new Random(); + random.Next(); + } + + [UnmanagedCallersOnly(EntryPoint = "CheckSimpleExceptionHandling")] + public static int CheckSimpleExceptionHandling() + { + int result = 10; + + try + { + Console.WriteLine("Throwing exception"); + throw new Exception(); + } + catch when (result == 10) + { + result += 20; + } + finally + { + result += 70; + } + + return result; + } + + private static bool s_collected; + + class ClassWithFinalizer + { + ~ClassWithFinalizer() { s_collected = true; } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void MakeGarbage() + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + + object[] arr = new object[1024 * 1024]; + for (int i = 0; i < arr.Length; i++) + arr[i] = new object(); + + new ClassWithFinalizer(); + } + + [UnmanagedCallersOnly(EntryPoint = "CheckSimpleGCCollect")] + public static int CheckSimpleGCCollect() + { + string myString = string.Format("Hello {0}", "world"); + + MakeGarbage(); + + Console.WriteLine("Triggering GC"); + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + + return s_collected ? (myString == "Hello world" ? 100 : 1) : 2; + } +} diff --git a/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLib.csproj b/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLib.csproj new file mode 100644 index 000000000000..f56b76c80296 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLib.csproj @@ -0,0 +1,34 @@ + + + Library + Static + true + BuildAndRun + 0 + true + false + + WasmStaticLib.js + WasmStaticLib.wasm + + + + + + + + + <_FinalLinkerArg Include="-o "$(NativeOutputPath)$(NativeDriverBinary)"" /> + <_FinalLinkerArg Include=""$(NativeBinary)"" /> + <_FinalLinkerArg Include=""$(MSBuildThisFileDirectory)WasmStaticLibDriver.cpp"" /> + + + <_ExcludedLinkerArg Include="@(NativeObjects->'"%(Identity)"'->Replace('\', '/'))" /> + <_ExcludedLinkerArg Include="-o "$(NativeBinary.Replace('\', '/'))"" /> + <_FinalLinkerArg Include="@(CustomLinkerArg)" Exclude="@(_ExcludedLinkerArg)" /> + + + + + + diff --git a/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLibDriver.cpp b/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLibDriver.cpp new file mode 100644 index 000000000000..85a26519453d --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/HelloWasm/WasmStaticLibDriver.cpp @@ -0,0 +1,30 @@ +extern "C" int ReturnsPrimitiveInt(); +extern "C" bool ReturnsPrimitiveBool(); +extern "C" unsigned short ReturnsPrimitiveChar(); +extern "C" void EnsureManagedClassLoaders(); +extern "C" int CheckSimpleGCCollect(); +extern "C" int CheckSimpleExceptionHandling(); + +int main() +{ + if (ReturnsPrimitiveInt() != 10) + return 1; + + if (!ReturnsPrimitiveBool()) + return 2; + + if (ReturnsPrimitiveChar() != 'a') + return 3; + + // As long as no unmanaged exception is thrown + // managed class loaders were initialized successfully + EnsureManagedClassLoaders(); + + if (CheckSimpleGCCollect() != 100) + return 4; + + if (CheckSimpleExceptionHandling() != 100) + return 5; + + return 0; +}