tag:crieit.net,2005:https://crieit.net/tags/Cargo/feed
「Cargo」の記事 - Crieit
Crieitでタグ「Cargo」に投稿された最近の記事
2020-06-28T13:07:35+09:00
https://crieit.net/tags/Cargo/feed
tag:crieit.net,2005:PublicArticle/15870
2020-04-26T21:58:35+09:00
2020-06-28T13:07:35+09:00
https://crieit.net/posts/cargo-make
cargo-makeによるプロジェクト・ビルド入門
<h1 id="cargo-makeによるプロジェクト・ビルド"><a href="#cargo-make%E3%81%AB%E3%82%88%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%83%BB%E3%83%93%E3%83%AB%E3%83%89">cargo-makeによるプロジェクト・ビルド</a></h1>
<h2 id="モチベーション"><a href="#%E3%83%A2%E3%83%81%E3%83%99%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3">モチベーション</a></h2>
<p>cargoはrustのパッケージ管理ツール兼ビルドツールである.これい自体非常に便利なのだが, Web標準は無視できない. 特にSeedのようなWebフロントエンド・フレームワークによる開発ではWeb標準に合わせる必要も出てくる. 単純なケースでは<a target="_blank" rel="nofollow noopener" href="https://seed-rs.org/guide/quickstart">Quickstart</a>に従ってindex.htmlに直接wasmモジュールを導入すれば良いのですが, 複雑なアプリなどはwebpackなどが使えた方が便利だと思います. 今回のケースではTailwindの導入などがそれに当たります.</p>
<h2 id="目標"><a href="#%E7%9B%AE%E6%A8%99">目標</a></h2>
<p>CSSフレームワークであるtailwindcssをSeedプロジェクトで利用する.</p>
<h2 id="前提条件"><a href="#%E5%89%8D%E6%8F%90%E6%9D%A1%E4%BB%B6">前提条件</a></h2>
<ul>
<li>rustupの導入</li>
</ul>
<p>とりあえずこれを導入しておけば諸々の開発環境の導入・管理が行えるようになります.</p>
<h2 id="NPM vs Cargo"><a href="#NPM+vs+Cargo">NPM vs Cargo</a></h2>
<div class="table-responsive"><table>
<thead>
<tr>
<th>機能</th>
<th>NPM</th>
<th>Cargo</th>
<th>備考</th>
</tr>
</thead>
<tbody>
<tr>
<td>パッケージ管理</td>
<td>⭕️</td>
<td>⭕️</td>
<td>パッケージのインスタール・公開などができる</td>
</tr>
<tr>
<td>依存性管理</td>
<td>⭕️</td>
<td>⭕️</td>
<td>lockファイルがある点など共通点が多い</td>
</tr>
<tr>
<td>タスク・ランナー</td>
<td>⭕️</td>
<td>❌</td>
<td>Cargoではカスタム・コマンドが開発できる(はず)</td>
</tr>
<tr>
<td>ビルド</td>
<td>❌</td>
<td>⭕️</td>
<td>NPMでは代わりにタスク・ランナーを使う</td>
</tr>
<tr>
<td>コマンド拡張</td>
<td>❌</td>
<td>⭕️</td>
<td>タスク・ランナーから呼び出せば良い</td>
</tr>
</tbody>
</table></div>
<p>Cargoには<a target="_blank" rel="nofollow noopener" href="https://docs.npmjs.com/misc/scripts">npm-scripts</a>のようなタスク・ランナーがありませんが, <a target="_blank" rel="nofollow noopener" href="https://doc.rust-lang.org/cargo/reference/external-tools.html#custom-subcommands">カスタム・コマンド</a>で機能を拡張することができます. その一つが<a target="_blank" rel="nofollow noopener" href="https://github.com/sagiegurari/cargo-make">cargo-make</a>です.</p>
<h2 id="cargo-makeによるプロジェクト管理"><a href="#cargo-make%E3%81%AB%E3%82%88%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E7%AE%A1%E7%90%86">cargo-makeによるプロジェクト管理</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/seed-rs/seed-quickstart">seed-quickstart</a>のMakefile.toml内容を解説する感じです. wachモードなどは<a target="_blank" rel="nofollow noopener" href="https://github.com/brainvader/EvaQL/blob/tags/v0.1/ui/Makefile.toml#L73">EvaQL/ui/Makefile.toml</a>を参照してください.</p>
<h3 id="cargo-makeの導入"><a href="#cargo-make%E3%81%AE%E5%B0%8E%E5%85%A5">cargo-makeの導入</a></h3>
<p>cargo-makeの実行にはcargo-makeバイナリが必要になるのでインストールしておきます.</p>
<pre><code class="bash">cargo install --force cargo-make
</code></pre>
<p>次にプロジェクトを作成します. これもコマンド一つでできます. 今回はwasmモジュールとして読み込まれるので--libオプションをつけます.</p>
<pre><code class="bash">cargo new --lib project-name
</code></pre>
<p>できたらプロジェクト・ルートに移動し実行してみましょう.</p>
<pre><code class="bash">cago make
</code></pre>
<p>この時点では<a target="_blank" rel="nofollow noopener" href="https://github.com/sagiegurari/cargo-make#default-tasks-and-extending">デフォルトのtomファイル</a>が参照されます. 次にMakefile.tomlファイルを作成します.</p>
<pre><code class="bash">cd project-name
touch Makefile.toml
</code></pre>
<p>同様に実行すると今度はMakefile.tomlをもとに実行が行われます. 任意のmakefileを指定するには--makefileオプションを使います.</p>
<pre><code class="bash">cargo make --makefile ./my_build.toml test
</code></pre>
<h3 id="Makefile.tomlの書き方"><a href="#Makefile.toml%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9">Makefile.tomlの書き方</a></h3>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/seed-rs/seed-quickstart/blob/master/Makefile.toml">seed-quickstart/Makefile.toml</a>の解説です. 必要ない方は飛ばしましょう.</p>
<h4 id="タスク"><a href="#%E3%82%BF%E3%82%B9%E3%82%AF">タスク</a></h4>
<p>実行するコマンドはタスクという単位で管理します. 何もしないタスクは以下のようになります.</p>
<pre><code class="toml">[tasks.do_nothing]
# do nothing
</code></pre>
<h4 id="基本"><a href="#%E5%9F%BA%E6%9C%AC">基本</a></h4>
<p>cargoのbuildサブコマンドを呼び出してみましょう.</p>
<pre><code class="toml"># cargo make compile
[tasks.compile]
description = "Build"
workspace = false
command = "cargo"
args = ["build"]
</code></pre>
<p>それぞれの意味は以下のようになります.</p>
<div class="table-responsive"><table>
<thead>
<tr>
<th>セクション</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td>description</td>
<td>このタスクの内容</td>
</tr>
<tr>
<td>workspace</td>
<td>workspaceでタスクを実行するかどうか</td>
</tr>
<tr>
<td>command</td>
<td>実行するメイン・コマンド</td>
</tr>
<tr>
<td>args</td>
<td>引数の指定</td>
</tr>
</tbody>
</table></div>
<h4 id="依存タスク"><a href="#%E4%BE%9D%E5%AD%98%E3%82%BF%E3%82%B9%E3%82%AF">依存タスク</a></h4>
<p>dependencies属性を指定するとコマンドの依存性を指定できます. 要するに呼び出し順序です.</p>
<pre><code class="toml"># cargo make start
[tasks.start]
description = "Combine the build and serve tasks"
workspace = false
dependencies = ["build"]
</code></pre>
<p>これでcargo startを実行するとbuildタスクが実行されます.</p>
<h4 id="開発サーバーと環境変数"><a href="#%E9%96%8B%E7%99%BA%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%A8%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0">開発サーバーと環境変数</a></h4>
<p>開発サーバーとしてmicroserverというクレートを使います. 簡単なWeb UIの開発には便利そうなのとクレート導入の例として紹介しておきます. 開発の趣旨を開発者の人がブログに書いています.</p>
<p><a target="_blank" rel="nofollow noopener" href="https://robertohuertas.com/2018/11/01/microserver/">Microserver: local http server with SPA support</a></p>
<p>今回のようにあるタスクの前提となるバイナリ・クレートのインストールも記述できます.</p>
<pre><code class="toml">[tasks.serve]
description = "Start server"
install_crate = { crate_name = "microserver", binary = "microserver", test_arg = "-h" }
workspace = false
command = "microserver"
args = ["--port", "${PORT}"]
</code></pre>
<p>サーバーということでポートの指定もしています. 環境変数もenvセクションで指定できます.</p>
<pre><code class="toml">[env]
PORT = "8000"
</code></pre>
<p>別ファイルに指定して読み込むこともできます.</p>
<pre><code class="toml">[env]
env_files = [
"./my_env.env",
]
</code></pre>
<h4 id="conditionによる条件設"><a href="#condition%E3%81%AB%E3%82%88%E3%82%8B%E6%9D%A1%E4%BB%B6%E8%A8%AD">conditionによる条件設</a></h4>
<p>ある条件を満たすときにタスクを実行することもできます. 環境変数がきちんと指定されている場合だけ実行するという条件ならconditionセクションをタスクに追加します.</p>
<pre><code class="toml">[tasks.start]
condition = { env_set = [ "PORT" ] }
</code></pre>
<p>あるいは特定の環境変数を条件にして新しい変数を定義することができる.</p>
<pre><code class="toml">[env]
PORT_EXISTING = { value = "true", condtion = { env_set = ["PORT"] } }
PORT = { value = "8000", condition = { env_not_set = ["PORT"] } }
</code></pre>
<p>条件によって読みやすい環境変数に変換したり, 環境変数が定義されていない場合に設定したりということができそうです.</p>
<h4 id="profileによるモードの切り替え"><a href="#profile%E3%81%AB%E3%82%88%E3%82%8B%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AE%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88">profileによるモードの切り替え</a></h4>
<p>webpackのモードの指定ののようなこともできます.</p>
<pre><code class="toml">[env]
env_files = [
{ path = "./development.env", profile = development },
{ path = "./production.env", profile = "production }
]
</code></pre>
<pre><code class="bash">cargo make --profile production some_task
</code></pre>
<p>developmentはデフォルト値なので指定する必要はないです.</p>
<h4 id="タスクの拡張とリリース・ビルド"><a href="#%E3%82%BF%E3%82%B9%E3%82%AF%E3%81%AE%E6%8B%A1%E5%BC%B5%E3%81%A8%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%83%BB%E3%83%93%E3%83%AB%E3%83%89">タスクの拡張とリリース・ビルド</a></h4>
<p>タスク名をextend属性で指定するとタスクを拡張できます. 例えばcompileタスクをリリース・モードでビルドするように拡張すると以下のようになります.</p>
<pre><code class="toml">[tasks.compile_release]
description = "Release Build "
extend = "compile"
args = ["build", "--release"]
</code></pre>
<p>プラットフォームごとの拡張も簡単にできます.</p>
<pre><code class="toml">[tasks.hello-world]
script = [
"echo \"Hello World From Unknown\""
]
[tasks.hello-world.linux]
script = [
"echo \"Hello World From Linux\""
]
[tasks.hello-world.mac]
script = [
"echo \"Hello World From macOS\""
]
</code></pre>
<h4 id="スクリプティング"><a href="#%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0">スクリプティング</a></h4>
<p>シェルスクリプトを指定して実行することもできます.</p>
<pre><code class="toml">[tasks.echo]
script = [
"echo hello world"
]
</code></pre>
<p>script_runner属性を指定することでpythonなどスクリプトのランナーを指定できます.</p>
<pre><code class="toml">[tasks.python]
script_runner = "python"
script_extension = "py"
script = [
'''
print("Hello, World!")
'''
]
</code></pre>
<p>またファイルを指定して実行することもできます.</p>
<pre><code class="toml">[tasks.run_from_script]
script = { file = "hello.py" }
</code></pre>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/sagiegurari/cargo-make#rust-code">@rust</a>の指定でRustを実行することもできます.</p>
<h4 id="run_tasks"><a href="#run_tasks">run_tasks</a></h4>
<p>実行するタスクを指定します. dependenciesで指定したタスクは事前に実行されますが, run_task属性で指定したタスクは事後に実行されます.</p>
<pre><code class="toml">[tasks.pre_task]
script = [ "echo pre task"]
[tasks.post_task]
script = [ "echo post task"]
[tasks.do_something]
dependencies = ["pre_task"]
run_task = "post_task"
</code></pre>
<p>この例の場合pre_task -> do_something -> post_taskの順で実行されます. 並列実行やフォークなど細かいタスクのフローを設定することできます. 詳しくは<a target="_blank" rel="nofollow noopener" href="https://github.com/sagiegurari/cargo-make#sub-task">Sub Task</a>を参照してください.</p>
<h4 id="エイリアス"><a href="#%E3%82%A8%E3%82%A4%E3%83%AA%E3%82%A2%E3%82%B9">エイリアス</a></h4>
<p>タスクを別名で参照できます.</p>
<pre><code class="toml">[tasks.build]
alias = "default_build"
</code></pre>
<p>Seedの<a target="_blank" rel="nofollow noopener" href="https://github.com/seed-rs/seed/tree/master/examples">examples</a>フォルダは複数のクレートが含まれており, そこにはMakefile.tomlが存在します. それぞれのクレートではプロジェクト・ルートのMakefile.tomlを拡張する形でルートのタスクを参照しています. つまり実行する処理は同じといことです.</p>
<h4 id="条件付き実行"><a href="#%E6%9D%A1%E4%BB%B6%E4%BB%98%E3%81%8D%E5%AE%9F%E8%A1%8C">条件付き実行</a></h4>
<p>条件を満たした場合にタスクが実行されます.</p>
<pre><code class="toml">[tasks.test-condition]
condition = {
platforms = ["windows", "linux"],
channels = ["beta", "nightly"],
profiles = ["development", "production"],
rust_version = { min = "1.39.0", max = "1.42.0" }
}
script = [
"echo \"condition was met\""
]
</code></pre>
<p>このタスクはmacでstableチャネルを利用している人は実行されません. またscriptの代わりにrun_taskで他のタスクを条件を満たした時だけ実行するということもできます.</p>
<h4 id="watchモード"><a href="#watch%E3%83%A2%E3%83%BC%E3%83%89">watchモード</a></h4>
<p>watch属性をつけるとwatchモードで実行できます.</p>
<pre><code class="toml">[tasks.run_from_script]
script = { file = "hello.py" }
watch = true
</code></pre>
<p>監視対象からの除外のような設定もできます.</p>
<pre><code class="toml">[tasks.watch]
description = "Start building project in watch mode"
workspace = false
dependencies = ["build", "build_wasm"]
watch = { ignore_pattern="pkg/*" }
</code></pre>
<p>watchモードでサーバーを起動することはできません. この場合run_taskのparallelを使うとファイルの変更を監視しながら配信もで可能です.</p>
<pre><code class="toml">[tasks.dev]
description = "Build in watch mode while serving file"
run_task = [
{ name = ["watch", "serve"], parallel = true }
]
</code></pre>
<h3 id="tailwindcssの導入"><a href="#tailwindcss%E3%81%AE%E5%B0%8E%E5%85%A5">tailwindcssの導入</a></h3>
<p>npmを使います.</p>
<pre><code class="bash">npm init # if needed
npm install tailwindcss
</code></pre>
<p>これでtailwindというコマンドがパッケージ上で使えるようになります. cssフォルダを作成して以下の内容をstyle.cssファイルを新規作成します.</p>
<pre><code class="css">@tailwind base;
@tailwind components;
@tailwind utilities;
</code></pre>
<p>これをビルドして利用します. publicフォルダを同じ階層に作っておいて, css用のフォルダを作ります. carg-makeのタスクを追加しましょう.</p>
<pre><code class="toml"># cargo make tailwind
[tasks.tailwind]
script = [
"npx tailwind build ./css/style.css -o ./public/css/style.css",
]
</code></pre>
<p>style.cssからstyle.cssが出力されますが中身を見ると見れ慣れたCSSファイルです. 出力されたファイルをpublic/index.htmlに読み込めばtailwindが提供するユーティリティ・クラスを利用できます.</p>
<p>Seedでtailwindを使ってみましょう. Seedの説明はしませんがRustのマクロを使って要素を記述できます. 注目するのはclassマクロです. ここに指定された文字列がtailwindcssのユーティリティ・クラス名です.</p>
<pre><code class="rust">fn view(model: &Model) -> impl View<Msg> {
let button_class = class!["bg-gray-400", "px-8", "py-4"];
div![
class![
"flex",
"flex-col",
"justify-center",
"items-center",
"h-screen",
"text-gray-600"
],
button![
button_class,
simple_ev(Ev::Click, Msg::Increment),
format!("Click Me!")
],
div![
class!["w-56", "text-center", "mt-2"],
format!("Click {} times", model.counter)
]
]
}
</code></pre>
<p>こんな感じの表示になりちゃんと表示されました(クリック時にカウント数を表示するラベルが動くバグがありますが・・・)</p>
<p><a href="https://crieit.now.sh/upload_images/06db047230e8021afca815dae9b4f1595ea58291385eb.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/06db047230e8021afca815dae9b4f1595ea58291385eb.png?mw=700" alt="Seed with tailwindcss" /></a></p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>もうちょっとまとまりがあれば良いと思ったのですが, 意外と機能が多く詳細は公式の<a target="_blank" rel="nofollow noopener" href="https://github.com/sagiegurari/cargo-make">README.md</a>を読むのがいいと思います. <a target="_blank" rel="nofollow noopener" href="https://github.com/sagiegurari/cargo-make/tree/master/examples">examplesフォルダ</a>に例が豊富なので参考になると思います.</p>
<p>tailwindcssはかなり使いやすいですしSeedもいい感じです(ただビルドが遅いですが・・・).</p>
<h2 id="補足"><a href="#%E8%A3%9C%E8%B6%B3">補足</a></h2>
<h3 id="WorkspaceとWorkspace Flow"><a href="#Workspace%E3%81%A8Workspace+Flow">WorkspaceとWorkspace Flow</a></h3>
<p>タスクにworkspace属性を指定できました. Workspaceとは何でしょうか?</p>
<blockquote>
<p>A workspace is a set of packages that share the same Cargo.lock and output directory.</p>
</blockquote>
<p><a target="_blank" rel="nofollow noopener" href="https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html#cargo-workspaces">Cargo Workspaces - The Rust Programming Language</a></p>
<p>要するに複数のパッケージを一つにまとめたものです. ただし単一のプロジェクトとして管理される前提なので最終生成物やCargo.lockなどで全体のクレートのバージョンなどは共通化されています. 実態は以下のような内容のCargo.tomlとmembers属性で指定されたメンバーとなるパッケージが存在するフォルダです.</p>
<pre><code class="toml">[workspace]
members = [
"client",
"server",
]
</code></pre>
<p>こうした構成はSeedの<a target="_blank" rel="nofollow noopener" href="https://github.com/seed-rs/seed/tree/master/examples/server_integration">server_integration</a>という例が参考になると思います. 例えば適当なウォークスペースにmakefileを作りworkspace属性を指定します.</p>
<pre><code class="toml">[tasks.do_something]
workspace = false
</code></pre>
<p>なぜこのような設定が必要なのでしょうか. 通常cargo-makeのタスクはworkspace直下では実行されません. タスクの要求はメンバー・クレートで実行されます(workspace flow). このおかげでウォークスペースで実行したビルド処理が各クレートで実行されることになり, 共通の処理をウォークスペースにまとめられるので構成ファイルを小さくできます.</p>
<p>しかしウォークスペースで実行したい場合もあるでしょう. その場合にこの機能をオフにするのがworkspace属性の意味です. この値はデフォルトでtrueになっています.</p>
<pre><code class="toml">[config]
default_to_workspace = false
</code></pre>
<p>のようにも指定するとデフォルト値をfalseに上書きできます.</p>
<p>あるいはコマンド実行時にオプションとして渡すこともできます.</p>
<pre><code class="bash">cargo make --no-workspace mytask
</code></pre>
<h3 id="CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILEフラグ"><a href="#CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE%E3%83%95%E3%83%A9%E3%82%B0">CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILEフラグ</a></h3>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/sagiegurari/cargo-make#automatically-extend-workspace-makefile">CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILEフラグ</a>はウォークスペース直下のmakefileに指定します. そうすると自動的に個々のメンバー・クーレトが持つmakefileはルートのmakefileをextendで読み込み参照できるようになるようです.</p>
<h3 id="WASM in A Nutshell"><a href="#WASM+in+A+Nutshell">WASM in A Nutshell</a></h3>
<p>WebAssemblyという技術の略称がWASMでコードの拡張子にもなっている. 通常ブラウザはJavaScriptのランタイムを備えており(V8やスパイダーモンキー)JavaScriptのみを実行できる. JIT(Just In Time)コンパイラによる最適化など高速化されたが, 原理的にはランタイムはJavaScriptを逐次解釈してマシンコードに翻訳しそれを実行するために遅い. このプロセスを飛ばせれば, ネットーワークにるRTT(Round-Trip Time)を無視すればネイティブ並みに高速化できるわけです. これはPythonやRubyなどのインタプリタ言語がC/C++やRustなどの言語より遅い事と基本的には同じ関係と言えそうです.</p>
<p>そこでWeb版のアセンブラを導入しようという話になるわけです. 通常アセンブリ言語はマシン語と1対1に対応するニーモニックを用いて表現されますが, WASMがターゲットとするのは複数のマシンを抽象化したマシンになります.</p>
<blockquote>
<p>So WebAssembly is a little bit different than other kinds of assembly. It’s a machine language for a conceptual machine, not an actual, physical machine.</p>
</blockquote>
<p><img src="https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2017/02/04-03-toolchain07.png" alt="image" /></p>
<p><a target="_blank" rel="nofollow noopener" href="https://hacks.mozilla.org/2017/02/creating-and-working-with-webassembly-modules/">Creating and working with WebAssembly modules</a></p>
<p>この説明を聞くとJavaに近い感じを受ける. 実際に(この比較はおかしいけど)WASIとJavaの類似性を指摘した記事なんかもある.</p>
<p><a target="_blank" rel="nofollow noopener" href="https://www.infoq.com/jp/news/2019/05/wasi-wasm-system-interface/">MozillaがWASIイニシアティブを発表、WebAssemblyをすべてのデバイス、コンピュータ、オペレーティングシステムで動作可能に</a></p>
<p>また公式ではWASMを以下のように定義している.</p>
<blockquote>
<p>WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine.</p>
</blockquote>
<p><a target="_blank" rel="nofollow noopener" href="https://webassembly.org/">WebAssembly</a></p>
<p>スタック・マシンは良くわからないけどWikipediaによると<a target="_blank" rel="nofollow noopener" href="https://ja.wikipedia.org/wiki/Java仮想マシン">Java仮想マシン</a>も似たような定義で紹介されている.</p>
<blockquote>
<p>Java仮想マシン (Java virtual machine、Java VM、JVM) は、Javaバイトコードとして定義された命令セットを実行するスタック型の仮想マシン。</p>
</blockquote>
<h2 id="Reference"><a href="#Reference">Reference</a></h2>
<ol>
<li><a target="_blank" rel="nofollow noopener" href="https://doc.rust-lang.org/cargo/">The Cargo Book</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/sagiegurari/cargo-make#usage-watch">cargo-make</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/seed-rs/seed-quickstart/blob/master/Makefile.toml">Makefile.toml - seed-quickstart</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://seed-rs.org/guide/view">View - Seed</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://tailwindcss.com/docs/installation">Installation - tailwindcss</a></li>
</ol>
<h2 id="例題"><a href="#%E4%BE%8B%E9%A1%8C">例題</a></h2>
<p>タスクの依存関係, watchモードやcrateの導入などcargo-makeの基本的な使い方を学べる.</p>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/seed-rs/seed-quickstart">seed-quickstart</a></p>
<p>examplesフォルダからルート・フォルダにあるMakefile.tomlの参照法などが参考になりました.</p>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/seed-rs/seed/tree/master/examples">examples -seed</a></p>
<h2 id="課題"><a href="#%E8%AA%B2%E9%A1%8C">課題</a></h2>
<p>SeedのようなWebフロントエンドの開発では, プロジェクトをcargoパッケージとしてマインに構成するのかnpmパッケージとしてメインに構成するのかが問題になる. cargo-makeがない場合はnpmパッケージ以下にcargoパッケージを作らないとビルド・プロセスが自動にできない. seed-quickstart-webpackもwebpackを使ってrustライブラリのビルドからwasmモジュールの読み込みなどを行なっている. これをcargo-makeベースに置き換えたい. npm-scriptでコマンド化しておけば, cargo-makeから呼び出せる.</p>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/seed-rs/seed-quickstart-webpack">seed-quickstart-webpack</a></p>
<h2 id="Further Reading"><a href="#Further+Reading">Further Reading</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://hacks.mozilla.org/2017/02/a-crash-course-in-assembly/">A crash course in assembly</a><br />
<a target="_blank" rel="nofollow noopener" href="https://hacks.mozilla.org/2017/02/a-cartoon-intro-to-webassembly/">A cartoon intro to WebAssembly</a><br />
<a target="_blank" rel="nofollow noopener" href="https://hacks.mozilla.org/2017/02/what-makes-webassembly-fast/">What makes WebAssembly fast?</a></p>
ブレイン