LoginSignup
21
3

More than 1 year has passed since last update.

UbuntuでWasmExを動かそう

Last updated at Posted at 2022-10-19

前提事項

検証用のOSはUbuntu 20.04
Elixirはインストール済みであること
https://elixir-lang.org/install.html

WasmExを使える環境を作ろう

下記のサイトを見よう
https://github.com/tessi/wasmex
Developmentの項目を見る
 a) Rustのインストール
 b) Rustの関連ツールイントール

e.png

下準備

$ sudo apt install git
$ sudo apt install curl

a) Rustをインストール

下記を実行

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

下記の画面が表示するので1を入力してEnter

Current installation options:


   default host triple: x86_64-unknown-linux-gnu
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1

その後ターミナルを再起動
※Rustのツールのパスを有効にするため
ネイティブのUbuntuならCtrl + Alt + tでターミナルを新規でひらけます

b) Rustの関連ツールイントール

$ rustup component add rustfmt
$ rustup component add clippy
$ rustup target add wasm32-unknown-unknown
$ rustup target add wasm32-wasi

動作確認

git clone 〜 mix test

git clone https://github.com/tessi/wasmex.git
cd wasmex
mix deps.get
mix compile --force
mix rustler_precompiled.download Wasmex.Native --only-local
mix test

iexを起動

$ iex -S mix

README.mdのExampleを参考に動作確認

Erlang/OTP 25 [erts-13.0.4] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]

Compiling 7 files (.ex)

17:48:30.529 [debug] Copying NIF from cache and extracting to /home/user/wasmex/_build/dev/lib/wasmex/priv/native/libwasmex-v0.7.1-nif-2.16-x86_64-unknown-linux-gnu.so
Generated wasmex app
Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, bytes } = File.read("test/wasm_test/target/wasm32-unknown-unknown/debug/wasmex_test.wasm")
{:ok,
 <<0, 97, 115, 109, 1, 0, 0, 0, 1, 118, 19, 96, 2, 127, 127, 0, 96, 3, 127, 127,
   127, 1, 127, 96, 2, 127, 127, 1, 127, 96, 3, 127, 127, 127, 0, 96, 1, 127, 1,
   127, 96, 0, 1, 127, 96, 1, 126, 1, ...>>}
iex(2)> {:ok, module} = Wasmex.Module.compile(bytes)
{:ok, #Wasmex.Module<#Reference<0.1531479610.3425435661.13361>>}
iex(3)> {:ok, instance } = Wasmex.start_link(%{module: module})
{:ok, #PID<0.346.0>}
iex(4)> {:ok, [42]} == Wasmex.call_function(instance, "sum", [50, -8])
true
iex(5)> 

Rustで実験用のWebAssemblyを作ってみよう

$ cargo new hoge_wasm --lib
$ cd hoge_wasm

Cargo.tomlに追加

[package]
name = "hoge_wasm"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

+ [lib]
+ crate-type =["cdylib"]

src/lib.rs を下記に上書き

#[no_mangle]
pub extern "C" fn hoge(a: i32) -> i32 {
    a * 777
}

ビルドする

$ cargo build --target=wasm32-unknown-unknown

hoge_wasm.wasmが生成されていることを確認

$ ls target/wasm32-unknown-unknown/debug/
build  deps  examples  hoge_wasm.d  hoge_wasm.wasm  incremental

Elixirのプロジェクトを作成

プロジェクト作成

$ mix new hoge
$ cd hoge

mix.exsを編集
wasmexを追加

defmodule Hoge.MixProject do
  use Mix.Project

  def project do
    [
      app: :hoge,
      version: "0.1.0",
      elixir: "~> 1.13",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
+     {:wasmex, "~> 0.7.1"}
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end
end

mix deps.getをする

$ mix deps.get

lib/hoge.exを編集

defmodule Hoge do
  @moduledoc """
  Documentation for `Hoge`.
  """

  @doc """
  Hello world.

  ## Examples

      iex> Hoge.hello()
      :world

  """
  def hello do
    :world
  end

+ def test do
+   {:ok, bytes } = File.read("hoge_wasm.wasm")
+   {:ok, module} = Wasmex.Module.compile(bytes)
+   {:ok, instance } = Wasmex.start_link(%{module: module})
+   Wasmex.call_function(instance, "hoge", [10])
+ end

end

hoge_wasm.wasmをelixirのプロジェクトの直下にコピーしておく

$ cp ../hoge_wasm/target/wasm32-unknown-unknown/debug/hoge_wasm.wasm ./

iex で検証

iex -S mix
iex(1)> Hoge.test()
{:ok, [7770]}

10 * 777 = 7770で正しく動いている事が確認できました

その他のOSで動作確認できたもの

・Windows 10 WSL2(Ubuntu 20.04)
・macOS Monterey 12.3 Mac mini(M1, 2020)

Rustの関数を呼び出している事を検証する

aaa.png
2147483647 + 0 はOK

2147483647 + 1をした場合、-214483648になると思いきや…
rustがpanicを起こしました

21
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
3