// SPDX-License-Identifier: LGPL-3.0-only // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® import std; import Crafter.Build; namespace fs = std::filesystem; using namespace Crafter; // A wasm build end to end: the fixture is compiled for wasm32-wasip1 against // the resolved toolchain's WASI sysroot and the result is run under // wasmtime. The other wasm tests only inspect generated files; this is the // one that proves the sysroot, the std module for wasm and wasm-ld all work // together. It skips when the sysroot or wasmtime is missing, so a // development box without them is not a failure. Inside the Flatpak both are // bundled, and there the skip would be the failure to look for. int main() { const Toolchain& tc = GetToolchain(); if (!fs::exists(tc.wasiSysroot / "include")) { std::println(std::cerr, "SKIP: no WASI sysroot at {}", tc.wasiSysroot.string()); return 77; } if (std::system("which wasmtime > /dev/null 2>&1") != 0) { std::println(std::cerr, "SKIP: wasmtime not on PATH"); return 77; } Configuration cfg; cfg.path = fs::current_path() / "tests" / "WasmHelloRuns" / "fixture"; cfg.name = "wasm-hello"; cfg.outputName = "wasm-hello"; cfg.target = "wasm32-wasip1"; cfg.type = ConfigurationType::Executable; std::array ifaces = {}; std::array impls = { "main" }; cfg.GetInterfacesAndImplementations(ifaces, impls); std::unordered_map> depResults; std::mutex depMutex; BuildResult r = Build(cfg, depResults, depMutex); if (!r.result.empty()) { std::println(std::cerr, "build failed: {}", r.result); return 1; } const fs::path wasm = ExpectedOutput(cfg); if (!fs::exists(wasm)) { std::println(std::cerr, "no .wasm produced at {}", wasm.string()); return 1; } const auto run = RunCommandWithTimeout(std::format("wasmtime {}", wasm.string()), std::chrono::seconds(60)); if (run.exitCode != 0 || !run.output.contains("hello from wasm")) { std::println(std::cerr, "wasmtime run failed (exit {}): {}", run.exitCode, run.output); return 1; } return 0; }