Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions eng/testing/tests.wasi.targets
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

<WasmSingleFileBundle Condition="'$(WasmSingleFileBundle)' == ''">false</WasmSingleFileBundle>
<WasmMainAssemblyFileName Condition="'$(WasmMainAssemblyFileName)' == ''">WasmTestRunner.dll</WasmMainAssemblyFileName>
<IsLibraryTest Condition="'$(OutputType)' == 'Library'">true</IsLibraryTest>

<InstallWasmtimeForTests Condition="'$(InstallWasmtimeForTests)' == '' and
('$(ContinuousIntegrationBuild)' != 'true' or Exists('/.dockerenv'))"
Expand Down
1 change: 1 addition & 0 deletions src/mono/browser/runtime/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ MonoAssembly *mono_wasm_assembly_load (const char *name);
MonoClass *mono_wasm_assembly_find_class (MonoAssembly *assembly, const char *namespace, const char *name);
MonoMethod *mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int arguments);
void mono_wasm_marshal_get_managed_wrapper (const char* assemblyName, const char* typeName, const char* methodName, int num_params);
int initialize_runtime ();

#endif
6 changes: 3 additions & 3 deletions src/mono/sample/wasi/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
TODOWASI - - tcplisten localhost:64000 - - env DEBUGGER_FD=4
-->
<Exec WorkingDirectory="bin/wasi-wasm/AppBundle"
Condition="'$(WasmBuildNative)' != 'true'"
Condition="'$(WasmBuildNative)' != 'true' and '$(OutputType)' != 'Library'"
Command="$(WasmtimeDir)wasmtime$(_ExeExt) $(MONO_LOG_LEVEL) --dir . dotnet.wasm $(_SampleProjectName)" IgnoreExitCode="true" />
<Exec WorkingDirectory="bin/wasi-wasm/AppBundle"
Condition="'$(WasmBuildNative)' == 'true' and '$(WasmSingleFileBundle)' != 'true'"
Condition="'$(WasmBuildNative)' == 'true' and '$(WasmSingleFileBundle)' != 'true' and '$(OutputType)' != 'Library'"
Command="$(WasmtimeDir)wasmtime$(_ExeExt) $(MONO_LOG_LEVEL) --dir . dotnet.wasm" IgnoreExitCode="true" />
<Exec WorkingDirectory="bin/wasi-wasm/AppBundle"
Condition="'$(WasmSingleFileBundle)' == 'true'"
Condition="'$(WasmSingleFileBundle)' == 'true' and '$(OutputType)' != 'Library'"
Command="$(WasmtimeDir)wasmtime$(_ExeExt) $(MONO_LOG_LEVEL) $([System.IO.Path]::ChangeExtension($(_SampleAssembly), '.wasm'))" IgnoreExitCode="true" />
</Target>

Expand Down
15 changes: 11 additions & 4 deletions src/mono/sample/wasi/native/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@ public static int MyExport(int number)
[DllImport("*", EntryPoint = "UnmanagedFunc")]
public static extern void MyImport(); // calls ManagedFunc aka MyExport

public unsafe static int Main(string[] args)
// public unsafe static int Main(string[] args)
// {
// Console.WriteLine($"main: {args.Length}");
// MyImport();
// return 0;
// }

[UnmanagedCallersOnly(EntryPoint = "MyCallback")]
public static int MyCallback()
{
Console.WriteLine($"main: {args.Length}");
MyImport();
return 0;
Console.WriteLine("WASM Library MyCallback is called");
return 100;
}
}
5 changes: 5 additions & 0 deletions src/mono/sample/wasi/native/Wasi.Native.Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
<WasmNativeStrip>false</WasmNativeStrip>
<IsBrowserWasmProject>false</IsBrowserWasmProject>
<WasmSingleFileBundle>true</WasmSingleFileBundle>
<OutputType>Library</OutputType>
<!-- This is needed for ReferenceCopyLocalPaths to include RuntimePackAsset-->
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<!-- This is needed so it will not complain about WasmAssembliesToBundle is empty -->
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup>

