David's Blog

Building Cross-Platform Desktop Applications with WebAssembly

By David Li on 2023-10-22T16:26:42.000Z

Building Cross-Platform Desktop Applications with WebAssembly

As the demand for cross-platform desktop applications grows, developers are continuously exploring innovative methods to create efficient and maintainable solutions. With the advent of WebAssembly, a new era of building cross-platform applications has begun. In this article, we’ll explore the potential of WebAssembly for building desktop applications and discuss how to get started with it.

What is WebAssembly?

WebAssembly (Wasm) is a binary instruction format for a stack-based virtual machine. It is designed as a portable target for the compilation of high-level languages like C, C++, and Rust, enabling deployment on the web for client and server applications.

The primary goal of WebAssembly is to provide a compact binary format that enables fast execution and is suitable for use as a compilation target for a variety of programming languages. It achieves this by offering a low-level virtual machine that runs code at near-native speed.

Why Use WebAssembly for Desktop Applications?

There are several reasons to consider WebAssembly for building cross-platform desktop applications:

  1. Performance: WebAssembly code is designed for efficient execution, as it runs at near-native speed. This makes it suitable for performance-critical applications.

  2. Portability: WebAssembly applications can run on any platform that has a compatible virtual machine, making it easy to target multiple platforms without recompiling the code.

  3. Security: WebAssembly has a strong sandboxing mechanism that ensures the safety and isolation of your application.

  4. Language Flexibility: WebAssembly can be used as a compilation target for various languages, allowing developers to continue using their preferred programming languages.

Getting Started with WebAssembly

To build cross-platform desktop applications using WebAssembly, you’ll need a few tools and frameworks in your arsenal. The following are the primary components you’ll work with:

  1. WebAssembly Compiler: To compile your high-level language code into WebAssembly, you’ll need a compatible compiler. For C and C++, you can use Emscripten, while for Rust, you can use the wasm32-unknown-unknown target.

  2. WebAssembly Runtime: To run your WebAssembly code, you’ll need a runtime that provides a virtual machine. Wasmer, Wasmtime, and WebAssembly Micro Runtime (WAMR) are some popular options.

  3. Desktop Framework: To build the user interface and interact with the system, you’ll need a desktop framework. Electron, NW.js, and Tauri are excellent choices for this purpose.

Building a Sample Application

Let’s build a simple cross-platform desktop application using Rust, WebAssembly, and Tauri. We’ll create a basic calculator app as an example.

Prerequisites

Ensure you have the following tools installed on your system:

  • Rust and Cargo
  • Node.js and npm
  • Tauri CLI

Step 1: Create a Rust Library

Create a new Rust library:

$ cargo new wasm_calculator --lib
$ cd wasm_calculator

Edit the src/lib.rs file to add the following code:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[wasm_bindgen]
pub fn subtract(a: i32, b: i32) -> i32 {
    a - b
}

Add the wasm-bindgen dependency to your Cargo.toml:

[dependencies]
wasm-bindgen = "0.2"

Step 2: Compile the Rust Library to WebAssembly

Compile the Rust library to WebAssembly using the following command:

$ cargo build --target wasm32-unknown-unknown --release

This generates a .wasm file in the target/wasm32-unknown-unknown/release directory.

Step 3: Create a Tauri Application

Create a new Tauri application:

$ npx create-tauri-app --name wasm_calculator_app
$ cd wasm_calculator_app

Copy the .wasm file generated earlier to the src-tauri/src directory:

$ cp ../wasm_calculator/target/wasm32-unknown-unknown/release/wasm_calculator.wasm src-tauri/src/

Edit the src-tauri/src/main.rs file to include the WebAssembly module:

fn main() {
    tauri::AppBuilder::default()
        .setup(|app| {
            // Load the WebAssembly module
            let wasm_bytes = include_bytes!("wasm_calculator.wasm");
            let wasm_module = app.load_web_assembly(wasm_bytes).unwrap();

            // Make the WebAssembly module available to the JS context
            app.window().unwrap().eval(&format!("window.wasm_calculator = {}", wasm_module)).unwrap();

            Ok(())
       })
        .build()
        .run();
}

Step 4: Create the User Interface

Edit the `src/index. file to create the user interface for the calculator:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Wasm Calculator</title>
    <link rel="stylesheet" href="index.css" />
</head>
<body>
    <div id="app">
        <h1>Wasm Calculator</h1>
        <input type="number" id="number1" />
        <input type="number" id="number2" />
        <button id="add">Add</button>
        <button id="subtract">Subtract</button>
        <p>Result: <span id="result"></span></p>
    </div>
    <script>
        document.getElementById("add").addEventListener("click", () => {
            const number1 = parseInt(document.getElementById("number1").value);
            const number2 = parseInt(document.getElementById("number2").value);
            const result = window.wasm_calculator.add(number1, number2);
            document.getElementById("result").textContent = result;
        });

        document.getElementById("subtract").addEventListener("click", () => {
            const number1 = parseInt(document.getElementById("number1").value);
            const number2 = parseInt(document.getElementById("number2").value);
            const result = window.wasm_calculator.subtract(number1, number2);
            document.getElementById("result").textContent = result;
        });
    </script>
</body>
</html>

Step 5: Build and Run the Application

Build and run the Tauri application:

$ npm run tauri:build
$ npm run tauri:serve

This will launch a desktop application with a calculator user interface, powered by WebAssembly.

Conclusion

WebAssembly has opened up new possibilities for building cross-platform desktop applications. By combining it with various desktop frameworks, you can create efficient, maintainable, and secure applications that run on multiple platforms. With the ever-growing ecosystem of tools and libraries, the future of WebAssembly in desktop applications looks promising.

© Copyright 2024 by FriendlyUsers Tech Blog. Built with ♥ by FriendlyUser. Last updated on 2024-05-02.