Coder Social home page Coder Social logo

newgyu / cargo-component Goto Github PK

View Code? Open in Web Editor NEW

This project forked from bytecodealliance/cargo-component

0.0 0.0 0.0 1.12 MB

A Cargo subcommand for creating WebAssembly components based on the component model proposal.

License: Apache License 2.0

Rust 100.00%

cargo-component's Introduction

cargo component

A Bytecode Alliance project

A cargo subcommand for building WebAssembly components according to the component model proposal.

build status Crates.io version Download docs.rs docs

Overview

cargo component is a cargo subcommand for creating WebAssembly components using Rust as the component's implementation language.

Notice

cargo component is considered to be experimental and is not currently stable in terms of the code it supports building.

Until the component model stabilizes, upgrading to a newer cargo component may cause build errors for existing component projects.

Requirements

  1. The cargo component subcommand is written in Rust, so you'll want the latest stable Rust installed.

Installation

To install the cargo component subcommand, run the following command:

cargo install --git https://github.com/bytecodealliance/cargo-component --locked cargo-component

The currently published crate on crates.io is a nonfunctional placeholder and these instructions will be updated to install the crates.io package once a proper release is made.

Motivation

Today, developers that target WebAssembly typically compile a monolithic program written in a single source language to a WebAssembly module. The WebAssembly module can then be used in all sorts of places: from web browsers to cloud compute platforms. WebAssembly was intentionally designed to provide the portability and security properties required for such environments.

However, WebAssembly modules are not easily composed with other modules into a single program or service. WebAssembly only has a few primitive value types (integer and floating point types) and those are inadequate to describe the complex types that developers would desire to exchange between modules.

To make things even more challenging, WebAssembly modules typically define their own local linear memories, meaning one module can't access the (conceptual) address space of another. Something must sit between the two modules to facilitate communication when pointers are passed around.

While it is possible to solve these challenges with the existing WebAssembly standard, doing so is burdensome, error-prone, and requires foreknowledge of how the WebAssembly modules are implemented.

WebAssembly Component Model

The WebAssembly component model proposal provides a way to simplify the process of building WebAssembly applications and services out of reusable pieces of functionality using a variety of source languages, all while still maintaining the portability and security properties of WebAssembly.

At its most fundamental level, WebAssembly components may be used to wrap a WebAssembly module in a way that describes how its interface, a set of functions using complex value types (e.g. strings, variants, records, lists, etc.), is translated to and from the lower-level representation required of the WebAssembly module.

This enables WebAssembly runtimes to know specifically how they must facilitate the exchange of data between the discrete linear memories of components, eliminating the need for developers to do so by hand.

Additionally, components can describe their dependencies in a way that modules simply cannot today; they can even control how their dependencies are instantiated, enabling a component to virtualize functionality needed by a dependency. And because different components might have a shared dependency, hosts may even share the same implementation of that dependency to save on host memory usage.

Cargo Component

A primary goal of cargo component is to try to imagine what first-class support for WebAssembly components might look like for Rust.

That means being able to reference WebAssembly components via Cargo.toml and have WebAssembly component dependencies used in the same way as Rust crate dependencies:

  • add a dependency on a WebAssembly component to Cargo.toml
  • reference it like you would an external crate (via bindings::<name>::...) in your source code
  • build using cargo component build and out pops your component!

To be able to use a WebAssembly component from any particular programming language, bindings must be created by translating a WebAssembly component's interface to a representation that a specific programming language can understand.

Tools like wit-bindgen exist to generate those bindings for different languages, including Rust.

wit-bindgen even provides procedural macros to generate the bindings "inline" with the component's source code.

Like wit-bindgen, cargo component uses a procedural macro to generate bindings. However, bindings are generated based on the resolved dependencies from Cargo.toml rather than parsing a local definition of the component's interface.

The hope is that one day (in the not too distant future...) that WebAssembly components might become an important part of the Rust ecosystem such that cargo itself might support them.

Until that time, there's cargo component!

Status

A quick note on the implementation status of the component model proposal.

At this time of this writing, no WebAssembly runtimes have fully implemented the component model proposal.

Wasmtime has implementation efforts underway to support it, but it's still a work-in-progress.

Until runtime support grows and additional tools are implemented for linking components together, the usefulness of cargo component today is effectively limited to creating components that runtime and tooling developers can use to test their implementations.

WASI Support

Currently cargo component targets wasm32-wasi by default.

