# WasmEdge 基礎介紹跟專案架構


## Wasm 基礎背景

檔案格式：

* `.wat` (WebAssembly Text Format): 人眼可讀的純文字格式。類似於組合語言，開發者可以用它來進行底層除錯或理解 Wasm 的運行邏輯
* `.wasm` (WebAssembly Binary Format): 二進制格式。這是 Wasm 的標準執行檔，體積小且跨平台，是交給瀏覽器或 WasmEdge 等運行環境執行的正式檔案
* `.aot.wasm` (Ahead-of-Time Compiled): 預先編譯後的格式，這是 WasmEdge 特有的優化檔案，將 `.wasm` 事先轉譯成機器碼。執行時不需要再經過「直譯」，速度會比純 `.wasm` 快非常多

常見工具：

* WABT (WebAssembly Binary Toolkit): 這是一套 Wasm 的基礎工具包，其中最常用的是 `wat2wasm`，它能將人類看得懂的 `.wat` 文字檔轉換成電腦執行的 `.wasm` 二進制檔
* WasmEdge Runtime: 有不同高效能的 Wasm 執行引擎
  * Interpreter (直譯) 模式： 逐行讀取並執行，靈活性高但速度較慢
  * AOT (預先編譯) 模式： 配合編譯後的 .aot.wasm 執行，效能接近原生程式（Native code）
* Emscripten (emcc)：這是一個強大的編譯器工具鏈，基於 LLVM，它能讓開發者直接將現有的 C 或 C++ 專案編譯成 WebAssembly。它不僅處理程式碼，還會處理系統呼叫（System Calls）和庫的連結，是 C++ 進入 Wasm 世界的主流工具

## WasmEdge

在 WebAssembly 的世界裡，有幾個著名的 Runtime（如 Wasmtime, Wasmer），而 WasmEdge 專攻的是 「高效能、雲原生 (Cloud Native) 與邊緣運算 (Edge)」。

### 專案架構

* include/: 定義不同標頭檔
  * api/: WasmEdge 的 C API 定義（這是外部整合最常用的入口）
  * runtime/: 核心組件的定義，包括你正在修改的 store.h (StoreManager) 和 instance
* lib/: 各種核心實作

你可以參考 [Build Guide | WasmEdge Developer Guides](https://wasmedge.org/docs/contribute/source/build_from_src/) 來自己編譯專案，基本上使用 CMake 設定 Make config，然後跑 `make`，或者你可以用 `-Bbuild -GNinja` 用 `ninja` 提升編譯時間。

```bash
sudo apt update
sudo apt install -y git cmake ninja-build build-essential llvm-15-dev liblld-15-dev
git clone https://github.com/WasmEdge/WasmEdge.git
cd WasmEdge
mkdir -p build && cd build
# 開啟測試選項，這樣才能跑 Unit Test
cmake -GNinja -DWASMEDGE_BUILD_TESTS=ON ..
ninja
ctest
```

最後會在 build 目錄底下看到產生的東西。

```bash
kola:~/proj/WasmEdge/build$ ls
build.ninja            CPackConfig.cmake        include  thirdparty
CMakeCache.txt         CPackSourceConfig.cmake  lib      tools
CMakeFiles             CTestTestfile.cmake      plugins
cmake_install.cmake    DartConfiguration.tcl    test
compile_commands.json  _deps                    Testing
```

基本上編譯的時候要 (假如用 `g++`)：

1. 指定標頭檔 (`-I./build/include/api`)
2. 連結共享庫 (-L 與 -l)，用 `-L./build/lib/api` 指定庫的搜尋路徑，使用 -lwasmedge 告訴編譯器連結 `libwasmedge.so`
3. 設定執行路徑 (`LD_LIBRARY_PATH`)，`LD_LIBRARY_PATH=./build/lib/api` 添加目錄，讓 Loader 去這個目錄找動態連結的 .so 檔案

### 測試

如果你有在 camke 使用 `-DWASMEDGE_BUILD_TESTS=ON`，你可以在 `build` 目錄使用 ctest 跑測試。

而實際上測試都放在 `test/` 目錄底下，底下有包含不同種類的測試，像是 api, aot ...

舉理我們看 `test/api/APIVMCoreTest.cpp`

```cpp
TEST(WasmEdgeVM, ForceDeleteRegisteredModule) {
  WasmEdge_ConfigureContext *Conf = WasmEdge_ConfigureCreate();
  WasmEdge_VMContext *VMCxt = WasmEdge_VMCreate(Conf, nullptr);

  uint32_t originalCount = WasmEdge_VMListRegisteredModuleLength(VMCxt);

  WasmEdge_String ModuleName = WasmEdge_StringCreateByCString("test_module");
  WasmEdge_ModuleInstanceContext *ModInst =
      WasmEdge_ModuleInstanceCreate(ModuleName);

  WasmEdge_Result Res = WasmEdge_VMRegisterModuleFromImport(VMCxt, ModInst);
  EXPECT_TRUE(WasmEdge_ResultOK(Res));
  EXPECT_EQ(WasmEdge_VMListRegisteredModuleLength(VMCxt), originalCount + 1);

  // Force delete
  WasmEdge_VMForceDeleteRegisteredModule(VMCxt, ModuleName);
  EXPECT_EQ(WasmEdge_VMListRegisteredModuleLength(VMCxt), originalCount);

  // Added check to ensure module is no longer accessible
  WasmEdge_StoreContext *StoreCxt = WasmEdge_VMGetStoreContext(VMCxt);
  const WasmEdge_ModuleInstanceContext *FindResult =
      WasmEdge_StoreFindModule(StoreCxt, ModuleName);
  EXPECT_EQ(FindResult, nullptr);

  // Cleanup
  WasmEdge_StringDelete(ModuleName);
  WasmEdge_VMDelete(VMCxt);
  WasmEdge_ConfigureDelete(Conf);
}
```

它每個測試都是用 `TEST()` 包裝的，`TEST(SuiteName, TestName)` 是 gtest 的基本 macro。`EXPECT_*` 與 `ASSERT_*`: 用來斷言結果。例如 EXPECT_EQ 檢查相等，EXPECT_TRUE 檢查布林值。

雖然測試程式碼本身不寫釋放檢查，但 WasmEdge 的 CI 會跑 ASan (AddressSanitizer) 。如果你「太早刪除」導致 Use-After-Free，測試就會噴錯。

我們可以用

```bash
cd build/test/api/
./wasmedgeAPIVMCoreTests --gtest_filter=WasmEdgeVM.ForceDeleteRegisteredModule
```

跑特定測試，不然預設 ctest 跑所有測試。

#### 官方測試資料

根據 [Shipping binary precompiled WASM files is problematic for downstreams #1869](https://github.com/WasmEdge/WasmEdge/issues/1869)，以前測試資料還會有 `wasm` binary 檔案，現在不回有了。

並且你看測試，他們其實會用 `wast2json`，官方測試通常是 `.wast` 格式（S-Expression 腳本）。WasmEdge 使用 `wast2json` 這個工具把一個 `.wast` 檔案拆開，變成一個包含指令的 json 檔案和一堆二進制的 wasm 檔案，可以看 [WasmEdge-spectest](https://github.com/WasmEdge/wasmedge-spectest)。