<ItemGroup>
Expand Down
10 changes: 10 additions & 0 deletions src/mono/sample/wasi/native/runtimeconfig.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"wasmHostProperties": {
"perHostConfig": [
{
"name": "wasmtime",
"Host": "wasmtime"
}
]
}
}
1 change: 1 addition & 0 deletions src/mono/wasi/build/WasiApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@
<_WasmCommonCFlags Condition="'$(InvariantGlobalization)' == 'true'" Include="-DINVARIANT_GLOBALIZATION=1" />
<_WasmCommonCFlags Condition="'$(InvariantTimezone)' == 'true'" Include="-DINVARIANT_TIMEZONE=1" />
<_WasmCommonCFlags Condition="'$(WasmLinkIcalls)' == 'true'" Include="-DLINK_ICALLS=1" />
<_WasmCommonCFlags Condition="'$(OutputType)' == 'Library' and '$(IsLibraryTest)' != 'true'" Include="-DWASM_LIBRARY_MODE=1" />
<_WasiClangCFlags Include="@(_WasmCommonCFlags)" />

<_WasiClangCFlags Include="&quot;-I%(_WasmCommonIncludePaths.Identity)&quot;" />
Expand Down
39 changes: 36 additions & 3 deletions src/mono/wasi/runtime/main.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <string.h>
#include <stdbool.h>
#include <string.h>
#include <driver.h>
#include <mono/metadata/assembly.h>

Expand All @@ -10,7 +11,31 @@ const char* dotnet_wasi_getentrypointassemblyname();
WASI_AFTER_RUNTIME_LOADED_DECLARATIONS
#endif

