Skip to content

Commit

Permalink
Merge pull request #104 from alexcrichton/components
Browse files Browse the repository at this point in the history
Merge component bindings generation into this repository
  • Loading branch information
alexcrichton authored Nov 18, 2022
2 parents 82dc9f2 + 8d08c55 commit 89d8639
Show file tree
Hide file tree
Showing 38 changed files with 5,120 additions and 47 deletions.
6 changes: 5 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
[flake8]
ignore = F405,F403
max-line-length = 160
exclude = wasmtime/__init__.py,tests/__init__.py
exclude = wasmtime/__init__.py,tests/__init__.py,wasmtime/bindgen/generated/*,tests/codegen/generated/*

per-file-ignores =
# Codegen tests intentionally have some imports not at the top
tests/codegen/*:E402
64 changes: 64 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: 'Setup wasmtime-py CI'
runs:
using: "composite"
steps:
# Setup Python and the Python dependencies of this project
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- run: pip install -e ".[testing]"
shell: bash

# Download precompiled wasmtime binaries for running the project
- run: python ci/download-wasmtime.py
shell: bash

# https://github.com/actions/cache/blob/main/workarounds.md#improving-cache-restore-performance-on-windows-using-cross-os-caching
- if: ${{ runner.os == 'Windows' }}
name: Use GNU tar
shell: cmd
run: |
echo "Adding GNU tar to PATH"
echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%"
# Ensure the Rust lockfile is up-to-date
- uses: actions/cache@v3
with:
path: |
~/.cargo/registry/index
~/.cargo/git/db
key: cargo-registry-${{ hashFiles('rust/Cargo.lock') }}
- run: cargo fetch --manifest-path rust/Cargo.toml --locked
shell: bash

# Install the `wasm-tools` binary with the `component` subcommand that is all
# that's needed here.
- uses: actions/cache@v3
with:
path: ${{ runner.tool_cache }}/wasm-tools
key: wasm-tools-bin-e15e768a346c30738103d372e8ccf442646628c9-${{ runner.os }}
- run: echo '${{ runner.tool_cache }}/wasm-tools/bin' >> $GITHUB_PATH
shell: bash
- run: |
cargo install \
wasm-tools \
--root '${{ runner.tool_cache }}/wasm-tools' \
--git https://github.com/bytecodealliance/wasm-tools \
--rev e15e768a346c30738103d372e8ccf442646628c9 \
--no-default-features \
--features component
shell: bash
# Build the bindgen wasm blob with some extra Rust targets.
- run: |
rustup target add wasm32-unknown-unknown wasm32-wasi
echo CARGO_INCREMENTAL=0 >> $GITHUB_ENV
echo CARGO_PROFILE_DEV_DEBUG=0 >> $GITHUB_ENV
echo RUSTC_VERSION=`rustc --version` >> $GITHUB_ENV
shell: bash
- uses: actions/cache@v3
with:
path: rust/target
key: rust-target-${{ env.RUSTC_VERSION }}-${{ runner.os }}-${{ hashFiles('rust/Cargo.lock') }}
- run: python ci/build-rust.py
shell: bash
78 changes: 38 additions & 40 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,46 +27,51 @@ jobs:
- os: windows-latest
python-version: pypy3
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- run: python download-wasmtime.py
- run: pip install -e ".[testing]"
# Tests are flaky on Windows. It's something to do with generating modules
# on-the-go in the component codegen tests. I have no idea how to fix it.
# This is a last-ditch attempt to get things working.
- run: pytest --setup-only
continue-on-error: true
- run: pytest

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- run: pip install setuptools wheel
# If this is a tagged build use real version numbers
- run: echo "PROD=true" >> $GITHUB_ENV
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
- run: |
git clean -fdx wasmtime build
python download-wasmtime.py linux x86_64
python ci/download-wasmtime.py linux x86_64
python ci/build-rust.py
python setup.py bdist_wheel --plat-name manylinux1-x86_64
- run: |
git clean -fdx wasmtime build
python download-wasmtime.py linux aarch64
python ci/download-wasmtime.py linux aarch64
python ci/build-rust.py
python setup.py bdist_wheel --plat-name manylinux2014_aarch64
- run: |
git clean -fdx wasmtime build
python download-wasmtime.py darwin x86_64
python ci/download-wasmtime.py darwin x86_64
python ci/build-rust.py
python setup.py bdist_wheel --plat-name macosx-10-13-x86_64
- run: |
git clean -fdx wasmtime build
python download-wasmtime.py darwin arm64
python ci/download-wasmtime.py darwin arm64
python setup.py bdist_wheel --plat-name macosx-11-0-arm64
python ci/build-rust.py
- run: |
git clean -fdx wasmtime build
python download-wasmtime.py win32 x86_64
python ci/download-wasmtime.py win32 x86_64
python ci/build-rust.py
python setup.py bdist_wheel --plat-name win-amd64
# Build an "any" wheel with:
Expand All @@ -80,41 +85,35 @@ jobs:
# shared libraries.
- run: |
git clean -fdx wasmtime build
python download-wasmtime.py win32 x86_64
python ci/download-wasmtime.py win32 x86_64
python ci/build-rust.py
python setup.py bdist_wheel
- uses: actions/upload-artifact@v1
- uses: actions/upload-artifact@v3
with:
name: wheels
path: dist

docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- run: pip install pdoc3
- run: python download-wasmtime.py
- run: pdoc --html wasmtime
- uses: actions/upload-artifact@v1
- uses: actions/upload-artifact@v3
with:
name: generated-docs
path: html/wasmtime

coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- run: python download-wasmtime.py
- run: pip install -e ".[testing]"
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- run: coverage run -m pytest
- run: coverage html
- uses: actions/upload-artifact@v1
- uses: actions/upload-artifact@v3
with:
name: coverage
path: htmlcov
Expand All @@ -123,15 +122,16 @@ jobs:
needs: [coverage, docs]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v1
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: coverage
- uses: actions/download-artifact@v1
path: generated-docs/coverage
- uses: actions/download-artifact@v3
with:
name: generated-docs
path: generated-docs
- run: find .
- run: mv coverage generated-docs
- uses: JamesIves/[email protected]
with:
branch: gh-pages
Expand All @@ -143,15 +143,13 @@ jobs:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- uses: actions/download-artifact@v1
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- uses: actions/download-artifact@v3
with:
name: wheels
path: dist
- run: find .
- run: mv wheels dist

- name: Publish distribution 📦 to Test PyPI
if: github.event_name == 'push'
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ wasmtime/linux-*
wasmtime/darwin-*
wasmtime/win32-*
wasmtime/include
wasmtime/bindgen/generated
tests/codegen/generated
9 changes: 8 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@ in the top-level directory of the package's source (this is what CI does):
[wasmtime]: https://wasmtime.dev/

```sh
$ python download-wasmtime.py
$ python ci/download-wasmtime.py
```

Otherwise if you have a local checkout of Wasmtime you can symlink its
`libwasmtime.so` (or equivalent) to `wasmtime/linux-x86_64/_libwasmtime.so` (or
equivalent).

Next the bindings generation requires compiling some Rust code to WebAssembly,
which can be done with:

```sh
$ python ci/build-rust.py
```

Finally, install the dev dependencies with `pip`:

```
Expand Down
4 changes: 1 addition & 3 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
recursive-include wasmtime *.so
recursive-include wasmtime *.dll
recursive-include wasmtime *.dylib
recursive-include wasmtime *.py *.wasm *.so *.dll *.dylib
83 changes: 83 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,89 @@ import your_wasm_file
print(your_wasm_file.run())
```

## Components

The `wasmtime` package has initial support for running WebAssembly components in
Python with high-level bindings. WebAssembly components are defined by the
[component model] and are a flagship feature under development for Wasmtime and
its bindings. Components enable communication between the host and WebAssembly
guests with richer types than the numerical primitives supported by core
WebAssembly. For example with a component Python can pass a string to wasm and
back.

Components are represented as `*.wasm` binaries in the same manner as core
WebAssembly modules. With a component binary you can generate Python bindings
with:

```sh
$ python -m wasmtime.bindgen the-component.wasm --out-dir the-bindings
```

An example of using this can be done with the [`wasm-tools`] repository. For
example with this core wasm module at `demo.wat`:

```wasm
(module
(import "python" "print" (func $print (param i32 i32)))
(memory (export "memory") 1)
(func (export "run")
i32.const 100 ;; base pointer of string
i32.const 13 ;; length of string
call $print)
(data (i32.const 100) "Hello, world!")
)
```

and with this [`*.wit`] interface at `demo.wit`:

```text
world demo {
import python: interface {
print: func(s: string)
}
default export interface {
run: func()
}
}
```

And this `demo.py` script

```python
from demo import Demo, DemoImports, imports
from wasmtime import Store

class Host(imports.Python):
def print(self, s: str):
print(s)

def main():
store = Store()
demo = Demo(store, DemoImports(Host()))
demo.run(store)

if __name__ == '__main__':
main()
```

```sh
$ wasm-tools component new demo.wat --wit demo.wit -o demo.wasm
$ python -m wasmtime.bindgen demo.wasm --out-dir demo
$ python demo.py
Hello, world!
```

The generated package `demo` has all of the requisite exports/imports into the
component bound. The `demo` package is additionally annotated with types to
assist with type-checking and self-documentation as much as possible.

[component model]: https://github.com/WebAssembly/component-model
[`wasm-tools`]: https://githubcom/bytecodealliance/wasm-tools
[`*.wit`]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md

## Contributing

See [`CONTRIBUTING.md`](./CONTRIBUTING.md).
Loading

0 comments on commit 89d8639

Please sign in to comment.