Compile dotnet to wasm

.NETをwasmにAOTしてみる。おそらくランタイムごとwasmになるんかな



ひとまずこの人の説明通りやってみる。

https://stackoverflow.com/questions/70474778/compiling-c-sharp-project-to-webassembly



まず、emscriptenをいれる。Python3.6が必要ぽいけど入っていたのでそこはスキップ


git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest


環境変数がセットされたので一応サインアウトからのサインイン。



適当なフォルダでdotnet projectをつくって、nugetconfigでnugetリポジトリを追加する。3rdPartyせいなのね。blazorのとかこれじゃなかったのか。



mkdir sample
cd sample
dotnet new classlib
dotnet new nugetconfig


<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="globalPackagesFolder" value=".packages" />
  </config>
  <packageSources>
    <!--To inherit the global NuGet package sources remove the <clear/> line below -->
    <clear />
    <add key="dotnet-experimental" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>


Class1にメソッドを追加


      [System.Runtime.InteropServices.UnmanagedCallersOnly(EntryPoint = "Answer")]
      public static int Answer()
      {
          return 41;
      }


csprojに以下を追加


    <ItemGroup>
      <PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="7.0.0-*" />
      <PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler.LLVM" Version="7.0.0-*" />
    </ItemGroup>


次のコマンドでコンパイル


dotnet publish /p:NativeLib=Static /p:SelfContained=true -r browser-wasm -c Debug /p:TargetArchitecture=wasm /p:PlatformTarget=AnyCPU /p:MSBuildEnableWorkloadResolver=false /p:EmccExtraArgs="-s EXPORTED_FUNCTIONS=_Answer%2C_CoreRT_StaticInitialization -s EXPORTED_RUNTIME_METHODS=cwrap" --self-contained


するんだけどうまくいかない。こんなエラーが出る。


Microsoft (R) Build Engine version 17.1.0-preview-21610-01+96a618ca5 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  You are using a preview version of .NET. See: https://aka.ms/dotnet-core-preview
  sample -> C:\Users\iwate\works\iwate\sample\bin\Debug\net6.0\browser-wasm\sample.dll
C:\Program Files\dotnet\sdk\6.0.200-preview.21617.4\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Publish.targets(248,5): error MSB3030: Could not copy the file "bin\Debug\net6.0\browser-wasm\native\sample.html" because it was not found. [\path\to\sample\sample.csproj]


StackOverflowじゃなくて、リポジトリのドキュメントを参考にしてみる。

https://github.com/dotnet/runtimelab/blob/feature/NativeAOT-LLVM/docs/using-nativeaot/compiling.md#webassembly



今度は、consoleアプリでそのままアプリケーションにする


dotnet new console
dotnet new nugetconfig


nuget.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <!--To inherit the global NuGet package sources remove the <clear/> line below -->
    <clear />
    <add key="dotnet-experimental" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>


csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.DotNet.ILCompiler" Version="7.0.0-*" />
    <PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM; runtime.win-x64.Microsoft.DotNet.ILCompiler.LLVM" Version="7.0.0-*" />
  </ItemGroup>

</Project>


ビルド

dotnet publish -r browser-wasm -c Debug /p:TargetArchitecture=wasm /p:PlatformTarget=AnyCPU


workdloadが足りないって言われる

C:\Program Files\dotnet\sdk\6.0.200-preview.21617.4\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.ImportWorkloads.targets(38,5): error NETSDK1147: To build this project, the following workloads must be installed: wasm-tools 
C:\Program Files\dotnet\sdk\6.0.200-preview.21617.4\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.ImportWorkloads.targets(38,5): error NETSDK1147: To install these workloads, run the following command: dotnet workload install wasm-tools


ので足す。

dotnet workload install wasm-tools


再度ビルドするがエラー

$ dotnet publish -r browser-wasm -c Debug /p:TargetArchitecture=wasm /p:PlatformTarget=AnyCPU
Microsoft (R) Build Engine version 17.1.0-preview-21610-01+96a618ca5 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  Restored C:\Users\iwate\works\iwate\wasm\wasm.csproj (in 1.6 min).
  You are using a preview version of .NET. See: https://aka.ms/dotnet-core-preview
C:\Program Files\dotnet\sdk\6.0.200-preview.21617.4\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.targets(1110,5): warning NETSDK1179: One of '--self-contained' or '--no-self-contained' options are required when '--runtime' is used. [C:\Users\iwate\works\iwate\wasm\wasm.csproj]
  wasm -> C:\Users\iwate\works\iwate\wasm\bin\Debug\net6.0\browser-wasm\wasm.dll
C:\Program Files\dotnet\packs\Microsoft.NET.Runtime.WebAssembly.Sdk\6.0.2-mauipre.1.22054.8\Sdk\WasmApp.targets(270,5): error : $(WasmMainJSPath) property needs to be set 


プロジェクト構成見てみる

https://github.com/dotnet/runtimelab/tree/feature/NativeAOT-LLVM/samples/HelloWorld


dotnet6じゃなくて5だったので、5に変更。Program.csも5になるように、namespaceやらエントリーポイントで囲う。


PackageReferenceも一つでいいぽい


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM; runtime.win-x64.Microsoft.DotNet.ILCompiler.LLVM" Version="7.0.0-*" />
  </ItemGroup>

</Project>


再度ビルド


$ dotnet publish -r browser-wasm -c Debug /p:TargetArchitecture=wasm /p:PlatformTarget=AnyCPU
Microsoft (R) Build Engine version 17.1.0-preview-21610-01+96a618ca5 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  Restored C:\Users\iwate\works\iwate\wasm\wasm.csproj (in 2.05 sec).
  You are using a preview version of .NET. See: https://aka.ms/dotnet-core-preview
  wasm -> C:\Users\iwate\works\iwate\wasm\bin\Debug\net5.0\browser-wasm\wasm.dll
  Generating compatible native code. To optimize for size or speed, visit https://aka.ms/OptimizeCoreRT
  RyuJIT compilation results, total methods 16830 RyuJit Methods 5699 33.8622%
C:\Program Files\dotnet\sdk\6.0.200-preview.21617.4\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Publish.targets(248,5): error MSB3030: Could not copy the file "bin\Debug\net5.0\browser-wasm\native\wasm.html" because it was not found. 


ズコー。最初と一緒やん。