int main(int argc, char * argv[]) {
#ifdef WASM_LIBRARY_MODE
// _initialize is a function generated by the WASI SDK libc that calls the LLVM synthesized __wasm_call_ctors function for reactor components:
// https://github.com/WebAssembly/wasi-libc/blob/9f51a7102085ec6a6ced5778f0864c9af9f50000/libc-bottom-half/crt/crt1-reactor.c#L7-L27
// We define and call it for WASM_LIBRARY_MODE and TARGET_WASI to call all the global c++ static constructors. This ensures the runtime is initialized
// when calling into WebAssembly Component Model components.
extern void _initialize();

// CustomNativeMain programs are built using the same libbootstrapperdll as WASM_LIBRARY_MODE but wasi-libc will not provide an _initialize implementation,
// so create a dummy one here and make it weak to allow wasi-libc to provide the real implementation for WASI reactor components.
__attribute__((weak)) void _initialize()
{
}

static bool runtime_initialized = false;

#endif

int initialize_runtime()
{
#if defined(WASM_LIBRARY_MODE)
if (runtime_initialized)
return 0;
_initialize();
runtime_initialized = true;
#endif

#ifndef WASM_SINGLE_FILE
mono_set_assemblies_path("managed");
Expand All @@ -21,7 +46,14 @@ int main(int argc, char * argv[]) {
// This is supplied from the MSBuild itemgroup @(WasiAfterRuntimeLoaded)
WASI_AFTER_RUNTIME_LOADED_CALLS
#endif

return 0;
}

#ifndef WASM_LIBRARY_MODE
int main(int argc, char * argv[]) {
int initval = initialize_runtime();
if (initval != 0)
return initval;
int arg_ofs = 0;
#ifdef WASM_SINGLE_FILE
/*
Expand Down Expand Up @@ -71,3 +103,4 @@ int main(int argc, char * argv[]) {
}
return ret < 0 ? -ret : ret;
}
#endif
9 changes: 4 additions & 5 deletions src/mono/wasm/build/WasmApp.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@
</WasmLinkDotNetDependsOn>

<WasmDedup Condition="'$(WasmDedup)' == ''">true</WasmDedup>
<IsWasiProject Condition="'$(IsWasiProject)' == '' and '$(RuntimeIdentifier)' == 'wasi-wasm' and '$(OutputType)' != 'Library'">true</IsWasiProject>
<IsBrowserWasmProject Condition="'$(IsBrowserWasmProject)' == '' and '$(RuntimeIdentifier)' == 'browser-wasm' and '$(OutputType)' != 'Library'">true</IsBrowserWasmProject>
<IsWasiProject Condition="'$(IsWasiProject)' == '' and '$(RuntimeIdentifier)' == 'wasi-wasm'">true</IsWasiProject>
<IsBrowserWasmProject Condition="'$(IsBrowserWasmProject)' == '' and '$(RuntimeIdentifier)' == 'browser-wasm'">true</IsBrowserWasmProject>
<IsWasmProject Condition="'$(IsWasmProject)' == '' and ('$(IsWasiProject)' == 'true' or '$(IsBrowserWasmProject)' == 'true')">true</IsWasmProject>
<WasmBuildAppAfterThisTarget Condition="'$(WasmBuildAppAfterThisTarget)' == '' and '$(DisableAutoWasmBuildApp)' != 'true'">Build</WasmBuildAppAfterThisTarget>

Expand All @@ -173,8 +173,7 @@
<EnableDefaultWasmAssembliesToBundle Condition="'$(EnableDefaultWasmAssembliesToBundle)' == ''">true</EnableDefaultWasmAssembliesToBundle>
<!-- VS uses DeployOnBuild, and sdk sets _IsPublishing -->
<WasmBuildOnlyAfterPublish Condition="'$(WasmBuildOnlyAfterPublish)' == '' and ('$(DeployOnBuild)' == 'true' or '$(_IsPublishing)' == 'true')">true</WasmBuildOnlyAfterPublish>
<WasmGenerateAppBundle Condition="'$(WasmGenerateAppBundle)' == '' and '$(OutputType)' != 'Library'">true</WasmGenerateAppBundle>
<WasmGenerateAppBundle Condition="'$(WasmGenerateAppBundle)' == ''">false</WasmGenerateAppBundle>
<WasmGenerateAppBundle Condition="'$(WasmGenerateAppBundle)' == ''">true</WasmGenerateAppBundle>

<!-- FIXME: can't set to true because
/workspaces/runtime/.dotnet/sdk/7.0.100-rc.1.22431.12/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(135,5): error NETSDK1084: There is no application host available for the specified RuntimeIdentifier 'wasi-wasm'.
Expand Down Expand Up @@ -346,7 +345,7 @@

<Target Name="_WasmGetRuntimeConfigPath">
<PropertyGroup>
<_MainAssemblyPath Condition="'%(WasmAssembliesToBundle.FileName)' == $(AssemblyName) and '%(WasmAssembliesToBundle.Extension)' == '.dll' and $(WasmGenerateAppBundle) == 'true'">%(WasmAssembliesToBundle.Identity)</_MainAssemblyPath>
<_MainAssemblyPath Condition="'%(WasmAssembliesToBundle.FileName)' == '$(AssemblyName)' and '%(WasmAssembliesToBundle.Extension)' == '.dll' and $(WasmGenerateAppBundle) == 'true'">%(WasmAssembliesToBundle.Identity)</_MainAssemblyPath>
<_WasmRuntimeConfigFilePath Condition="'$(_WasmRuntimeConfigFilePath)' == '' and $(_MainAssemblyPath) != ''">$([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json'))</_WasmRuntimeConfigFilePath>
<_ParsedRuntimeConfigFilePath Condition="'$(_WasmRuntimeConfigFilePath)' != ''">$([System.IO.Path]::GetDirectoryName($(_WasmRuntimeConfigFilePath)))\runtimeconfig.bin</_ParsedRuntimeConfigFilePath>
</PropertyGroup>
Expand Down
7 changes: 7 additions & 0 deletions src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,13 @@ private void EmitNativeToInterp(StreamWriter w, List<PInvokeCallback> callbacks)
if (!is_void)
sb.Append($" {MapType(method.ReturnType)} res;\n");

if (HasAttribute(method, "System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute"))
{
sb.Append($" #if defined(WASM_LIBRARY_MODE) \n");
sb.Append($" initialize_runtime(); \n");
sb.Append($" #endif\n");
}

// In case when null force interpreter to initialize the pointers
sb.Append($" if (!(WasmInterpEntrySig_{cb_index})wasm_native_to_interp_ftndescs [{cb_index}].func) {{\n");
var assemblyFullName = cb.Method.DeclaringType == null ? "" : cb.Method.DeclaringType.Assembly.FullName;
Expand Down