As this target is for a preview1 release of WASI, the WebAssembly module produced by the Rust compiler must be adapted to the preview2 version of WASI supported by the component model.

The adaptation is automatically performed when wasm32-wasi is targeted.

To prevent this, override the target to wasm32-unknown-unknown using the --target option when building. This, however, will disable WASI support.

Use the preview2 version of wasi-common in your host to run components produced by cargo component.

When the Rust compiler supports a preview2 version of the WASI target, support in cargo component for adapting a preview1 module will be removed.

Getting Started

Use cargo component new --reactor <name> to create a new reactor component.

A reactor component doesn't have a run (i.e. main in Rust) function exported and is meant to be used as a library rather than a command that runs and exits. Without the --reactor flag, cargo component defaults to creating a command component.

This will create a wit/world.wit file describing the world that the component will target:

package my-org:my-component

/// An example world for the component to target.
world example {
    export hello-world: func() -> string
}

The component will export a hello-world function returning a string.

The implementation of the component will be in src/lib.rs:

cargo_component_bindings::generate!();

use bindings::Example;

struct Component;

impl Example for Component {
    /// Say hello!
    fn hello_world() -> String {
        "Hello, World!".to_string()
    }
}

The generate! macro is responsible for generating the bindings to allow the Rust code to export what is expected of the component.

It generates a Rust module named bindings containing the types and traits the correspond to the world definition.

Usage

The cargo component subcommand has some analogous commands to cargo itself:

  • cargo component new — creates a new WebAssembly component Rust project.
  • cargo component add — adds a component interface dependency to a cargo manifest file.
  • cargo component update — same as cargo update but also updates the dependencies in the component lock file.
  • cargo component publish - publishes a WebAssembly component to a warg component registry.
  • cargo component key - manages signing keys for publishing WebAssembly components.

Unrecognized commands are passed through to cargo itself, but only after the bindings information for component packages has been updated.

Some examples of commands that are passed directly to cargo are: build, check, doc, clippy and extension commands such as expand from cargo-expand.

Certain command line options, like --target and --release, are detected by cargo component to determine what output files of a build command should be componentized.

Using rust-analyzer

rust-analyzer is an extremely useful tool for analyzing Rust code and is used in many different editors to provide code completion and other features.

rust-analyzer depends on cargo metadata and cargo check to discover workspace information and to check for errors.

To ensure that rust-analyzer is able to discover the latest bindings information, rust-analyzer must be configured to use cargo component check as the check command.

To configure rust-analyzer to use the cargo-component executable, set the rust-analyzer.server.extraEnv setting to the following:

"rust-analyzer.check.overrideCommand": ["cargo", "component", "check", "--message-format=json"]

By default, cargo component new will configure Visual Studio Code to use cargo component check by creating a .vscode/settings.json file for you. To prevent this, pass --editor none to cargo component new.

Please check the documentation for rust-analyzer regarding how to set settings for other IDEs.

Contributing to cargo component

cargo component is a Bytecode Alliance project, and follows the Bytecode Alliance's Code of Conduct and Organizational Code of Conduct.

Getting the Code

You'll clone the code via git:

git clone https://github.com/bytecodealliance/cargo-component

Testing Changes

We'd like tests ideally to be written for all changes. Test can be run via:

cargo test

You'll be adding tests primarily to the tests/ directory.

Submitting Changes

Changes to cargo component are managed through pull requests (PRs). Everyone is welcome to submit a pull request! We'll try to get to reviewing it or responding to it in at most a few days.

Code Formatting

Code is required to be formatted with the current Rust stable's cargo fmt command. This is checked on CI.

Continuous Integration

The CI for the cargo component repository is relatively significant. It tests changes on Windows, macOS, and Linux.

It also performs a "dry run" of the release process to ensure that release binaries can be built and are ready to be published (coming soon).

Publishing (coming soon)

Publication of this crate is entirely automated via CI. A publish happens whenever a tag is pushed to the repository, so to publish a new version you'll want to make a PR that bumps the version numbers (see the bump.rs scripts in the root of the repository), merge the PR, then tag the PR and push the tag. That should trigger all that's necessary to publish all the crates and binaries to crates.io.

cargo-component's People

Contributors

alexcrichton avatar cardoso avatar elliottt avatar esoterra avatar figsoda avatar kajacx avatar macovedj avatar newgyu avatar peterhuene avatar ricochet avatar rylev avatar saulecabrera avatar sunfishcode avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.