├── .cargo └── config.toml ├── .devcontainer ├── Dockerfile ├── devcontainer.json └── finalize.sh ├── .github ├── dependabot.yml └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── ORG_CODE_OF_CONDUCT.md ├── README.md ├── SECURITY.md ├── crates └── wamr-sys │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ └── src │ └── lib.rs ├── examples └── wasi-hello │ ├── Cargo.lock │ ├── Cargo.toml │ ├── gcd_wasm32_wasi.wasm │ └── src │ └── main.rs ├── resources └── test │ ├── add-extra │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── add_extra_wasm32_wasi.wasm │ ├── gcd │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── gcd_wasm32_wasi.wasm │ ├── multiret.wasm │ ├── multiret │ └── multiret.wat │ └── wasi-demo-app.wasm └── src ├── function.rs ├── helper.rs ├── host_function.rs ├── instance.rs ├── lib.rs ├── module.rs ├── runtime.rs ├── value.rs └── wasi_context.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [env] 2 | # vprintf callback. refer to https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/build_wamr.md?plain=1#L193 3 | #WAMR_BH_VPRINTF = "" 4 | 5 | # for a new platform , please refer to https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/port_wamr.md#wamr-porting-guide 6 | # need to prepare relative stuff and set the following variables 7 | # - WAMR_BUILD_PLATFORM 8 | # - WAMR_BUILD_TARGET 9 | # - WAMR_BUILD_PLATFORM 10 | 11 | # for an existing platform, following variables are required: 12 | # - WAMR_BUILD_PLATFORM 13 | # - WAMR_BUILD_TARGET 14 | # 15 | # default combination is "linux" and "X86_64" and for convenience, you don't need to set them. 16 | # 17 | # for a un-default platform, you need to set the following variables. 18 | # please refer to CMakeLists.txt in https://github.com/bytecodealliance/wasm-micro-runtime/tree/main/product-mini/platforms for more details. 19 | # - WAMR_BUILD_PLATFORM. Options are "alios-things", "android", "cosmopolitan", "darwin", "freebsd", "linux", "linux-sgx", "nuttx", "riot", "rt-thread", "vsworks", "windows", "zephyr" 20 | # - WAMR_BUILD_TARGET. Options are "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" 21 | 22 | #WAMR_BUILD_PLATFORM = "OS name" 23 | #WAMR_BUILD_TARGET = "CPU architecture" 24 | #WAMR_BUILD_PLATFORM = "" 25 | 26 | # change it to your own LLVM lib path 27 | LLVM_LIB_CFG_PATH = "/usr/lib/llvm-15/cmake/" 28 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | ENV TZ=Asian/Shanghai 5 | 6 | RUN apt-get update \ 7 | && apt-get upgrade -y \ 8 | && apt-get install --no-install-recommends -y cmake gnupg lsb-release software-properties-common wget 9 | 10 | RUN cd /tmp \ 11 | && wget https://apt.llvm.org/llvm.sh \ 12 | && chmod a+x llvm.sh \ 13 | && ./llvm.sh 15 14 | 15 | RUN ln -sf /usr/bin/lldb-15 /usr/bin/lldb 16 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/rust 3 | { 4 | "name": "wamr-rust-sdk", 5 | "build": { 6 | "dockerfile": "Dockerfile" 7 | }, 8 | // Use 'mounts' to make the cargo cache persistent in a Docker Volume. 9 | // "mounts": [ 10 | // { 11 | // "source": "devcontainer-cargo-cache-${devcontainerId}", 12 | // "target": "/usr/local/cargo", 13 | // "type": "volume" 14 | // } 15 | // ] 16 | // Features to add to the dev container. More info: https://containers.dev/features. 17 | // "features": {}, 18 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 19 | // "forwardPorts": [], 20 | // Use 'postCreateCommand' to run commands after the container is created. 21 | //"postCreateCommand": "rustc --version", 22 | "postCreateCommand": "bash .devcontainer/finalize.sh", 23 | // Configure tool-specific properties. 24 | "customizations": { 25 | "settings": { 26 | "lldb.executable": "/usr/bin/lldb", 27 | "terminal.integrated.shell.linux": "/bin/bash" 28 | }, 29 | "vscode": { 30 | "extensions": [ 31 | "DavidAnson.vscode-markdownlint", 32 | "dtsvet.vscode-wasm", 33 | "fill-labs.dependi", 34 | "rust-lang.rust-analyzer", 35 | "streetsidesoftware.code-spell-checker", 36 | "tamasfe.even-better-toml", 37 | "vadimcn.vscode-lldb" 38 | ], 39 | } 40 | }, 41 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 42 | "remoteUser": "vscode" 43 | } 44 | -------------------------------------------------------------------------------- /.devcontainer/finalize.sh: -------------------------------------------------------------------------------- 1 | printf "Running 'postCreateCommand' Script\n" 2 | 3 | # Install Rust Targets 4 | printf "Installing Rust Targets\n" 5 | #rustup update stable --no-self-update 6 | rustup default stable 7 | rustup target add wasm32-unknown-unknown 8 | rustup target add wasm32-wasip1 9 | rustup component add clippy 10 | rustup component add rustfmt 11 | 12 | cargo install cargo-readme 13 | cargo install rustfilt 14 | 15 | # Install Python stuff 16 | printf "Installing Python Dependencies" 17 | 18 | # Install NPM dependencies 19 | printf "Installing NPM Dependencies" 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Intel Corporation. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | version: 2 5 | updates: 6 | 7 | - package-ecosystem: "github-actions" 8 | directory: "/" 9 | schedule: 10 | interval: "weekly" 11 | 12 | - package-ecosystem: "cargo" 13 | directory: "/" 14 | schedule: 15 | interval: "weekly" 16 | 17 | - package-ecosystem: "cargo" 18 | directory: "/examples/wasi-hello" 19 | schedule: 20 | interval: "weekly" 21 | 22 | - package-ecosystem: "cargo" 23 | directory: "/resources/test/add-extra/" 24 | schedule: 25 | interval: "weekly" 26 | 27 | - package-ecosystem: "cargo" 28 | directory: "/resources/test/gcd/" 29 | schedule: 30 | interval: "weekly" 31 | 32 | - package-ecosystem: "gitsubmodule" 33 | directory: "/crates/wamr-sys/wasm-micro-runtime/" 34 | schedule: 35 | interval: "weekly" 36 | 37 | - package-ecosystem: "docker" 38 | directory: "/.devcontainer" 39 | schedule: 40 | interval: "weekly" 41 | 42 | - package-ecosystem: "devcontainers" 43 | directory: "/" 44 | schedule: 45 | interval: "weekly" 46 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Intel Corporation. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | name: linter and test 4 | 5 | on: 6 | # will be triggered on PR events 7 | pull_request: 8 | types: 9 | - opened 10 | - synchronize 11 | paths: 12 | - ".github/**" 13 | - "crates/**" 14 | - "src/**" 15 | 16 | push: 17 | branches: 18 | - main 19 | - "dev/**" 20 | paths: 21 | - "crates/**" 22 | - "src/**" 23 | 24 | # allow to be triggered manually 25 | workflow_dispatch: 26 | 27 | # Cancel any in-flight jobs for the same PR/branch so there's only one active 28 | # at a time 29 | concurrency: 30 | group: ${{ github.workflow }}-${{ github.ref }} 31 | cancel-in-progress: true 32 | 33 | # Make sure CI fails on all warnings, including Clippy lints 34 | env: 35 | RUSTFLAGS: "-Dwarnings" 36 | 37 | jobs: 38 | # linter 39 | clippy_check: 40 | # ubuntu 24.04 doesn't have LLVM 15(https://apt.llvm.org/noble/dists/), 41 | # so we use 22.04 42 | runs-on: ubuntu-22.04 43 | steps: 44 | - uses: actions/checkout@v4 45 | with: 46 | submodules: true 47 | 48 | - name: Run Clippy 49 | run: | 50 | cargo clippy --all-targets --all-features 51 | 52 | # all test cases with default features 53 | test: 54 | # ubuntu 24.04 doesn't have LLVM 15(https://apt.llvm.org/noble/dists/), 55 | # so we use 22.04 56 | runs-on: ubuntu-22.04 57 | steps: 58 | - uses: actions/checkout@v4 59 | with: 60 | submodules: true 61 | 62 | - name: Run test cases 63 | run: cargo test --lib 64 | 65 | - name: Run test cases sequentially 66 | run: cargo test --lib -- --ignored --test-threads 1 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # cargo 2 | **/target/ 3 | 4 | # vscode 5 | *.code-workspace 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "crates/wamr-sys/wasm-micro-runtime"] 2 | path = crates/wamr-sys/wasm-micro-runtime 3 | url = https://github.com/bytecodealliance/wasm-micro-runtime 4 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # In this project, we use CODEOWNERS to identify people who are likely to know 2 | # who should review a pull request. 3 | # 4 | # People listed in this file are committing to respond in a timely fashion to 5 | # PRs in the selected areas. However, that response doesn't have to be a full 6 | # code review; it could also take any of these forms: 7 | # 8 | # - "I intend to review this but I can't yet. Please leave me a message if I 9 | # haven't responded by (a specific date in the near future)." 10 | # 11 | # - "I think (a specific other contributor) should review this." (Note that the 12 | # best reviewer for a PR may not necessarily be listed in this file.) 13 | # 14 | # People must only be added to this file if they've agreed to provide one of 15 | # the above responses in a reasonable amount of time for every PR to which 16 | # they're assigned. 17 | # 18 | # We only ask for this commitment from people who are employed full-time to 19 | # work on this project. We gratefully welcome reviews from other contributors, 20 | # but we don't believe it's fair to ask volunteers to respond quickly. 21 | 22 | # If none of the later patterns match, assign to 23 | * @lum1n0us @TianlongLiang @wenyongh @xujuntwt95329 24 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | *Note*: this Code of Conduct pertains to individuals' behavior. Please also see the [Organizational Code of Conduct][OCoC]. 4 | 5 | ## Our Pledge 6 | 7 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 8 | 9 | ## Our Standards 10 | 11 | Examples of behavior that contributes to creating a positive environment include: 12 | 13 | * Using welcoming and inclusive language 14 | * Being respectful of differing viewpoints and experiences 15 | * Gracefully accepting constructive criticism 16 | * Focusing on what is best for the community 17 | * Showing empathy towards other community members 18 | 19 | Examples of unacceptable behavior by participants include: 20 | 21 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 22 | * Trolling, insulting/derogatory comments, and personal or political attacks 23 | * Public or private harassment 24 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 25 | * Other conduct which could reasonably be considered inappropriate in a professional setting 26 | 27 | ## Our Responsibilities 28 | 29 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 30 | 31 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 32 | 33 | ## Scope 34 | 35 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 36 | 37 | ## Enforcement 38 | 39 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Bytecode Alliance CoC team at [report@bytecodealliance.org](mailto:report@bytecodealliance.org). The CoC team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The CoC team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 40 | 41 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the Bytecode Alliance's leadership. 42 | 43 | ## Attribution 44 | 45 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 46 | 47 | [OCoC]: ORG_CODE_OF_CONDUCT.md 48 | [homepage]: https://www.contributor-covenant.org 49 | [version]: https://www.contributor-covenant.org/version/1/4/ 50 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to WAMR-Rust-SDK 2 | ===================== 3 | As an open-source project, we welcome and encourage the community to submit patches directly to the project. In our collaborative open source environment, standards and methods for submitting changes help reduce the chaos that can result from an active development community. 4 | We want to make contributing to this project as easy and transparent as possible, whether it's: 5 | - Reporting a bug 6 | - the current state of the code 7 | - Submitting a fix 8 | - Proposing new features 9 | 10 | License 11 | ======= 12 | WAMR-Rust-SDK uses the same license as LLVM: the `Apache 2.0 license` with the LLVM 13 | exception. See the LICENSE file for details. This license allows you to freely 14 | use, modify, distribute and sell your own products based on WAMR. 15 | Any contributions you make will be under the same license. 16 | 17 | Code changes 18 | =================== 19 | We Use Github Flow, So All Code Changes Happen Through Pull Requests. Pull requests are the best way to propose changes to the codebase. We actively welcome your pull requests: 20 | 21 | - If you've added code that should be tested, add tests. Ensure the test suite passes. 22 | - Avoid use macros for different platforms. Use seperate folder of source files to host diffeent platform logic. 23 | - Put macro definitions inside share_lib/include/config.h if you have to use macro. 24 | - Make sure your code lints and compliant to our coding style. 25 | - Extend the application library is highly welcome. 26 | 27 | Coding Style 28 | =============================== 29 | Please use `cargo fmt` to maintain the coding style. 30 | 31 | Report bugs 32 | =================== 33 | We use GitHub issues to track public bugs. Report a bug by [open a new issue](https://github.com/bytecodealliance/wamr-rust-sdk/issues/new). 34 | 35 | Code of Conduct 36 | =============== 37 | 38 | WAMR-Rust-SDK is a [Bytecode Alliance](https://bytecodealliance.org/) project, and follows the Bytecode Alliance's [Code of Conduct](CODE_OF_CONDUCT.md) and [Organizational Code of Conduct](ORG_CODE_OF_CONDUCT.md). 39 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "aligned" 16 | version = "0.4.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" 19 | dependencies = [ 20 | "as-slice", 21 | ] 22 | 23 | [[package]] 24 | name = "android-tzdata" 25 | version = "0.1.1" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 28 | 29 | [[package]] 30 | name = "android_system_properties" 31 | version = "0.1.5" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 34 | dependencies = [ 35 | "libc", 36 | ] 37 | 38 | [[package]] 39 | name = "anyhow" 40 | version = "1.0.95" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" 43 | 44 | [[package]] 45 | name = "as-slice" 46 | version = "0.2.1" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" 49 | dependencies = [ 50 | "stable_deref_trait", 51 | ] 52 | 53 | [[package]] 54 | name = "autocfg" 55 | version = "1.4.0" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 58 | 59 | [[package]] 60 | name = "bindgen" 61 | version = "0.71.1" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" 64 | dependencies = [ 65 | "bitflags 2.8.0", 66 | "cexpr", 67 | "clang-sys", 68 | "itertools", 69 | "log", 70 | "prettyplease", 71 | "proc-macro2", 72 | "quote", 73 | "regex", 74 | "rustc-hash", 75 | "shlex", 76 | "syn 2.0.96", 77 | ] 78 | 79 | [[package]] 80 | name = "bitflags" 81 | version = "1.3.2" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 84 | 85 | [[package]] 86 | name = "bitflags" 87 | version = "2.8.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" 90 | 91 | [[package]] 92 | name = "bstr" 93 | version = "1.11.3" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" 96 | dependencies = [ 97 | "memchr", 98 | "serde", 99 | ] 100 | 101 | [[package]] 102 | name = "build-time" 103 | version = "0.1.3" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "f1219c19fc29b7bfd74b7968b420aff5bc951cf517800176e795d6b2300dd382" 106 | dependencies = [ 107 | "chrono", 108 | "once_cell", 109 | "proc-macro2", 110 | "quote", 111 | "syn 2.0.96", 112 | ] 113 | 114 | [[package]] 115 | name = "bumpalo" 116 | version = "3.16.0" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 119 | 120 | [[package]] 121 | name = "camino" 122 | version = "1.1.9" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" 125 | dependencies = [ 126 | "serde", 127 | ] 128 | 129 | [[package]] 130 | name = "cargo-platform" 131 | version = "0.1.9" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" 134 | dependencies = [ 135 | "serde", 136 | ] 137 | 138 | [[package]] 139 | name = "cargo_metadata" 140 | version = "0.18.1" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" 143 | dependencies = [ 144 | "camino", 145 | "cargo-platform", 146 | "semver", 147 | "serde", 148 | "serde_json", 149 | "thiserror", 150 | ] 151 | 152 | [[package]] 153 | name = "cc" 154 | version = "1.2.24" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" 157 | dependencies = [ 158 | "shlex", 159 | ] 160 | 161 | [[package]] 162 | name = "cexpr" 163 | version = "0.6.0" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 166 | dependencies = [ 167 | "nom", 168 | ] 169 | 170 | [[package]] 171 | name = "cfg-if" 172 | version = "1.0.0" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 175 | 176 | [[package]] 177 | name = "cfg_aliases" 178 | version = "0.2.1" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 181 | 182 | [[package]] 183 | name = "chrono" 184 | version = "0.4.39" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" 187 | dependencies = [ 188 | "android-tzdata", 189 | "iana-time-zone", 190 | "num-traits", 191 | "windows-targets", 192 | ] 193 | 194 | [[package]] 195 | name = "clang-sys" 196 | version = "1.8.1" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" 199 | dependencies = [ 200 | "glob", 201 | "libc", 202 | "libloading", 203 | ] 204 | 205 | [[package]] 206 | name = "cmake" 207 | version = "0.1.54" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" 210 | dependencies = [ 211 | "cc", 212 | ] 213 | 214 | [[package]] 215 | name = "const_format" 216 | version = "0.2.34" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" 219 | dependencies = [ 220 | "const_format_proc_macros", 221 | ] 222 | 223 | [[package]] 224 | name = "const_format_proc_macros" 225 | version = "0.2.34" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" 228 | dependencies = [ 229 | "proc-macro2", 230 | "quote", 231 | "unicode-xid", 232 | ] 233 | 234 | [[package]] 235 | name = "core-foundation-sys" 236 | version = "0.8.7" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 239 | 240 | [[package]] 241 | name = "crossbeam-deque" 242 | version = "0.8.6" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 245 | dependencies = [ 246 | "crossbeam-epoch", 247 | "crossbeam-utils", 248 | ] 249 | 250 | [[package]] 251 | name = "crossbeam-epoch" 252 | version = "0.9.18" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 255 | dependencies = [ 256 | "crossbeam-utils", 257 | ] 258 | 259 | [[package]] 260 | name = "crossbeam-utils" 261 | version = "0.8.21" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 264 | 265 | [[package]] 266 | name = "cvt" 267 | version = "0.1.2" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "d2ae9bf77fbf2d39ef573205d554d87e86c12f1994e9ea335b0651b9b278bcf1" 270 | dependencies = [ 271 | "cfg-if", 272 | ] 273 | 274 | [[package]] 275 | name = "either" 276 | version = "1.13.0" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 279 | 280 | [[package]] 281 | name = "embuild" 282 | version = "0.33.0" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | checksum = "28a8cbd9507fabce8f2741b9ca45da9e898cc2b0f1c2e53d21cb2436aeac811d" 285 | dependencies = [ 286 | "anyhow", 287 | "bindgen", 288 | "bitflags 1.3.2", 289 | "cmake", 290 | "filetime", 291 | "globwalk", 292 | "home", 293 | "log", 294 | "regex", 295 | "remove_dir_all", 296 | "serde", 297 | "serde_json", 298 | "shlex", 299 | "strum", 300 | "tempfile", 301 | "thiserror", 302 | "which", 303 | ] 304 | 305 | [[package]] 306 | name = "envy" 307 | version = "0.4.2" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" 310 | dependencies = [ 311 | "serde", 312 | ] 313 | 314 | [[package]] 315 | name = "errno" 316 | version = "0.3.10" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" 319 | dependencies = [ 320 | "libc", 321 | "windows-sys 0.59.0", 322 | ] 323 | 324 | [[package]] 325 | name = "esp-idf-sys" 326 | version = "0.36.1" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "fb77a3d02b579a60a811ed9be22b78c5e794bc492d833ee7fc44d3a0155885e1" 329 | dependencies = [ 330 | "anyhow", 331 | "build-time", 332 | "cargo_metadata", 333 | "cmake", 334 | "const_format", 335 | "embuild", 336 | "envy", 337 | "libc", 338 | "regex", 339 | "serde", 340 | "strum", 341 | "which", 342 | ] 343 | 344 | [[package]] 345 | name = "fastrand" 346 | version = "2.3.0" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 349 | 350 | [[package]] 351 | name = "filetime" 352 | version = "0.2.25" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" 355 | dependencies = [ 356 | "cfg-if", 357 | "libc", 358 | "libredox", 359 | "windows-sys 0.59.0", 360 | ] 361 | 362 | [[package]] 363 | name = "fs_at" 364 | version = "0.2.1" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "14af6c9694ea25db25baa2a1788703b9e7c6648dcaeeebeb98f7561b5384c036" 367 | dependencies = [ 368 | "aligned", 369 | "cfg-if", 370 | "cvt", 371 | "libc", 372 | "nix", 373 | "windows-sys 0.52.0", 374 | ] 375 | 376 | [[package]] 377 | name = "getrandom" 378 | version = "0.2.15" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 381 | dependencies = [ 382 | "cfg-if", 383 | "libc", 384 | "wasi", 385 | ] 386 | 387 | [[package]] 388 | name = "glob" 389 | version = "0.3.2" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" 392 | 393 | [[package]] 394 | name = "globset" 395 | version = "0.4.15" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" 398 | dependencies = [ 399 | "aho-corasick", 400 | "bstr", 401 | "log", 402 | "regex-automata", 403 | "regex-syntax", 404 | ] 405 | 406 | [[package]] 407 | name = "globwalk" 408 | version = "0.8.1" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" 411 | dependencies = [ 412 | "bitflags 1.3.2", 413 | "ignore", 414 | "walkdir", 415 | ] 416 | 417 | [[package]] 418 | name = "heck" 419 | version = "0.4.1" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 422 | 423 | [[package]] 424 | name = "home" 425 | version = "0.5.11" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 428 | dependencies = [ 429 | "windows-sys 0.59.0", 430 | ] 431 | 432 | [[package]] 433 | name = "iana-time-zone" 434 | version = "0.1.61" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 437 | dependencies = [ 438 | "android_system_properties", 439 | "core-foundation-sys", 440 | "iana-time-zone-haiku", 441 | "js-sys", 442 | "wasm-bindgen", 443 | "windows-core", 444 | ] 445 | 446 | [[package]] 447 | name = "iana-time-zone-haiku" 448 | version = "0.1.2" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 451 | dependencies = [ 452 | "cc", 453 | ] 454 | 455 | [[package]] 456 | name = "ignore" 457 | version = "0.4.23" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" 460 | dependencies = [ 461 | "crossbeam-deque", 462 | "globset", 463 | "log", 464 | "memchr", 465 | "regex-automata", 466 | "same-file", 467 | "walkdir", 468 | "winapi-util", 469 | ] 470 | 471 | [[package]] 472 | name = "itertools" 473 | version = "0.13.0" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 476 | dependencies = [ 477 | "either", 478 | ] 479 | 480 | [[package]] 481 | name = "itoa" 482 | version = "1.0.14" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 485 | 486 | [[package]] 487 | name = "js-sys" 488 | version = "0.3.77" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 491 | dependencies = [ 492 | "once_cell", 493 | "wasm-bindgen", 494 | ] 495 | 496 | [[package]] 497 | name = "libc" 498 | version = "0.2.169" 499 | source = "registry+https://github.com/rust-lang/crates.io-index" 500 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 501 | 502 | [[package]] 503 | name = "libloading" 504 | version = "0.8.6" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" 507 | dependencies = [ 508 | "cfg-if", 509 | "windows-targets", 510 | ] 511 | 512 | [[package]] 513 | name = "libredox" 514 | version = "0.1.3" 515 | source = "registry+https://github.com/rust-lang/crates.io-index" 516 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 517 | dependencies = [ 518 | "bitflags 2.8.0", 519 | "libc", 520 | "redox_syscall", 521 | ] 522 | 523 | [[package]] 524 | name = "linux-raw-sys" 525 | version = "0.4.15" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" 528 | 529 | [[package]] 530 | name = "log" 531 | version = "0.4.25" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" 534 | 535 | [[package]] 536 | name = "memchr" 537 | version = "2.7.4" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 540 | 541 | [[package]] 542 | name = "minimal-lexical" 543 | version = "0.2.1" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 546 | 547 | [[package]] 548 | name = "nix" 549 | version = "0.29.0" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" 552 | dependencies = [ 553 | "bitflags 2.8.0", 554 | "cfg-if", 555 | "cfg_aliases", 556 | "libc", 557 | ] 558 | 559 | [[package]] 560 | name = "nom" 561 | version = "7.1.3" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 564 | dependencies = [ 565 | "memchr", 566 | "minimal-lexical", 567 | ] 568 | 569 | [[package]] 570 | name = "normpath" 571 | version = "1.3.0" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" 574 | dependencies = [ 575 | "windows-sys 0.59.0", 576 | ] 577 | 578 | [[package]] 579 | name = "num-traits" 580 | version = "0.2.19" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 583 | dependencies = [ 584 | "autocfg", 585 | ] 586 | 587 | [[package]] 588 | name = "once_cell" 589 | version = "1.20.2" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 592 | 593 | [[package]] 594 | name = "prettyplease" 595 | version = "0.2.29" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" 598 | dependencies = [ 599 | "proc-macro2", 600 | "syn 2.0.96", 601 | ] 602 | 603 | [[package]] 604 | name = "proc-macro2" 605 | version = "1.0.93" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 608 | dependencies = [ 609 | "unicode-ident", 610 | ] 611 | 612 | [[package]] 613 | name = "quote" 614 | version = "1.0.38" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 617 | dependencies = [ 618 | "proc-macro2", 619 | ] 620 | 621 | [[package]] 622 | name = "redox_syscall" 623 | version = "0.5.8" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" 626 | dependencies = [ 627 | "bitflags 2.8.0", 628 | ] 629 | 630 | [[package]] 631 | name = "regex" 632 | version = "1.11.1" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 635 | dependencies = [ 636 | "aho-corasick", 637 | "memchr", 638 | "regex-automata", 639 | "regex-syntax", 640 | ] 641 | 642 | [[package]] 643 | name = "regex-automata" 644 | version = "0.4.9" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 647 | dependencies = [ 648 | "aho-corasick", 649 | "memchr", 650 | "regex-syntax", 651 | ] 652 | 653 | [[package]] 654 | name = "regex-syntax" 655 | version = "0.8.5" 656 | source = "registry+https://github.com/rust-lang/crates.io-index" 657 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 658 | 659 | [[package]] 660 | name = "remove_dir_all" 661 | version = "0.8.4" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | checksum = "a694f9e0eb3104451127f6cc1e5de55f59d3b1fc8c5ddfaeb6f1e716479ceb4a" 664 | dependencies = [ 665 | "cfg-if", 666 | "cvt", 667 | "fs_at", 668 | "libc", 669 | "normpath", 670 | "windows-sys 0.59.0", 671 | ] 672 | 673 | [[package]] 674 | name = "rustc-hash" 675 | version = "2.1.0" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" 678 | 679 | [[package]] 680 | name = "rustix" 681 | version = "0.38.43" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" 684 | dependencies = [ 685 | "bitflags 2.8.0", 686 | "errno", 687 | "libc", 688 | "linux-raw-sys", 689 | "windows-sys 0.59.0", 690 | ] 691 | 692 | [[package]] 693 | name = "rustversion" 694 | version = "1.0.19" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 697 | 698 | [[package]] 699 | name = "ryu" 700 | version = "1.0.18" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 703 | 704 | [[package]] 705 | name = "same-file" 706 | version = "1.0.6" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 709 | dependencies = [ 710 | "winapi-util", 711 | ] 712 | 713 | [[package]] 714 | name = "semver" 715 | version = "1.0.24" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" 718 | dependencies = [ 719 | "serde", 720 | ] 721 | 722 | [[package]] 723 | name = "serde" 724 | version = "1.0.217" 725 | source = "registry+https://github.com/rust-lang/crates.io-index" 726 | checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" 727 | dependencies = [ 728 | "serde_derive", 729 | ] 730 | 731 | [[package]] 732 | name = "serde_derive" 733 | version = "1.0.217" 734 | source = "registry+https://github.com/rust-lang/crates.io-index" 735 | checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" 736 | dependencies = [ 737 | "proc-macro2", 738 | "quote", 739 | "syn 2.0.96", 740 | ] 741 | 742 | [[package]] 743 | name = "serde_json" 744 | version = "1.0.136" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "336a0c23cf42a38d9eaa7cd22c7040d04e1228a19a933890805ffd00a16437d2" 747 | dependencies = [ 748 | "itoa", 749 | "memchr", 750 | "ryu", 751 | "serde", 752 | ] 753 | 754 | [[package]] 755 | name = "shlex" 756 | version = "1.3.0" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 759 | 760 | [[package]] 761 | name = "stable_deref_trait" 762 | version = "1.2.0" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 765 | 766 | [[package]] 767 | name = "strum" 768 | version = "0.24.1" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" 771 | dependencies = [ 772 | "strum_macros", 773 | ] 774 | 775 | [[package]] 776 | name = "strum_macros" 777 | version = "0.24.3" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" 780 | dependencies = [ 781 | "heck", 782 | "proc-macro2", 783 | "quote", 784 | "rustversion", 785 | "syn 1.0.109", 786 | ] 787 | 788 | [[package]] 789 | name = "syn" 790 | version = "1.0.109" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 793 | dependencies = [ 794 | "proc-macro2", 795 | "quote", 796 | "unicode-ident", 797 | ] 798 | 799 | [[package]] 800 | name = "syn" 801 | version = "2.0.96" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" 804 | dependencies = [ 805 | "proc-macro2", 806 | "quote", 807 | "unicode-ident", 808 | ] 809 | 810 | [[package]] 811 | name = "tempfile" 812 | version = "3.15.0" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" 815 | dependencies = [ 816 | "cfg-if", 817 | "fastrand", 818 | "getrandom", 819 | "once_cell", 820 | "rustix", 821 | "windows-sys 0.59.0", 822 | ] 823 | 824 | [[package]] 825 | name = "thiserror" 826 | version = "1.0.69" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 829 | dependencies = [ 830 | "thiserror-impl", 831 | ] 832 | 833 | [[package]] 834 | name = "thiserror-impl" 835 | version = "1.0.69" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 838 | dependencies = [ 839 | "proc-macro2", 840 | "quote", 841 | "syn 2.0.96", 842 | ] 843 | 844 | [[package]] 845 | name = "unicode-ident" 846 | version = "1.0.14" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" 849 | 850 | [[package]] 851 | name = "unicode-xid" 852 | version = "0.2.6" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 855 | 856 | [[package]] 857 | name = "walkdir" 858 | version = "2.5.0" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 861 | dependencies = [ 862 | "same-file", 863 | "winapi-util", 864 | ] 865 | 866 | [[package]] 867 | name = "wamr-rust-sdk" 868 | version = "1.0.0" 869 | dependencies = [ 870 | "esp-idf-sys", 871 | "wamr-sys", 872 | ] 873 | 874 | [[package]] 875 | name = "wamr-sys" 876 | version = "1.0.0" 877 | dependencies = [ 878 | "bindgen", 879 | "cc", 880 | "cmake", 881 | ] 882 | 883 | [[package]] 884 | name = "wasi" 885 | version = "0.11.0+wasi-snapshot-preview1" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 888 | 889 | [[package]] 890 | name = "wasm-bindgen" 891 | version = "0.2.100" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 894 | dependencies = [ 895 | "cfg-if", 896 | "once_cell", 897 | "rustversion", 898 | "wasm-bindgen-macro", 899 | ] 900 | 901 | [[package]] 902 | name = "wasm-bindgen-backend" 903 | version = "0.2.100" 904 | source = "registry+https://github.com/rust-lang/crates.io-index" 905 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 906 | dependencies = [ 907 | "bumpalo", 908 | "log", 909 | "proc-macro2", 910 | "quote", 911 | "syn 2.0.96", 912 | "wasm-bindgen-shared", 913 | ] 914 | 915 | [[package]] 916 | name = "wasm-bindgen-macro" 917 | version = "0.2.100" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 920 | dependencies = [ 921 | "quote", 922 | "wasm-bindgen-macro-support", 923 | ] 924 | 925 | [[package]] 926 | name = "wasm-bindgen-macro-support" 927 | version = "0.2.100" 928 | source = "registry+https://github.com/rust-lang/crates.io-index" 929 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 930 | dependencies = [ 931 | "proc-macro2", 932 | "quote", 933 | "syn 2.0.96", 934 | "wasm-bindgen-backend", 935 | "wasm-bindgen-shared", 936 | ] 937 | 938 | [[package]] 939 | name = "wasm-bindgen-shared" 940 | version = "0.2.100" 941 | source = "registry+https://github.com/rust-lang/crates.io-index" 942 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 943 | dependencies = [ 944 | "unicode-ident", 945 | ] 946 | 947 | [[package]] 948 | name = "which" 949 | version = "4.4.2" 950 | source = "registry+https://github.com/rust-lang/crates.io-index" 951 | checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" 952 | dependencies = [ 953 | "either", 954 | "home", 955 | "once_cell", 956 | "rustix", 957 | ] 958 | 959 | [[package]] 960 | name = "winapi-util" 961 | version = "0.1.9" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 964 | dependencies = [ 965 | "windows-sys 0.59.0", 966 | ] 967 | 968 | [[package]] 969 | name = "windows-core" 970 | version = "0.52.0" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 973 | dependencies = [ 974 | "windows-targets", 975 | ] 976 | 977 | [[package]] 978 | name = "windows-sys" 979 | version = "0.52.0" 980 | source = "registry+https://github.com/rust-lang/crates.io-index" 981 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 982 | dependencies = [ 983 | "windows-targets", 984 | ] 985 | 986 | [[package]] 987 | name = "windows-sys" 988 | version = "0.59.0" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 991 | dependencies = [ 992 | "windows-targets", 993 | ] 994 | 995 | [[package]] 996 | name = "windows-targets" 997 | version = "0.52.6" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1000 | dependencies = [ 1001 | "windows_aarch64_gnullvm", 1002 | "windows_aarch64_msvc", 1003 | "windows_i686_gnu", 1004 | "windows_i686_gnullvm", 1005 | "windows_i686_msvc", 1006 | "windows_x86_64_gnu", 1007 | "windows_x86_64_gnullvm", 1008 | "windows_x86_64_msvc", 1009 | ] 1010 | 1011 | [[package]] 1012 | name = "windows_aarch64_gnullvm" 1013 | version = "0.52.6" 1014 | source = "registry+https://github.com/rust-lang/crates.io-index" 1015 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1016 | 1017 | [[package]] 1018 | name = "windows_aarch64_msvc" 1019 | version = "0.52.6" 1020 | source = "registry+https://github.com/rust-lang/crates.io-index" 1021 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1022 | 1023 | [[package]] 1024 | name = "windows_i686_gnu" 1025 | version = "0.52.6" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1028 | 1029 | [[package]] 1030 | name = "windows_i686_gnullvm" 1031 | version = "0.52.6" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1034 | 1035 | [[package]] 1036 | name = "windows_i686_msvc" 1037 | version = "0.52.6" 1038 | source = "registry+https://github.com/rust-lang/crates.io-index" 1039 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1040 | 1041 | [[package]] 1042 | name = "windows_x86_64_gnu" 1043 | version = "0.52.6" 1044 | source = "registry+https://github.com/rust-lang/crates.io-index" 1045 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1046 | 1047 | [[package]] 1048 | name = "windows_x86_64_gnullvm" 1049 | version = "0.52.6" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1052 | 1053 | [[package]] 1054 | name = "windows_x86_64_msvc" 1055 | version = "0.52.6" 1056 | source = "registry+https://github.com/rust-lang/crates.io-index" 1057 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1058 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Intel Corporation. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | [workspace] 5 | members = ["crates/wamr-sys"] 6 | exclude = [ 7 | "examples/wasi-hello", 8 | "resources/test/gcd", 9 | "resources/test/add-extra", 10 | ".devcontainer", 11 | ".github", 12 | ] 13 | resolver = "2" 14 | 15 | [workspace.package] 16 | edition = "2021" 17 | license = "Apache-2.0 WITH LLVM-exception" 18 | authors = ["The WAMR Project Developers"] 19 | 20 | [package] 21 | name = "wamr-rust-sdk" 22 | description = "The Rust SDK of WAMR" 23 | license.workspace = true 24 | edition.workspace = true 25 | repository = "https://github.com/bytecodealliance/wamr-rust-sdk" 26 | version = "1.0.0" 27 | readme = "README.md" 28 | categories = ["api-bindings", "wasm"] 29 | keywords = ["api-bindings", "wasm", "webassembly"] 30 | 31 | [dependencies] 32 | wamr-sys = { path = "crates/wamr-sys", version = "1.0.0" } 33 | 34 | [target.'cfg( target_os = "espidf" )'.dependencies] 35 | esp-idf-sys = { version = "0.36", optional = true } 36 | 37 | [[package.metadata.esp-idf-sys.extra_components]] 38 | bindings_header = "./crates/wamr-sys/wasm-micro-runtime/core/iwasm/include/wasm_export.h" 39 | component_dirs = ["./crates/wamr-sys/wasm-micro-runtime/build-scripts/esp-idf"] 40 | 41 | [features] 42 | custom-section = ["wamr-sys/custom-section"] 43 | dump-call-stack = ["wamr-sys/dump-call-stack"] 44 | esp-idf = ["esp-idf-sys", "wamr-sys/esp-idf"] 45 | hw-bound-check = ["wamr-sys/hw-bound-check"] 46 | llvmjit = ["wamr-sys/llvmjit"] 47 | multi-module = ["wamr-sys/multi-module"] 48 | name-section = ["wamr-sys/name-section"] 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | 204 | --- LLVM Exceptions to the Apache 2.0 License ---- 205 | 206 | As an exception, if, as a result of your compiling your source code, portions 207 | of this Software are embedded into an Object form of such source code, you 208 | may redistribute such embedded portions in such Object form without complying 209 | with the conditions of Sections 4(a), 4(b) and 4(d) of the License. 210 | 211 | In addition, if you combine or link compiled forms of this Software with 212 | software that is licensed under the GPLv2 ("Combined Software") and if a 213 | court of competent jurisdiction determines that the patent provision (Section 214 | 3), the indemnity provision (Section 9) or other Section of the License 215 | conflicts with the conditions of the GPLv2, you may retroactively and 216 | prospectively choose to deem waived or otherwise exclude such Section(s) of 217 | the License, but only in their entirety and only with respect to the Combined 218 | Software. 219 | 220 | -------------------------------------------------------------------------------- /ORG_CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Bytecode Alliance Organizational Code of Conduct (OCoC) 2 | 3 | *Note*: this Code of Conduct pertains to organizations' behavior. Please also see the [Individual Code of Conduct](CODE_OF_CONDUCT.md). 4 | 5 | ## Preamble 6 | 7 | The Bytecode Alliance (BA) welcomes involvement from organizations, 8 | including commercial organizations. This document is an 9 | *organizational* code of conduct, intended particularly to provide 10 | guidance to commercial organizations. It is distinct from the 11 | [Individual Code of Conduct (ICoC)](CODE_OF_CONDUCT.md), and does not 12 | replace the ICoC. This OCoC applies to any group of people acting in 13 | concert as a BA member or as a participant in BA activities, whether 14 | or not that group is formally incorporated in some jurisdiction. 15 | 16 | The code of conduct described below is not a set of rigid rules, and 17 | we did not write it to encompass every conceivable scenario that might 18 | arise. For example, it is theoretically possible there would be times 19 | when asserting patents is in the best interest of the BA community as 20 | a whole. In such instances, consult with the BA, strive for 21 | consensus, and interpret these rules with an intent that is generous 22 | to the community the BA serves. 23 | 24 | While we may revise these guidelines from time to time based on 25 | real-world experience, overall they are based on a simple principle: 26 | 27 | *Bytecode Alliance members should observe the distinction between 28 | public community functions and private functions — especially 29 | commercial ones — and should ensure that the latter support, or at 30 | least do not harm, the former.* 31 | 32 | ## Guidelines 33 | 34 | * **Do not cause confusion about Wasm standards or interoperability.** 35 | 36 | Having an interoperable WebAssembly core is a high priority for 37 | the BA, and members should strive to preserve that core. It is fine 38 | to develop additional non-standard features or APIs, but they 39 | should always be clearly distinguished from the core interoperable 40 | Wasm. 41 | 42 | Treat the WebAssembly name and any BA-associated names with 43 | respect, and follow BA trademark and branding guidelines. If you 44 | distribute a customized version of software originally produced by 45 | the BA, or if you build a product or service using BA-derived 46 | software, use names that clearly distinguish your work from the 47 | original. (You should still provide proper attribution to the 48 | original, of course, wherever such attribution would normally be 49 | given.) 50 | 51 | Further, do not use the WebAssembly name or BA-associated names in 52 | other public namespaces in ways that could cause confusion, e.g., 53 | in company names, names of commercial service offerings, domain 54 | names, publicly-visible social media accounts or online service 55 | accounts, etc. It may sometimes be reasonable, however, to 56 | register such a name in a new namespace and then immediately donate 57 | control of that account to the BA, because that would help the project 58 | maintain its identity. 59 | 60 | * **Do not restrict contributors.** If your company requires 61 | employees or contractors to sign non-compete agreements, those 62 | agreements must not prevent people from participating in the BA or 63 | contributing to related projects. 64 | 65 | This does not mean that all non-compete agreements are incompatible 66 | with this code of conduct. For example, a company may restrict an 67 | employee's ability to solicit the company's customers. However, an 68 | agreement must not block any form of technical or social 69 | participation in BA activities, including but not limited to the 70 | implementation of particular features. 71 | 72 | The accumulation of experience and expertise in individual persons, 73 | who are ultimately free to direct their energy and attention as 74 | they decide, is one of the most important drivers of progress in 75 | open source projects. A company that limits this freedom may hinder 76 | the success of the BA's efforts. 77 | 78 | * **Do not use patents as offensive weapons.** If any BA participant 79 | prevents the adoption or development of BA technologies by 80 | asserting its patents, that undermines the purpose of the 81 | coalition. The collaboration fostered by the BA cannot include 82 | members who act to undermine its work. 83 | 84 | * **Practice responsible disclosure** for security vulnerabilities. 85 | Use designated, non-public reporting channels to disclose technical 86 | vulnerabilities, and give the project a reasonable period to 87 | respond, remediate, and patch. 88 | 89 | Vulnerability reporters may patch their company's own offerings, as 90 | long as that patching does not significantly delay the reporting of 91 | the vulnerability. Vulnerability information should never be used 92 | for unilateral commercial advantage. Vendors may legitimately 93 | compete on the speed and reliability with which they deploy 94 | security fixes, but withholding vulnerability information damages 95 | everyone in the long run by risking harm to the BA project's 96 | reputation and to the security of all users. 97 | 98 | * **Respect the letter and spirit of open source practice.** While 99 | there is not space to list here all possible aspects of standard 100 | open source practice, some examples will help show what we mean: 101 | 102 | * Abide by all applicable open source license terms. Do not engage 103 | in copyright violation or misattribution of any kind. 104 | 105 | * Do not claim others' ideas or designs as your own. 106 | 107 | * When others engage in publicly visible work (e.g., an upcoming 108 | demo that is coordinated in a public issue tracker), do not 109 | unilaterally announce early releases or early demonstrations of 110 | that work ahead of their schedule in order to secure private 111 | advantage (such as marketplace advantage) for yourself. 112 | 113 | The BA reserves the right to determine what constitutes good open 114 | source practices and to take action as it deems appropriate to 115 | encourage, and if necessary enforce, such practices. 116 | 117 | ## Enforcement 118 | 119 | Instances of organizational behavior in violation of the OCoC may 120 | be reported by contacting the Bytecode Alliance CoC team at 121 | [report@bytecodealliance.org](mailto:report@bytecodealliance.org). The 122 | CoC team will review and investigate all complaints, and will respond 123 | in a way that it deems appropriate to the circumstances. The CoC team 124 | is obligated to maintain confidentiality with regard to the reporter of 125 | an incident. Further details of specific enforcement policies may be 126 | posted separately. 127 | 128 | When the BA deems an organization in violation of this OCoC, the BA 129 | will, at its sole discretion, determine what action to take. The BA 130 | will decide what type, degree, and duration of corrective action is 131 | needed, if any, before a violating organization can be considered for 132 | membership (if it was not already a member) or can have its membership 133 | reinstated (if it was a member and the BA canceled its membership due 134 | to the violation). 135 | 136 | In practice, the BA's first approach will be to start a conversation, 137 | with punitive enforcement used only as a last resort. Violations 138 | often turn out to be unintentional and swiftly correctable with all 139 | parties acting in good faith. 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wamr-rust-sdk 2 | 3 | ## WAMR Rust SDK 4 | 5 | ### Overview 6 | 7 | WAMR Rust SDK provides Rust language bindings for WAMR. It is the wrapper 8 | of [*wasm_export.h*](../../../core/iwasm/include/wasm_export.h) but with Rust style. 9 | It is more convenient to use WAMR in Rust with this crate. 10 | 11 | This crate contains API used to interact with Wasm modules. You can compile 12 | modules, instantiate modules, call their export functions, etc. 13 | Plus, as an embedded of Wasm, you can provide Wasm module functionality by 14 | creating host-defined functions. 15 | 16 | WAMR Rust SDK includes a [*wamr-sys*](../crates/wamr-sys) crate. It will search for 17 | the WAMR runtime source in the path *../..*. And then uses `rust-bindgen` durning 18 | the build process to make a .so. 19 | 20 | This crate has similar concepts to the 21 | [WebAssembly specification](https://webassembly.github.io/spec/core/). 22 | 23 | #### Core concepts 24 | 25 | - *Runtime*. It is the environment that hosts all the wasm modules. Each process has one runtime instance. 26 | - *Module*. It is the compiled .wasm or .aot. It can be loaded into runtime and instantiated into instance. 27 | - *Instance*. It is the running instance of a module. It can be used to call export functions. 28 | - *Function*. It is the exported function. 29 | 30 | #### WASI concepts 31 | 32 | - *WASIArgs*. It is used to configure the WASI environment. 33 | - *pre-open*. All files and directories in the list will be opened before the .wasm or .aot loaded. 34 | - *allowed address*. All ip addresses in the *allowed address* list will be allowed to connect with a socket. 35 | - *allowed DNS*. 36 | 37 | #### WAMR private concepts 38 | 39 | - *loading linking* instead of *instantiation linking*. *instantiation linking* is 40 | used in Wasm JS API and Wasm C API. It means that every instance has its own, maybe 41 | variant, imports. But *loading linking* means that all instances share the same *imports*. 42 | 43 | - *RuntimeArg*. Control runtime behavior. 44 | - *running mode*. 45 | - *allocator*. 46 | 47 | - *NativeFunction*. 48 | 49 | - *WasmValues*. 50 | 51 | ### Examples 52 | 53 | #### Example: to run a wasm32-wasip1 .wasm 54 | 55 | *wasm32-wasip1* is a most common target for Wasm. It means that the .wasm is compiled with 56 | `cargo build --target wasm32-wasip1` or `wasi-sdk/bin/clang --target wasm32-wasip1`. 57 | 58 | Say there is a gcd_wasm32_wasi.wasm which includes a function named *gcd*. It returns the GCD 59 | of two parameters. 60 | 61 | The rust code to call the function would be: 62 | 63 | ```rust 64 | use wamr_rust_sdk::{ 65 | runtime::Runtime, module::Module, instance::Instance, function::Function, 66 | value::WasmValue, RuntimeError 67 | }; 68 | use std::path::PathBuf; 69 | 70 | fn main() -> Result<(), RuntimeError> { 71 | let runtime = Runtime::new()?; 72 | 73 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 74 | d.push("resources/test"); 75 | d.push("gcd_wasm32_wasi.wasm"); 76 | 77 | let module = Module::from_file(&runtime, d.as_path())?; 78 | 79 | let instance = Instance::new(&runtime, &module, 1024 * 64)?; 80 | 81 | let function = Function::find_export_func(&instance, "gcd")?; 82 | 83 | let params: Vec = vec![WasmValue::I32(9), WasmValue::I32(27)]; 84 | let result = function.call(&instance, ¶ms)?; 85 | assert_eq!(result, WasmValue::I32(9)); 86 | 87 | Ok(()) 88 | } 89 | ``` 90 | 91 | #### Example: more configuration for runtime 92 | 93 | With more configuration, runtime is capable to run .wasm with variant features, like 94 | 95 | - Wasm without WASI requirement. Usually, it means that the .wasm is compiled with `-nostdlib` 96 | or `--target wasm32-unknown-unknown` 97 | - Configure runtime. 98 | - Provides host-defined functions to meet import requirements. 99 | 100 | Say there is an add_extra_wasm32_wasi.wasm. Its exported function, `add()`, 101 | requires an imported function, `extra()`, during the execution. The `add()` 102 | adds two parameters and the result of `extra()` . It is like `a + b + extra()`. 103 | 104 | The rust code to call the *add* function is like this: 105 | 106 | ```rust 107 | use wamr_rust_sdk::{ 108 | runtime::Runtime, module::Module, instance::Instance, function::Function, 109 | value::WasmValue, RuntimeError 110 | }; 111 | use std::path::PathBuf; 112 | use std::ffi::c_void; 113 | 114 | extern "C" fn extra() -> i32 { 115 | 100 116 | } 117 | 118 | fn main() -> Result<(), RuntimeError> { 119 | let runtime = Runtime::builder() 120 | .use_system_allocator() 121 | .register_host_function("extra", extra as *mut c_void) 122 | .build()?; 123 | 124 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 125 | d.push("resources/test"); 126 | d.push("add_extra_wasm32_wasi.wasm"); 127 | let module = Module::from_file(&runtime, d.as_path())?; 128 | 129 | let instance = Instance::new(&runtime, &module, 1024 * 64)?; 130 | 131 | let function = Function::find_export_func(&instance, "add")?; 132 | 133 | let params: Vec = vec![WasmValue::I32(9), WasmValue::I32(27)]; 134 | let result = function.call(&instance, ¶ms)?; 135 | assert_eq!(result, WasmValue::I32(136)); 136 | 137 | Ok(()) 138 | } 139 | ``` 140 | 141 | ### Build Instructions 142 | 143 | #### Building `wamr-sys` and `wamr-rust-sdk` 144 | 145 | To build the `wamr-sys` and `wamr-rust-sdk` crates, follow these steps: 146 | 147 | 1. Ensure you have the Rust toolchain installed. 148 | 2. Clone the repository: 149 | 150 | ```sh 151 | git clone https://github.com/bytecodealliance/wamr-rust-sdk.git 152 | cd wamr-rust-sdk 153 | ``` 154 | 155 | 3. Build the `wamr-sys` crate: 156 | 157 | ```sh 158 | cargo build -p wamr-sys 159 | ``` 160 | 161 | 4. Build the `wamr-rust-sdk` crate: 162 | 163 | ```sh 164 | cargo build 165 | ``` 166 | 167 | #### Preparing a Development and Building Environment 168 | 169 | ##### For non-espidf targets 170 | 171 | 1. Prepare the Rust toolchain 172 | 173 | 2. If targeting a non-linux platform, set `WAMR_BUILD_TARGET` and `WAMR_BUILD_PLATFORM` in the `.cargo/config.toml`: 174 | 175 | ```toml 176 | [env] 177 | WAMR_BUILD_PLATFORM = "OS name" 178 | WAMR_BUILD_TARGET = "CPU architecture" 179 | ``` 180 | 181 | 3. If targeting a platform not supplied by WAMR, refer to the [WAMR porting guide](https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/port_wamr.md#wamr-porting-guide) and set `WAMR_BUILD_TARGET`, `WAMR_BUILD_PLATFORM` and `WAMR_SHARED_PLATFORM_CONFIG` in the `.cargo/config.toml` properly. 182 | 183 | ##### For espidf targets 184 | 185 | 1. Get the latest information from [The Rust on ESP Book](https://docs.esp-rs.org/book/writing-your-own-application/index.html). 186 | 2. Please make sure you have installed all [prerequisites](https://github.com/esp-rs/esp-idf-template?tab=readme-ov-file#prerequisites) first! 187 | 3. Generate projects from templates following the instructions in [The Rust on ESP Book](https://docs.esp-rs.org/book/writing-your-own-application/generate-project/index.html). 188 | 189 | ``` sh 190 | $ cargo generate esp-rs/esp-idf-template cargo 191 | # follow prompts from the command 192 | ``` 193 | 194 | 4. Add the following configuration to your project's `Cargo.toml`: 195 | 196 | ```toml 197 | wamr-rust-sdk = { git = "https://github.com/bytecodealliance/wamr-rust-sdk", features = ["esp-idf"] } 198 | 199 | 200 | #### BKMs 201 | 202 | - [Rust on ESP-IDF "Hello, World" template](https://github.com/esp-rs/esp-idf-template?tab=readme-ov-file#rust-on-esp-idf-hello-world-template) is a good example 203 | - Ensure that `LIBCLANG_PATH` is correctly set (something like: */home//.rustup/toolchains/esp/xtensa-esp32-elf-clang/esp-/esp-clang/lib*, if on a Mac). If not, there might be something wrong with your espup installation. 204 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Please refer to the [Bytecode Alliance security policy](https://bytecodealliance.org/security) for details on how to report security issues in WebAssembly Micro Runtime, our disclosure policy, and how to receive notifications about security issues. 4 | -------------------------------------------------------------------------------- /crates/wamr-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2023 Liquid Reply GmbH. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | [package] 5 | name = "wamr-sys" 6 | description = "Unsafe bindings for wasm-micro-runtime" 7 | license.workspace = true 8 | edition.workspace = true 9 | repository = "https://github.com/bytecodealliance/wamr-rust-sdk" 10 | version = "1.0.0" 11 | readme = "README.md" 12 | categories = ["api-bindings", "wasm"] 13 | keywords = ["api-bindings", "wasm", "webassembly"] 14 | include = [ 15 | "/build.rs", 16 | "/src/lib.rs", 17 | "/wasm-micro-runtime/build-scripts", 18 | "/wasm-micro-runtime/CMakeLists.txt", 19 | "/wasm-micro-runtime/core/iwasm", 20 | "/wasm-micro-runtime/core/shared", 21 | "/wasm-micro-runtime/core/config.h", 22 | "/wasm-micro-runtime/core/version.h", 23 | "/README.md", 24 | ] 25 | 26 | [dependencies] 27 | 28 | [build-dependencies] 29 | bindgen = "0.71" 30 | cc = "1.2" 31 | cmake = "0.1" 32 | 33 | [features] 34 | custom-section = [] 35 | dump-call-stack = [] 36 | esp-idf = [] 37 | hw-bound-check = [] 38 | llvmjit = [] 39 | multi-module = [] 40 | name-section = [ "custom-section" ] 41 | std = [] 42 | -------------------------------------------------------------------------------- /crates/wamr-sys/README.md: -------------------------------------------------------------------------------- 1 | [WebAssembly Micro Runtime (WAMR)](https://github.com/bytecodealliance/wasm-micro-runtime) is a lightweight standalone WebAssembly (Wasm) runtime with small footprint, high performance and highly configurable features for applications cross from embedded, IoT, edge to Trusted Execution Environment (TEE), smart contract, cloud native and so on. 2 | 3 | Usually you shouldn't use this crate directly, instead use [wamr-rust-sdk](https://github.com/bytecodealliance/wamr-rust-sdk) crate which provides safe interface. 4 | -------------------------------------------------------------------------------- /crates/wamr-sys/build.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Liquid Reply GmbH. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | extern crate bindgen; 7 | extern crate cmake; 8 | 9 | use cmake::Config; 10 | use std::{env, path::Path, path::PathBuf}; 11 | 12 | const LLVM_LIBRARIES: &[&str] = &[ 13 | // keep alphabet order 14 | "LLVMOrcJIT", 15 | "LLVMOrcShared", 16 | "LLVMOrcTargetProcess", 17 | "LLVMPasses", 18 | "LLVMProfileData", 19 | "LLVMRuntimeDyld", 20 | "LLVMScalarOpts", 21 | "LLVMSelectionDAG", 22 | "LLVMSymbolize", 23 | "LLVMTarget", 24 | "LLVMTextAPI", 25 | "LLVMTransformUtils", 26 | "LLVMVectorize", 27 | "LLVMX86AsmParser", 28 | "LLVMX86CodeGen", 29 | "LLVMX86Desc", 30 | "LLVMX86Disassembler", 31 | "LLVMX86Info", 32 | "LLVMXRay", 33 | "LLVMipo", 34 | ]; 35 | 36 | fn check_is_espidf() -> bool { 37 | let is_espidf = env::var("CARGO_FEATURE_ESP_IDF").is_ok() 38 | && env::var("CARGO_CFG_TARGET_OS").unwrap() == "espidf"; 39 | 40 | if is_espidf 41 | && (env::var("WAMR_BUILD_PLATFORM").is_ok() 42 | || env::var("WAMR_SHARED_PLATFORM_CONFIG").is_ok()) 43 | { 44 | panic!("ESP-IDF build cannot use custom platform build (WAMR_BUILD_PLATFORM) or shared platform config (WAMR_SHARED_PLATFORM_CONFIG)"); 45 | } 46 | 47 | is_espidf 48 | } 49 | 50 | fn get_feature_flags() -> (String, String, String, String, String, String) { 51 | let enable_custom_section = if cfg!(feature = "custom-section") { 52 | "1" 53 | } else { 54 | "0" 55 | }; 56 | let enable_dump_call_stack = if cfg!(feature = "dump-call-stack") { 57 | "1" 58 | } else { 59 | "0" 60 | }; 61 | let enable_llvm_jit = if cfg!(feature = "llvmjit") { "1" } else { "0" }; 62 | let enable_multi_module = if cfg!(feature = "multi-module") { 63 | "1" 64 | } else { 65 | "0" 66 | }; 67 | let enable_name_section = if cfg!(feature = "name-section") { 68 | "1" 69 | } else { 70 | "0" 71 | }; 72 | let disable_hw_bound_check = if cfg!(feature = "hw-bound-check") { 73 | "0" 74 | } else { 75 | "1" 76 | }; 77 | 78 | ( 79 | enable_custom_section.to_string(), 80 | enable_dump_call_stack.to_string(), 81 | enable_llvm_jit.to_string(), 82 | enable_multi_module.to_string(), 83 | enable_name_section.to_string(), 84 | disable_hw_bound_check.to_string(), 85 | ) 86 | } 87 | 88 | fn link_llvm_libraries(llvm_cfg_path: &String, enable_llvm_jit: &String) { 89 | if enable_llvm_jit == "0" { 90 | return; 91 | } 92 | 93 | let llvm_cfg_path = PathBuf::from(llvm_cfg_path); 94 | assert!(llvm_cfg_path.exists()); 95 | 96 | let llvm_lib_path = llvm_cfg_path.join("../../../lib").canonicalize().unwrap(); 97 | assert!(llvm_lib_path.exists()); 98 | 99 | println!("cargo:rustc-link-lib=dylib=dl"); 100 | println!("cargo:rustc-link-lib=dylib=m"); 101 | println!("cargo:rustc-link-lib=dylib=rt"); 102 | println!("cargo:rustc-link-lib=dylib=stdc++"); 103 | println!("cargo:rustc-link-lib=dylib=z"); 104 | println!("cargo:libdir={}", llvm_lib_path.display()); 105 | println!("cargo:rustc-link-search=native={}", llvm_lib_path.display()); 106 | 107 | for &llvm_lib in LLVM_LIBRARIES { 108 | println!("cargo:rustc-link-lib=static={}", llvm_lib); 109 | } 110 | } 111 | 112 | fn setup_config( 113 | wamr_root: &PathBuf, 114 | feature_flags: (String, String, String, String, String, String), 115 | ) -> Config { 116 | let ( 117 | enable_custom_section, 118 | enable_dump_call_stack, 119 | enable_llvm_jit, 120 | enable_multi_module, 121 | enable_name_section, 122 | disalbe_hw_bound_check, 123 | ) = feature_flags; 124 | 125 | let mut cfg = Config::new(wamr_root); 126 | cfg.define("WAMR_BUILD_AOT", "1") 127 | .define("WAMR_BUILD_INTERP", "1") 128 | .define("WAMR_BUILD_FAST_INTERP", "1") 129 | .define("WAMR_BUILD_JIT", &enable_llvm_jit) 130 | .define("WAMR_BUILD_BULK_MEMORY", "1") 131 | .define("WAMR_BUILD_REF_TYPES", "1") 132 | .define("WAMR_BUILD_SIMD", "1") 133 | .define("WAMR_BUILD_LIBC_WASI", "1") 134 | .define("WAMR_BUILD_LIBC_BUILTIN", "0") 135 | .define("WAMR_DISABLE_HW_BOUND_CHECK", &disalbe_hw_bound_check) 136 | .define("WAMR_BUILD_MULTI_MODULE", &enable_multi_module) 137 | .define("WAMR_BUILD_DUMP_CALL_STACK", &enable_dump_call_stack) 138 | .define("WAMR_BUILD_CUSTOM_NAME_SECTION", &enable_name_section) 139 | .define("WAMR_BUILD_LOAD_CUSTOM_SECTION", &enable_custom_section); 140 | 141 | // always assume non-empty strings for these environment variables 142 | 143 | if let Ok(platform_name) = env::var("WAMR_BUILD_PLATFORM") { 144 | cfg.define("WAMR_BUILD_PLATFORM", &platform_name); 145 | } 146 | 147 | if let Ok(target_name) = env::var("WAMR_BUILD_TARGET") { 148 | cfg.define("WAMR_BUILD_TARGET", &target_name); 149 | } 150 | 151 | if let Ok(platform_config) = env::var("WAMR_SHARED_PLATFORM_CONFIG") { 152 | cfg.define("SHARED_PLATFORM_CONFIG", &platform_config); 153 | } 154 | 155 | if let Ok(llvm_cfg_path) = env::var("LLVM_LIB_CFG_PATH") { 156 | link_llvm_libraries(&llvm_cfg_path, &enable_llvm_jit); 157 | cfg.define("LLVM_DIR", &llvm_cfg_path); 158 | } 159 | 160 | // STDIN/STDOUT/STDERR redirect 161 | if let Ok(bh_vprintf) = env::var("WAMR_BH_VPRINTF") { 162 | cfg.define("WAMR_BH_VPRINTF", &bh_vprintf); 163 | } 164 | 165 | cfg 166 | } 167 | 168 | fn build_wamr_libraries(wamr_root: &PathBuf) { 169 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 170 | let vmbuild_path = out_dir.join("vmbuild"); 171 | 172 | let feature_flags = get_feature_flags(); 173 | let mut cfg = setup_config(wamr_root, feature_flags); 174 | let dst = cfg.out_dir(vmbuild_path).build_target("iwasm_static").build(); 175 | 176 | println!("cargo:rustc-link-search=native={}/build", dst.display()); 177 | println!("cargo:rustc-link-lib=static=vmlib"); 178 | } 179 | 180 | fn build_wamrc(wamr_root: &Path) { 181 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 182 | let wamrc_build_path = out_dir.join("wamrcbuild"); 183 | 184 | let wamr_compiler_path = wamr_root.join("wamr-compiler"); 185 | assert!(wamr_compiler_path.exists()); 186 | 187 | Config::new(&wamr_compiler_path) 188 | .out_dir(wamrc_build_path) 189 | .define("WAMR_BUILD_WITH_CUSTOM_LLVM", "1") 190 | .define("LLVM_DIR", env::var("LLVM_LIB_CFG_PATH").expect("LLVM_LIB_CFG_PATH isn't specified in config.toml")) 191 | .build(); 192 | } 193 | 194 | fn generate_bindings(wamr_root: &Path) { 195 | let wamr_header = wamr_root.join("core/iwasm/include/wasm_export.h"); 196 | assert!(wamr_header.exists()); 197 | 198 | let bindings = bindgen::Builder::default() 199 | .ctypes_prefix("::core::ffi") 200 | .use_core() 201 | .header(wamr_header.into_os_string().into_string().unwrap()) 202 | .derive_default(true) 203 | .generate() 204 | .expect("Unable to generate bindings"); 205 | let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); 206 | bindings 207 | .write_to_file(out_path.join("bindings.rs")) 208 | .expect("Couldn't write bindings"); 209 | } 210 | 211 | fn main() { 212 | println!("cargo:rerun-if-env-changed=CARGO_FEATURE_ESP_IDF"); 213 | println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS"); 214 | println!("cargo:rerun-if-env-changed=WAMR_BUILD_PLATFORM"); 215 | println!("cargo:rerun-if-env-changed=WAMR_SHARED_PLATFORM_CONFIG"); 216 | println!("cargo:rerun-if-env-changed=LLVM_LIB_CFG_PATH"); 217 | println!("cargo:rerun-if-env-changed=WAMR_BH_VPRINTF"); 218 | 219 | let wamr_root = env::current_dir().unwrap(); 220 | let wamr_root = wamr_root.join("wasm-micro-runtime"); 221 | assert!(wamr_root.exists()); 222 | 223 | if !check_is_espidf() { 224 | // because the ESP-IDF build procedure differs from the regular one 225 | // (build internally by esp-idf-sys), 226 | build_wamr_libraries(&wamr_root); 227 | build_wamrc(&wamr_root); 228 | } 229 | 230 | generate_bindings(&wamr_root); 231 | } 232 | -------------------------------------------------------------------------------- /crates/wamr-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Liquid Reply GmbH. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | // Suppress the flurry of warnings caused by using "C" naming conventions 7 | #![allow(non_upper_case_globals)] 8 | #![allow(non_camel_case_types)] 9 | #![allow(non_snake_case)] 10 | #![cfg_attr(not(feature = "std"), no_std)] 11 | 12 | // This matches bindgen::Builder output 13 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 14 | -------------------------------------------------------------------------------- /examples/wasi-hello/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "bindgen" 16 | version = "0.70.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" 19 | dependencies = [ 20 | "bitflags", 21 | "cexpr", 22 | "clang-sys", 23 | "itertools", 24 | "log", 25 | "prettyplease", 26 | "proc-macro2", 27 | "quote", 28 | "regex", 29 | "rustc-hash", 30 | "shlex", 31 | "syn", 32 | ] 33 | 34 | [[package]] 35 | name = "bitflags" 36 | version = "2.4.2" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" 39 | 40 | [[package]] 41 | name = "cc" 42 | version = "1.1.19" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" 45 | dependencies = [ 46 | "shlex", 47 | ] 48 | 49 | [[package]] 50 | name = "cexpr" 51 | version = "0.6.0" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 54 | dependencies = [ 55 | "nom", 56 | ] 57 | 58 | [[package]] 59 | name = "cfg-if" 60 | version = "1.0.0" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 63 | 64 | [[package]] 65 | name = "clang-sys" 66 | version = "1.7.0" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" 69 | dependencies = [ 70 | "glob", 71 | "libc", 72 | "libloading", 73 | ] 74 | 75 | [[package]] 76 | name = "cmake" 77 | version = "0.1.50" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" 80 | dependencies = [ 81 | "cc", 82 | ] 83 | 84 | [[package]] 85 | name = "either" 86 | version = "1.10.0" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" 89 | 90 | [[package]] 91 | name = "glob" 92 | version = "0.3.1" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 95 | 96 | [[package]] 97 | name = "itertools" 98 | version = "0.12.1" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 101 | dependencies = [ 102 | "either", 103 | ] 104 | 105 | [[package]] 106 | name = "libc" 107 | version = "0.2.153" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 110 | 111 | [[package]] 112 | name = "libloading" 113 | version = "0.8.1" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" 116 | dependencies = [ 117 | "cfg-if", 118 | "windows-sys", 119 | ] 120 | 121 | [[package]] 122 | name = "log" 123 | version = "0.4.21" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 126 | 127 | [[package]] 128 | name = "memchr" 129 | version = "2.7.1" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" 132 | 133 | [[package]] 134 | name = "minimal-lexical" 135 | version = "0.2.1" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 138 | 139 | [[package]] 140 | name = "nom" 141 | version = "7.1.3" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 144 | dependencies = [ 145 | "memchr", 146 | "minimal-lexical", 147 | ] 148 | 149 | [[package]] 150 | name = "prettyplease" 151 | version = "0.2.16" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" 154 | dependencies = [ 155 | "proc-macro2", 156 | "syn", 157 | ] 158 | 159 | [[package]] 160 | name = "proc-macro2" 161 | version = "1.0.78" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" 164 | dependencies = [ 165 | "unicode-ident", 166 | ] 167 | 168 | [[package]] 169 | name = "quote" 170 | version = "1.0.35" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 173 | dependencies = [ 174 | "proc-macro2", 175 | ] 176 | 177 | [[package]] 178 | name = "regex" 179 | version = "1.10.3" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" 182 | dependencies = [ 183 | "aho-corasick", 184 | "memchr", 185 | "regex-automata", 186 | "regex-syntax", 187 | ] 188 | 189 | [[package]] 190 | name = "regex-automata" 191 | version = "0.4.5" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" 194 | dependencies = [ 195 | "aho-corasick", 196 | "memchr", 197 | "regex-syntax", 198 | ] 199 | 200 | [[package]] 201 | name = "regex-syntax" 202 | version = "0.8.2" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 205 | 206 | [[package]] 207 | name = "rustc-hash" 208 | version = "1.1.0" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 211 | 212 | [[package]] 213 | name = "shlex" 214 | version = "1.3.0" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 217 | 218 | [[package]] 219 | name = "syn" 220 | version = "2.0.52" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" 223 | dependencies = [ 224 | "proc-macro2", 225 | "quote", 226 | "unicode-ident", 227 | ] 228 | 229 | [[package]] 230 | name = "unicode-ident" 231 | version = "1.0.12" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 234 | 235 | [[package]] 236 | name = "wamr-rust-sdk" 237 | version = "1.0.0" 238 | source = "git+https://github.com/bytecodealliance/wamr-rust-sdk?tag=v1.1.0#b03ec6030b3f0ee9a190e59804ed87b2445635f6" 239 | dependencies = [ 240 | "wamr-sys", 241 | ] 242 | 243 | [[package]] 244 | name = "wamr-sys" 245 | version = "1.0.0" 246 | source = "git+https://github.com/bytecodealliance/wamr-rust-sdk?tag=v1.1.0#b03ec6030b3f0ee9a190e59804ed87b2445635f6" 247 | dependencies = [ 248 | "bindgen", 249 | "cc", 250 | "cmake", 251 | ] 252 | 253 | [[package]] 254 | name = "wasi-hello" 255 | version = "0.1.0" 256 | dependencies = [ 257 | "wamr-rust-sdk", 258 | ] 259 | 260 | [[package]] 261 | name = "windows-sys" 262 | version = "0.48.0" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 265 | dependencies = [ 266 | "windows-targets", 267 | ] 268 | 269 | [[package]] 270 | name = "windows-targets" 271 | version = "0.48.5" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 274 | dependencies = [ 275 | "windows_aarch64_gnullvm", 276 | "windows_aarch64_msvc", 277 | "windows_i686_gnu", 278 | "windows_i686_msvc", 279 | "windows_x86_64_gnu", 280 | "windows_x86_64_gnullvm", 281 | "windows_x86_64_msvc", 282 | ] 283 | 284 | [[package]] 285 | name = "windows_aarch64_gnullvm" 286 | version = "0.48.5" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 289 | 290 | [[package]] 291 | name = "windows_aarch64_msvc" 292 | version = "0.48.5" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 295 | 296 | [[package]] 297 | name = "windows_i686_gnu" 298 | version = "0.48.5" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 301 | 302 | [[package]] 303 | name = "windows_i686_msvc" 304 | version = "0.48.5" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 307 | 308 | [[package]] 309 | name = "windows_x86_64_gnu" 310 | version = "0.48.5" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 313 | 314 | [[package]] 315 | name = "windows_x86_64_gnullvm" 316 | version = "0.48.5" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 319 | 320 | [[package]] 321 | name = "windows_x86_64_msvc" 322 | version = "0.48.5" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 325 | -------------------------------------------------------------------------------- /examples/wasi-hello/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2023 Liquid Reply GmbH. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | [package] 5 | name = "wasi-hello" 6 | version = "0.1.0" 7 | edition = "2021" 8 | license = "Apache-2.0 WITH LLVM-exception" 9 | authors = ["The WAMR Project Developers"] 10 | 11 | [dependencies] 12 | wamr-rust-sdk = { git = "https://github.com/bytecodealliance/wamr-rust-sdk", tag = "v1.1.0" } 13 | -------------------------------------------------------------------------------- /examples/wasi-hello/gcd_wasm32_wasi.wasm: -------------------------------------------------------------------------------- 1 | ../../resources/test/gcd_wasm32_wasi.wasm -------------------------------------------------------------------------------- /examples/wasi-hello/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Liquid Reply GmbH. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | use std::path::PathBuf; 7 | use wamr_rust_sdk::{ 8 | function::Function, instance::Instance, module::Module, runtime::Runtime, value::WasmValue, 9 | wasi_context::WasiCtxBuilder, RuntimeError, 10 | }; 11 | 12 | fn main() -> Result<(), RuntimeError> { 13 | let runtime = Runtime::new()?; 14 | 15 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 16 | d.push("gcd_wasm32_wasi.wasm"); 17 | let mut module = Module::from_file(&runtime, d.as_path())?; 18 | 19 | let wasi_ctx = WasiCtxBuilder::new() 20 | .set_pre_open_path(vec!["."], vec![]) 21 | .build(); 22 | 23 | module.set_wasi_context(wasi_ctx); 24 | 25 | let instance = Instance::new(&runtime, &module, 1024 * 64)?; 26 | 27 | let function = Function::find_export_func(&instance, "gcd")?; 28 | 29 | let params: Vec = vec![WasmValue::I32(9), WasmValue::I32(27)]; 30 | let result = function.call(&instance, ¶ms)?; 31 | assert_eq!(result, WasmValue::I32(9)); 32 | 33 | Ok(()) 34 | } 35 | -------------------------------------------------------------------------------- /resources/test/add-extra/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "add_extra" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /resources/test/add-extra/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Intel Corporation. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | [package] 5 | name = "add_extra" 6 | version = "0.1.0" 7 | edition = "2021" 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | -------------------------------------------------------------------------------- /resources/test/add-extra/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | #[link(wasm_import_module = "host")] 7 | extern "C" { 8 | fn extra() -> u32; 9 | } 10 | 11 | #[export_name = "add"] 12 | pub fn add_ex(m: u32, n: u32) -> u32 { 13 | m + n + unsafe { extra() } 14 | } 15 | 16 | fn main() { 17 | println!("Hello, world! Please call add(10, 20) to see the result."); 18 | } 19 | -------------------------------------------------------------------------------- /resources/test/add_extra_wasm32_wasi.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytecodealliance/wamr-rust-sdk/fef4905391e3a11f2a694e7292aedc616e8ade19/resources/test/add_extra_wasm32_wasi.wasm -------------------------------------------------------------------------------- /resources/test/gcd/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "gcd" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /resources/test/gcd/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Intel Corporation. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | [package] 5 | name = "gcd" 6 | version = "0.1.0" 7 | edition = "2021" 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | -------------------------------------------------------------------------------- /resources/test/gcd/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | #[export_name = "gcd"] 7 | pub fn gcd(m: u32, n: u32) -> u32 { 8 | let mut a = m; 9 | let mut b = n; 10 | 11 | while b != 0 { 12 | (a, b) = (b, a % b) 13 | } 14 | 15 | println!("gcd({}, {}) = {}", m, n, a); 16 | a 17 | } 18 | 19 | fn main() { 20 | println!("Hello, world! Please call gcd(10, 5) to see the result."); 21 | } 22 | -------------------------------------------------------------------------------- /resources/test/gcd_wasm32_wasi.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytecodealliance/wamr-rust-sdk/fef4905391e3a11f2a694e7292aedc616e8ade19/resources/test/gcd_wasm32_wasi.wasm -------------------------------------------------------------------------------- /resources/test/multiret.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytecodealliance/wamr-rust-sdk/fef4905391e3a11f2a694e7292aedc616e8ade19/resources/test/multiret.wasm -------------------------------------------------------------------------------- /resources/test/multiret/multiret.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "multi") (result f64 f32 i32 i64 f64 f32 i32 i64 v128 v128 v128 v128) 3 | f64.const 22.2222 4 | f32.const 1.57 5 | i32.const 42 6 | i64.const 3523 7 | f64.const 22.2222 8 | f32.const 1.57 9 | i32.const 42 10 | i64.const 3523 11 | v128.const i32x4 1 2 3 4 12 | v128.const f32x4 1 2 3 4 13 | v128.const i64x2 1 2 14 | v128.const f64x2 1 2 15 | ) 16 | ) -------------------------------------------------------------------------------- /resources/test/wasi-demo-app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytecodealliance/wamr-rust-sdk/fef4905391e3a11f2a694e7292aedc616e8ade19/resources/test/wasi-demo-app.wasm -------------------------------------------------------------------------------- /src/function.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | //! an exported wasm function. 7 | //! get one via `Function::find_export_func()` 8 | 9 | use std::{ffi::CString, marker::PhantomData}; 10 | use wamr_sys::{ 11 | wasm_exec_env_t, wasm_func_get_param_count, wasm_func_get_result_count, 12 | wasm_func_get_result_types, wasm_function_inst_t, wasm_runtime_call_wasm, 13 | wasm_runtime_get_exception, wasm_runtime_get_exec_env_singleton, 14 | wasm_runtime_get_wasi_exit_code, wasm_runtime_lookup_function, 15 | wasm_valkind_enum_WASM_EXTERNREF, wasm_valkind_enum_WASM_F32, wasm_valkind_enum_WASM_F64, 16 | wasm_valkind_enum_WASM_FUNCREF, wasm_valkind_enum_WASM_I32, wasm_valkind_enum_WASM_I64, 17 | wasm_valkind_enum_WASM_V128, 18 | }; 19 | 20 | use crate::{ 21 | helper::exception_to_string, instance::Instance, value::WasmValue, ExecError, RuntimeError, 22 | }; 23 | 24 | pub struct Function<'instance> { 25 | function: wasm_function_inst_t, 26 | _phantom: PhantomData>, 27 | } 28 | 29 | impl<'instance> Function<'instance> { 30 | /// find a function by name 31 | /// 32 | /// # Error 33 | /// 34 | /// Return `RuntimeError::FunctionNotFound` if failed. 35 | pub fn find_export_func( 36 | instance: &'instance Instance<'instance>, 37 | name: &str, 38 | ) -> Result { 39 | let name = CString::new(name).expect("CString::new failed"); 40 | let function = 41 | unsafe { wasm_runtime_lookup_function(instance.get_inner_instance(), name.as_ptr()) }; 42 | match function.is_null() { 43 | true => Err(RuntimeError::FunctionNotFound), 44 | false => Ok(Function { 45 | function, 46 | _phantom: PhantomData, 47 | }), 48 | } 49 | } 50 | 51 | #[allow(non_upper_case_globals)] 52 | #[allow(non_snake_case)] 53 | fn parse_result( 54 | &self, 55 | instance: &Instance<'instance>, 56 | result: Vec, 57 | ) -> Result, RuntimeError> { 58 | let result_count = 59 | unsafe { wasm_func_get_result_count(self.function, instance.get_inner_instance()) }; 60 | if result_count == 0 { 61 | return Ok(vec![WasmValue::Void]); 62 | } 63 | 64 | let mut result_types = vec![0u8; result_count as usize]; 65 | unsafe { 66 | wasm_func_get_result_types( 67 | self.function, 68 | instance.get_inner_instance(), 69 | result_types.as_mut_ptr(), 70 | ); 71 | } 72 | 73 | let mut results = Vec::with_capacity(result_types.len()); 74 | let mut index: usize = 0; 75 | 76 | for result_type in result_types.iter() { 77 | match *result_type as u32 { 78 | wasm_valkind_enum_WASM_I32 79 | | wasm_valkind_enum_WASM_FUNCREF 80 | | wasm_valkind_enum_WASM_EXTERNREF => { 81 | results.push(WasmValue::decode_to_i32(&result[index..index + 1])); 82 | index += 1; 83 | } 84 | wasm_valkind_enum_WASM_I64 => { 85 | results.push(WasmValue::decode_to_i64(&result[index..index + 2])); 86 | index += 2; 87 | } 88 | wasm_valkind_enum_WASM_F32 => { 89 | results.push(WasmValue::decode_to_f32(&result[index..index + 1])); 90 | index += 1; 91 | } 92 | wasm_valkind_enum_WASM_F64 => { 93 | results.push(WasmValue::decode_to_f64(&result[index..index + 2])); 94 | index += 2; 95 | } 96 | wasm_valkind_enum_WASM_V128 => { 97 | results.push(WasmValue::decode_to_v128(&result[index..index + 4])); 98 | index += 4; 99 | } 100 | _ => return Err(RuntimeError::NotImplemented), 101 | } 102 | } 103 | 104 | Ok(results) 105 | } 106 | 107 | /// execute an export function. 108 | /// all parameters need to be wrapped in `WasmValue` 109 | /// 110 | /// # Error 111 | /// 112 | /// Return `RuntimeError::ExecutionError` if failed. 113 | #[allow(non_upper_case_globals)] 114 | pub fn call( 115 | &self, 116 | instance: &'instance Instance<'instance>, 117 | params: &Vec, 118 | ) -> Result, RuntimeError> { 119 | let param_count = 120 | unsafe { wasm_func_get_param_count(self.function, instance.get_inner_instance()) }; 121 | if param_count > params.len() as u32 { 122 | return Err(RuntimeError::ExecutionError(ExecError { 123 | message: "invalid parameters".to_string(), 124 | exit_code: 0xff, 125 | })); 126 | } 127 | 128 | // Maintain sufficient allocated space in the vector rather than just declaring its capacity. 129 | let result_count = 130 | unsafe { wasm_func_get_result_count(self.function, instance.get_inner_instance()) }; 131 | let capacity = std::cmp::max(param_count, result_count) as usize * 4; 132 | 133 | // Populate the parameters in the sufficiently allocated argv vector 134 | let mut argv = Vec::with_capacity(capacity); 135 | for p in params { 136 | argv.append(&mut p.encode()); 137 | } 138 | argv.resize(capacity, 0); 139 | 140 | let call_result: bool; 141 | unsafe { 142 | let exec_env: wasm_exec_env_t = 143 | wasm_runtime_get_exec_env_singleton(instance.get_inner_instance()); 144 | call_result = 145 | wasm_runtime_call_wasm(exec_env, self.function, param_count, argv.as_mut_ptr()); 146 | }; 147 | 148 | if !call_result { 149 | unsafe { 150 | let exception_c = wasm_runtime_get_exception(instance.get_inner_instance()); 151 | let error_info = ExecError { 152 | message: exception_to_string(exception_c), 153 | exit_code: wasm_runtime_get_wasi_exit_code(instance.get_inner_instance()), 154 | }; 155 | return Err(RuntimeError::ExecutionError(error_info)); 156 | } 157 | } 158 | 159 | // there is no out of bounds problem, because we have precalculated the safe vec size 160 | self.parse_result(instance, argv) 161 | } 162 | } 163 | 164 | #[cfg(test)] 165 | mod tests { 166 | use super::*; 167 | use crate::{module::Module, runtime::Runtime, wasi_context::WasiCtxBuilder}; 168 | use std::{ 169 | process::{Command, Stdio}, path::Path, path::PathBuf, env, fs, 170 | }; 171 | 172 | #[test] 173 | fn test_func_in_wasm32_unknown() { 174 | let runtime = Runtime::new().unwrap(); 175 | 176 | // (module 177 | // (func (export "add") (param i64 i32) (result i32 i64) 178 | // (local.get 1) 179 | // (i32.const 32) 180 | // (i32.add) 181 | // (local.get 0) 182 | // (i64.const 64) 183 | // (i64.add) 184 | // ) 185 | // 186 | // (func (export "multi-result") (result i32 i64 i32) 187 | // (i32.const 1) 188 | // (i64.const 2) 189 | // (i32.const 3) 190 | // ) 191 | // ) 192 | let binary = vec![ 193 | 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x02, 0x60, 0x02, 0x7E, 194 | 0x7F, 0x02, 0x7F, 0x7E, 0x60, 0x00, 0x03, 0x7F, 0x7E, 0x7F, 0x03, 0x03, 0x02, 0x00, 195 | 0x01, 0x07, 0x16, 0x02, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0C, 0x6D, 0x75, 0x6C, 196 | 0x74, 0x69, 0x2D, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x00, 0x01, 0x0A, 0x18, 0x02, 197 | 0x0D, 0x00, 0x20, 0x01, 0x41, 0x20, 0x6A, 0x20, 0x00, 0x42, 0xC0, 0x00, 0x7C, 0x0B, 198 | 0x08, 0x00, 0x41, 0x01, 0x42, 0x02, 0x41, 0x03, 0x0B, 199 | ]; 200 | let binary = binary.into_iter().map(|c| c as u8).collect::>(); 201 | 202 | let module = Module::from_vec(&runtime, binary, ""); 203 | assert!(module.is_ok()); 204 | let module = module.unwrap(); 205 | 206 | let instance = Instance::new(&runtime, &module, 1024); 207 | assert!(instance.is_ok()); 208 | let instance: &Instance = &instance.unwrap(); 209 | 210 | // 211 | // run add() 212 | // 213 | 214 | let function = Function::find_export_func(instance, "add"); 215 | assert!(function.is_ok()); 216 | let function = function.unwrap(); 217 | 218 | let params: Vec = vec![WasmValue::I64(10), WasmValue::I32(20)]; 219 | let call_result = function.call(instance, ¶ms); 220 | assert!(call_result.is_ok()); 221 | assert_eq!( 222 | call_result.unwrap(), 223 | vec![WasmValue::I32(52), WasmValue::I64(74)] 224 | ); 225 | 226 | // 227 | // run multi-result() 228 | // 229 | 230 | let function = Function::find_export_func(instance, "multi-result"); 231 | assert!(function.is_ok()); 232 | let function = function.unwrap(); 233 | 234 | let params: Vec = Vec::new(); 235 | let call_result = function.call(instance, ¶ms); 236 | assert!(call_result.is_ok()); 237 | assert_eq!( 238 | call_result.unwrap(), 239 | vec![WasmValue::I32(1), WasmValue::I64(2), WasmValue::I32(3)] 240 | ); 241 | } 242 | 243 | #[test] 244 | fn test_func_in_wasm32_wasi() { 245 | let runtime = Runtime::new().unwrap(); 246 | 247 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 248 | d.push("resources/test"); 249 | d.push("gcd_wasm32_wasi.wasm"); 250 | let module = Module::from_file(&runtime, d.as_path()); 251 | assert!(module.is_ok()); 252 | let mut module = module.unwrap(); 253 | 254 | let wasi_ctx = WasiCtxBuilder::new() 255 | .set_pre_open_path(vec!["."], vec![]) 256 | .build(); 257 | module.set_wasi_context(wasi_ctx); 258 | 259 | let instance = Instance::new(&runtime, &module, 1024 * 64); 260 | assert!(instance.is_ok()); 261 | let instance: &Instance = &instance.unwrap(); 262 | 263 | let function = Function::find_export_func(instance, "gcd"); 264 | assert!(function.is_ok()); 265 | let function = function.unwrap(); 266 | 267 | let params: Vec = vec![WasmValue::I32(9), WasmValue::I32(27)]; 268 | let result = function.call(instance, ¶ms); 269 | assert_eq!(result.unwrap(), vec![WasmValue::I32(9)]); 270 | 271 | let params: Vec = vec![WasmValue::I32(0), WasmValue::I32(27)]; 272 | let result = function.call(instance, ¶ms); 273 | assert_eq!(result.unwrap(), vec![WasmValue::I32(27)]); 274 | } 275 | 276 | #[test] 277 | fn test_func_in_wasm32_wasi_w_args() { 278 | let runtime = Runtime::new().unwrap(); 279 | 280 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 281 | d.push("resources/test"); 282 | d.push("wasi-demo-app.wasm"); 283 | let module = Module::from_file(&runtime, d.as_path()); 284 | assert!(module.is_ok()); 285 | let mut module = module.unwrap(); 286 | 287 | let wasi_ctx = WasiCtxBuilder::new() 288 | .set_pre_open_path(vec!["."], vec![]) 289 | .set_arguments(vec!["wasi-demo-app.wasm", "echo", "hi"]) 290 | .build(); 291 | module.set_wasi_context(wasi_ctx); 292 | 293 | let instance = Instance::new(&runtime, &module, 1024 * 64); 294 | assert!(instance.is_ok()); 295 | let instance: &Instance = &instance.unwrap(); 296 | 297 | let function = Function::find_export_func(instance, "_start"); 298 | assert!(function.is_ok()); 299 | let function = function.unwrap(); 300 | 301 | let result = function.call(instance, &vec![]); 302 | assert!(result.is_ok()); 303 | println!("{:?}", result.unwrap()); 304 | } 305 | 306 | #[test] 307 | fn test_func_in_multi_v128_return() { 308 | let runtime = Runtime::new().unwrap(); 309 | 310 | // (module 311 | // (func (export "multi") (result f64 f32 i32 i64 f64 f32 i32 i64 v128 v128 v128 v128) 312 | // f64.const 22.2222 313 | // f32.const 1.57 314 | // i32.const 42 315 | // i64.const 3523 316 | // f64.const 22.2222 317 | // f32.const 1.57 318 | // i32.const 42 319 | // i64.const 3523 320 | // v128.const i32x4 1 2 3 4 321 | // v128.const f32x4 1 2 3 4 322 | // v128.const i64x2 1 2 323 | // v128.const f64x2 1 2) 324 | // ) 325 | let mut wasm_src = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 326 | wasm_src.push("resources/test"); 327 | wasm_src.push("multiret.wasm"); 328 | 329 | // Compiling to AOT 330 | let mut aot_dest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 331 | aot_dest.push("resources/test"); 332 | aot_dest.push("multiret.aot"); 333 | 334 | // Get the path to wamrc binary 335 | let base = match Path::new("target/release").exists() { 336 | true => "target/release/build", 337 | false => "target/debug/build", 338 | }; 339 | let base_entries = fs::read_dir(base); 340 | assert!(base_entries.is_ok()); 341 | let found = base_entries.unwrap() 342 | .filter_map(|entry| entry.ok()) 343 | .map(|entry| { 344 | let path = entry.path(); 345 | let name = path 346 | .file_name() 347 | .and_then(|s| s.to_str()) 348 | .unwrap_or("") 349 | .to_string(); 350 | (path, name) 351 | }) 352 | .filter_map(|(path, name)| { 353 | if name.starts_with("wamr-sys") && path.join("out").join("wamrcbuild").join("bin").join("wamrc").exists() { 354 | Some(path.join("out").join("wamrcbuild").join("bin").join("wamrc")) 355 | } else { 356 | None 357 | } 358 | }) 359 | .next(); 360 | assert!(found.is_some()); 361 | let wamrc_path = found.unwrap(); 362 | 363 | let wamrc_output = Command::new(wamrc_path) 364 | .arg("--bounds-checks=1") 365 | .arg("-o") 366 | .arg(aot_dest.clone()) 367 | .arg(wasm_src.clone()) 368 | .stderr(Stdio::piped()) 369 | .stdout(Stdio::piped()) 370 | .output() 371 | .unwrap(); 372 | assert!(String::from_utf8_lossy(&wamrc_output.stdout).contains("Compile success")); 373 | 374 | let module = Module::from_file(&runtime, aot_dest.as_path()); 375 | assert!(module.is_ok()); 376 | let module = module.unwrap(); 377 | 378 | let instance = Instance::new(&runtime, &module, 1024 * 64); 379 | assert!(instance.is_ok()); 380 | let instance: &Instance = &instance.unwrap(); 381 | 382 | let function = Function::find_export_func(instance, "multi"); 383 | assert!(function.is_ok()); 384 | let function = function.unwrap(); 385 | 386 | let wrapped_result = function.call(instance, &vec![]); 387 | let unwrapped_result = wrapped_result.unwrap(); 388 | 389 | assert_eq!(unwrapped_result.len(), 12); 390 | assert_eq!( 391 | unwrapped_result, 392 | vec![ 393 | WasmValue::F64(22.2222), 394 | WasmValue::F32(1.57), 395 | WasmValue::I32(42), 396 | WasmValue::I64(3523), 397 | WasmValue::F64(22.2222), 398 | WasmValue::F32(1.57), 399 | WasmValue::I32(42), 400 | WasmValue::I64(3523), 401 | WasmValue::V128(316912650112397582603894390785), 402 | WasmValue::V128(85735205748011485687928662073142149120), 403 | WasmValue::V128(36893488147419103233), 404 | WasmValue::V128(85070591730234615870450834276742070272) 405 | ] 406 | ); 407 | } 408 | } 409 | -------------------------------------------------------------------------------- /src/helper.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | use std::ffi::{c_char, CStr}; 7 | use std::string::String; 8 | 9 | pub const DEFAULT_ERROR_BUF_SIZE: usize = 128; 10 | 11 | pub fn error_buf_to_string(&error_buf: &[c_char; DEFAULT_ERROR_BUF_SIZE]) -> String { 12 | let error_content: Vec = error_buf 13 | .map(|c| c as u8) 14 | .into_iter() 15 | .filter(|c| *c > 0) 16 | .collect(); 17 | String::from_utf8(error_content).unwrap() 18 | } 19 | 20 | pub fn cstr_to_string(raw_cstr: *const c_char) -> String { 21 | let cstr = unsafe { CStr::from_ptr(raw_cstr) }; 22 | String::from_utf8_lossy(cstr.to_bytes()).to_string() 23 | } 24 | 25 | pub fn exception_to_string(raw_exception: *const c_char) -> String { 26 | cstr_to_string(raw_exception) 27 | } 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | use std::ffi::CString; 33 | 34 | #[test] 35 | fn test_error_buf_empty() { 36 | let error_buf = [0 as c_char; DEFAULT_ERROR_BUF_SIZE]; 37 | let error_str = error_buf_to_string(&error_buf); 38 | assert_eq!(error_str.len(), 0); 39 | assert_eq!(error_str, ""); 40 | } 41 | 42 | #[test] 43 | fn test_error_buf() { 44 | let mut error_buf = [0 as c_char; DEFAULT_ERROR_BUF_SIZE]; 45 | error_buf[0] = 'a' as i8; 46 | error_buf[1] = 'b' as i8; 47 | error_buf[2] = 'c' as i8; 48 | 49 | let error_str = error_buf_to_string(&error_buf); 50 | assert_eq!(error_str.len(), 3); 51 | assert_eq!(error_str, "abc"); 52 | } 53 | 54 | #[test] 55 | fn test_exception_to_string() { 56 | let exception = "it is an exception"; 57 | 58 | let exception_cstr = CString::new(exception).expect("CString::new failed"); 59 | let exception_str = exception_to_string(exception_cstr.as_ptr()); 60 | assert_eq!(exception_str.len(), exception.len()); 61 | assert_eq!(exception_str, exception); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/host_function.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | /// This is a wrapper of a host defined(Rust) function. 7 | use std::ffi::{c_void, CString}; 8 | use std::ptr; 9 | 10 | use wamr_sys::NativeSymbol; 11 | 12 | #[allow(dead_code)] 13 | #[derive(Debug)] 14 | struct HostFunction { 15 | function_name: CString, 16 | function_ptr: *mut c_void, 17 | } 18 | 19 | #[derive(Debug)] 20 | pub struct HostFunctionList { 21 | pub module_name: CString, 22 | // keep ownership of the content of `native_symbols` 23 | host_functions: Vec, 24 | pub native_symbols: Vec, 25 | } 26 | 27 | impl HostFunctionList { 28 | pub fn new(module_name: &str) -> Self { 29 | HostFunctionList { 30 | module_name: CString::new(module_name).unwrap(), 31 | host_functions: Vec::new(), 32 | native_symbols: Vec::new(), 33 | } 34 | } 35 | 36 | pub fn register_host_function(&mut self, function_name: &str, function_ptr: *mut c_void) { 37 | self.host_functions.push(HostFunction { 38 | function_name: CString::new(function_name).unwrap(), 39 | function_ptr, 40 | }); 41 | 42 | let last = self.host_functions.last().unwrap(); 43 | self.native_symbols 44 | .push(pack_host_function(&(last.function_name), function_ptr)); 45 | } 46 | 47 | pub fn get_native_symbols(&mut self) -> &mut Vec { 48 | &mut self.native_symbols 49 | } 50 | 51 | pub fn get_module_name(&mut self) -> &CString { 52 | &self.module_name 53 | } 54 | } 55 | 56 | pub fn pack_host_function(function_name: &CString, function_ptr: *mut c_void) -> NativeSymbol { 57 | NativeSymbol { 58 | symbol: function_name.as_ptr(), 59 | func_ptr: function_ptr, 60 | signature: ptr::null(), 61 | attachment: ptr::null_mut(), 62 | } 63 | } 64 | 65 | #[cfg(test)] 66 | mod tests { 67 | use super::*; 68 | use crate::{ 69 | function::Function, instance::Instance, module::Module, runtime::Runtime, value::WasmValue, 70 | }; 71 | use std::env; 72 | use std::path::PathBuf; 73 | 74 | extern "C" fn extra() -> i32 { 75 | 100 76 | } 77 | 78 | #[test] 79 | #[ignore] 80 | fn test_host_function() { 81 | let runtime = Runtime::builder() 82 | .use_system_allocator() 83 | .register_host_function("extra", extra as *mut c_void) 84 | .build() 85 | .unwrap(); 86 | 87 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 88 | d.push("resources/test"); 89 | d.push("add_extra_wasm32_wasi.wasm"); 90 | let module = Module::from_file(&runtime, d.as_path()); 91 | assert!(module.is_ok()); 92 | let module = module.unwrap(); 93 | 94 | let instance = Instance::new(&runtime, &module, 1024 * 64); 95 | assert!(instance.is_ok()); 96 | let instance: &Instance = &instance.unwrap(); 97 | 98 | let function = Function::find_export_func(instance, "add"); 99 | assert!(function.is_ok()); 100 | let function = function.unwrap(); 101 | 102 | let params: Vec = vec![WasmValue::I32(8), WasmValue::I32(8)]; 103 | let result = function.call(instance, ¶ms); 104 | assert_eq!(result.unwrap(), vec![WasmValue::I32(116)]); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/instance.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | //! an instantiated module. The module is instantiated with the given imports. 7 | //! get one via `Instance::new()` 8 | 9 | #![allow(unused_variables)] 10 | 11 | use core::{ffi::c_char, marker::PhantomData}; 12 | 13 | use wamr_sys::{ 14 | wasm_module_inst_t, wasm_runtime_deinstantiate, wasm_runtime_destroy_thread_env, 15 | wasm_runtime_init_thread_env, wasm_runtime_instantiate, 16 | }; 17 | 18 | use crate::{ 19 | helper::error_buf_to_string, helper::DEFAULT_ERROR_BUF_SIZE, module::Module, runtime::Runtime, 20 | RuntimeError, 21 | }; 22 | 23 | #[derive(Debug)] 24 | pub struct Instance<'module> { 25 | instance: wasm_module_inst_t, 26 | _phantom: PhantomData>, 27 | } 28 | 29 | impl<'module> Instance<'module> { 30 | /// instantiate a module with stack size 31 | /// 32 | /// # Error 33 | /// 34 | /// Return `RuntimeError::CompilationError` if failed. 35 | pub fn new( 36 | runtime: &Runtime, 37 | module: &'module Module<'module>, 38 | stack_size: u32, 39 | ) -> Result { 40 | Self::new_with_args(runtime, module, stack_size, 0) 41 | } 42 | 43 | /// instantiate a module with stack size and host managed heap size 44 | /// 45 | /// heap_size is used for `-nostdlib` Wasm and wasm32-unknown 46 | /// 47 | /// # Error 48 | /// 49 | /// Return `RuntimeError::CompilationError` if failed. 50 | pub fn new_with_args( 51 | _runtime: &Runtime, 52 | module: &'module Module<'module>, 53 | stack_size: u32, 54 | heap_size: u32, 55 | ) -> Result { 56 | let init_thd_env = unsafe { wasm_runtime_init_thread_env() }; 57 | if !init_thd_env { 58 | return Err(RuntimeError::InstantiationFailure(String::from( 59 | "thread signal env initialized failed", 60 | ))); 61 | } 62 | 63 | let mut error_buf = [0 as c_char; DEFAULT_ERROR_BUF_SIZE]; 64 | let instance = unsafe { 65 | wasm_runtime_instantiate( 66 | module.get_inner_module(), 67 | stack_size, 68 | heap_size, 69 | error_buf.as_mut_ptr(), 70 | error_buf.len() as u32, 71 | ) 72 | }; 73 | 74 | if instance.is_null() { 75 | match error_buf.len() { 76 | 0 => { 77 | return Err(RuntimeError::InstantiationFailure(String::from( 78 | "instantiation failed", 79 | ))) 80 | } 81 | _ => { 82 | return Err(RuntimeError::InstantiationFailure(error_buf_to_string( 83 | &error_buf, 84 | ))) 85 | } 86 | } 87 | } 88 | 89 | Ok(Instance { 90 | instance, 91 | _phantom: PhantomData, 92 | }) 93 | } 94 | 95 | pub fn get_inner_instance(&self) -> wasm_module_inst_t { 96 | self.instance 97 | } 98 | } 99 | 100 | impl Drop for Instance<'_> { 101 | fn drop(&mut self) { 102 | unsafe { 103 | wasm_runtime_destroy_thread_env(); 104 | wasm_runtime_deinstantiate(self.instance); 105 | } 106 | } 107 | } 108 | 109 | #[cfg(test)] 110 | mod tests { 111 | use super::*; 112 | use crate::runtime::Runtime; 113 | use wamr_sys::{ 114 | wasm_runtime_get_running_mode, RunningMode_Mode_Interp, RunningMode_Mode_LLVM_JIT, 115 | }; 116 | 117 | #[test] 118 | fn test_instance_new() { 119 | let runtime = Runtime::new().unwrap(); 120 | 121 | // (module 122 | // (func (export "add") (param i32 i32) (result i32) 123 | // (local.get 0) 124 | // (local.get 1) 125 | // (i32.add) 126 | // ) 127 | // ) 128 | let binary = vec![ 129 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 130 | 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 131 | 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b, 132 | ]; 133 | let binary = binary.into_iter().map(|c| c as u8).collect::>(); 134 | 135 | let module = Module::from_vec(&runtime, binary, "add"); 136 | assert!(module.is_ok()); 137 | 138 | let module = &module.unwrap(); 139 | 140 | let instance = Instance::new_with_args(&runtime, module, 1024, 1024); 141 | assert!(instance.is_ok()); 142 | 143 | let instance = Instance::new_with_args(&runtime, module, 1024, 0); 144 | assert!(instance.is_ok()); 145 | 146 | let instance = instance.unwrap(); 147 | assert_eq!( 148 | unsafe { wasm_runtime_get_running_mode(instance.get_inner_instance()) }, 149 | if cfg!(feature = "llvmjit") { 150 | RunningMode_Mode_LLVM_JIT 151 | } else { 152 | RunningMode_Mode_Interp 153 | } 154 | ); 155 | } 156 | 157 | #[test] 158 | #[ignore] 159 | fn test_instance_running_mode_default() { 160 | let runtime = Runtime::builder().use_system_allocator().build().unwrap(); 161 | 162 | // (module 163 | // (func (export "add") (param i32 i32) (result i32) 164 | // (local.get 0) 165 | // (local.get 1) 166 | // (i32.add) 167 | // ) 168 | // ) 169 | let binary = vec![ 170 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 171 | 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 172 | 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b, 173 | ]; 174 | let binary = binary.into_iter().map(|c| c as u8).collect::>(); 175 | 176 | let module = Module::from_vec(&runtime, binary, ""); 177 | assert!(module.is_ok()); 178 | 179 | let module = &module.unwrap(); 180 | 181 | let instance = Instance::new_with_args(&runtime, module, 1024, 1024); 182 | assert!(instance.is_ok()); 183 | 184 | let instance = instance.unwrap(); 185 | assert_eq!( 186 | unsafe { wasm_runtime_get_running_mode(instance.get_inner_instance()) }, 187 | if cfg!(feature = "llvmjit") { 188 | RunningMode_Mode_LLVM_JIT 189 | } else { 190 | RunningMode_Mode_Interp 191 | } 192 | ); 193 | } 194 | 195 | #[test] 196 | #[ignore] 197 | fn test_instance_running_mode_interpreter() { 198 | let runtime = Runtime::builder() 199 | .run_as_interpreter() 200 | .use_system_allocator() 201 | .build() 202 | .unwrap(); 203 | 204 | // (module 205 | // (func (export "add") (param i32 i32) (result i32) 206 | // (local.get 0) 207 | // (local.get 1) 208 | // (i32.add) 209 | // ) 210 | // ) 211 | let binary = vec![ 212 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 213 | 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 214 | 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b, 215 | ]; 216 | let binary = binary.into_iter().map(|c| c as u8).collect::>(); 217 | 218 | let module = Module::from_vec(&runtime, binary, "add"); 219 | assert!(module.is_ok()); 220 | 221 | let module = &module.unwrap(); 222 | 223 | let instance = Instance::new_with_args(&runtime, module, 1024, 1024); 224 | assert!(instance.is_ok()); 225 | 226 | let instance = instance.unwrap(); 227 | assert_eq!( 228 | unsafe { wasm_runtime_get_running_mode(instance.get_inner_instance()) }, 229 | RunningMode_Mode_Interp 230 | ); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | //! # WAMR Rust SDK 7 | //! 8 | //! ## Overview 9 | //! 10 | //! WAMR Rust SDK provides Rust language bindings for WAMR. It is the wrapper 11 | //! of [*wasm_export.h*](../../../core/iwasm/include/wasm_export.h) but with Rust style. 12 | //! It is more convenient to use WAMR in Rust with this crate. 13 | //! 14 | //! This crate contains API used to interact with Wasm modules. You can compile 15 | //! modules, instantiate modules, call their export functions, etc. 16 | //! Plus, as an embedded of Wasm, you can provide Wasm module functionality by 17 | //! creating host-defined functions. 18 | //! 19 | //! WAMR Rust SDK includes a [*wamr-sys*](../crates/wamr-sys) crate. It will search for 20 | //! the WAMR runtime source in the path *../..*. And then uses `rust-bindgen` durning 21 | //! the build process to make a .so. 22 | //! 23 | //! This crate has similar concepts to the 24 | //! [WebAssembly specification](https://webassembly.github.io/spec/core/). 25 | //! 26 | //! ### Core concepts 27 | //! 28 | //! - *Runtime*. It is the environment that hosts all the wasm modules. Each process has one runtime instance. 29 | //! - *Module*. It is the compiled .wasm or .aot. It can be loaded into runtime and instantiated into instance. 30 | //! - *Instance*. It is the running instance of a module. It can be used to call export functions. 31 | //! - *Function*. It is the exported function. 32 | //! 33 | //! ### WASI concepts 34 | //! 35 | //! - *WASIArgs*. It is used to configure the WASI environment. 36 | //! - *pre-open*. All files and directories in the list will be opened before the .wasm or .aot loaded. 37 | //! - *allowed address*. All ip addresses in the *allowed address* list will be allowed to connect with a socket. 38 | //! - *allowed DNS*. 39 | //! 40 | //! ### WAMR private concepts 41 | //! 42 | //! - *loading linking* instead of *instantiation linking*. *instantiation linking* is 43 | //! used in Wasm JS API and Wasm C API. It means that every instance has its own, maybe 44 | //! variant, imports. But *loading linking* means that all instances share the same *imports*. 45 | //! 46 | //! - *RuntimeArg*. Control runtime behavior. 47 | //! - *running mode*. 48 | //! - *allocator*. 49 | //! 50 | //! - *NativeFunction*. 51 | //! 52 | //! - *WasmValues*. 53 | //! 54 | //! ## Examples 55 | //! 56 | //! ### Example: to run a wasm32-wasip1 .wasm 57 | //! 58 | //! *wasm32-wasip1* is a most common target for Wasm. It means that the .wasm is compiled with 59 | //! `cargo build --target wasm32-wasip1` or `wasi-sdk/bin/clang --target wasm32-wasip1`. 60 | //! 61 | //! Say there is a gcd_wasm32_wasi.wasm which includes a function named *gcd*. It returns the GCD 62 | //! of two parameters. 63 | //! 64 | //! The rust code to call the function would be: 65 | //! 66 | //! ``` 67 | //! use wamr_rust_sdk::{ 68 | //! runtime::Runtime, module::Module, instance::Instance, function::Function, 69 | //! value::WasmValue, RuntimeError 70 | //! }; 71 | //! use std::path::PathBuf; 72 | //! 73 | //! fn main() -> Result<(), RuntimeError> { 74 | //! let runtime = Runtime::new()?; 75 | //! 76 | //! let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 77 | //! d.push("resources/test"); 78 | //! d.push("gcd_wasm32_wasi.wasm"); 79 | //! 80 | //! let module = Module::from_file(&runtime, d.as_path())?; 81 | //! 82 | //! let instance = Instance::new(&runtime, &module, 1024 * 64)?; 83 | //! 84 | //! let function = Function::find_export_func(&instance, "gcd")?; 85 | //! 86 | //! let params: Vec = vec![WasmValue::I32(9), WasmValue::I32(27)]; 87 | //! let result = function.call(&instance, ¶ms)?; 88 | //! assert_eq!(result, vec![WasmValue::I32(9)]); 89 | //! 90 | //! Ok(()) 91 | //! } 92 | //! ``` 93 | //! 94 | //! ### Example: more configuration for runtime. 95 | //! 96 | //! With more configuration, runtime is capable to run .wasm with variant features, like 97 | //! - Wasm without WASI requirement. Usually, it means that the .wasm is compiled with `-nostdlib` 98 | //! or `--target wasm32-unknown-unknown` 99 | //! - Configure runtime. 100 | //! - Provides host-defined functions to meet import requirements. 101 | //! 102 | //! Say there is an add_extra_wasm32_wasi.wasm. Its exported function, `add()`, 103 | //! requires an imported function, `extra()`, during the execution. The `add()` 104 | //! adds two parameters and the result of `extra()` . It is like `a + b + extra()`. 105 | //! 106 | //! The rust code to call the *add* function is like this: 107 | //! 108 | //! ``` 109 | //! use wamr_rust_sdk::{ 110 | //! runtime::Runtime, module::Module, instance::Instance, function::Function, 111 | //! value::WasmValue, RuntimeError 112 | //! }; 113 | //! use std::path::PathBuf; 114 | //! use std::ffi::c_void; 115 | //! 116 | //! extern "C" fn extra() -> i32 { 117 | //! 100 118 | //! } 119 | //! 120 | //! fn main() -> Result<(), RuntimeError> { 121 | //! let runtime = Runtime::builder() 122 | //! .use_system_allocator() 123 | //! .register_host_function("extra", extra as *mut c_void) 124 | //! .build()?; 125 | //! 126 | //! let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 127 | //! d.push("resources/test"); 128 | //! d.push("add_extra_wasm32_wasi.wasm"); 129 | //! let module = Module::from_file(&runtime, d.as_path())?; 130 | //! 131 | //! let instance = Instance::new(&runtime, &module, 1024 * 64)?; 132 | //! 133 | //! let function = Function::find_export_func(&instance, "add")?; 134 | //! 135 | //! let params: Vec = vec![WasmValue::I32(9), WasmValue::I32(27)]; 136 | //! let result = function.call(&instance, ¶ms)?; 137 | //! assert_eq!(result, vec![WasmValue::I32(136)]); 138 | //! 139 | //! Ok(()) 140 | //! } 141 | //! ``` 142 | //! 143 | 144 | use std::error; 145 | use std::fmt; 146 | use std::io; 147 | pub use wamr_sys as sys; 148 | 149 | pub mod function; 150 | mod helper; 151 | pub mod host_function; 152 | pub mod instance; 153 | pub mod module; 154 | pub mod runtime; 155 | pub mod value; 156 | pub mod wasi_context; 157 | 158 | #[derive(Debug)] 159 | pub struct ExecError { 160 | pub message: String, 161 | pub exit_code: u32, 162 | } 163 | 164 | /// all kinds of exceptions raised by WAMR 165 | #[derive(Debug)] 166 | pub enum RuntimeError { 167 | NotImplemented, 168 | /// Runtime initialization error. 169 | InitializationFailure, 170 | /// file operation error. usually while loading(compilation) a .wasm 171 | WasmFileFSError(std::io::Error), 172 | /// A compilation error. usually means that the .wasm file is invalid 173 | CompilationError(String), 174 | /// instantiation failure 175 | InstantiationFailure(String), 176 | /// Error during execute wasm functions 177 | ExecutionError(ExecError), 178 | /// usually returns by `find_export_func()` 179 | FunctionNotFound, 180 | } 181 | 182 | impl fmt::Display for RuntimeError { 183 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 184 | match self { 185 | RuntimeError::NotImplemented => write!(f, "Not implemented"), 186 | RuntimeError::InitializationFailure => write!(f, "Runtime initialization failure"), 187 | RuntimeError::WasmFileFSError(e) => write!(f, "Wasm file operation error: {}", e), 188 | RuntimeError::CompilationError(e) => write!(f, "Wasm compilation error: {}", e), 189 | RuntimeError::InstantiationFailure(e) => write!(f, "Wasm instantiation failure: {}", e), 190 | RuntimeError::ExecutionError(info) => write!( 191 | f, 192 | "Wasm execution error: {} and {}", 193 | info.message, info.exit_code 194 | ), 195 | RuntimeError::FunctionNotFound => write!(f, "Function not found"), 196 | } 197 | } 198 | } 199 | 200 | impl error::Error for RuntimeError { 201 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { 202 | match self { 203 | RuntimeError::WasmFileFSError(e) => Some(e), 204 | _ => None, 205 | } 206 | } 207 | } 208 | 209 | impl From for RuntimeError { 210 | fn from(e: io::Error) -> Self { 211 | RuntimeError::WasmFileFSError(e) 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/module.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | //! .wasm compiled, in-memory representation 7 | //! get one via `Module::from_file()` or `Module::from_buf()` 8 | 9 | use crate::{ 10 | helper::error_buf_to_string, helper::DEFAULT_ERROR_BUF_SIZE, runtime::Runtime, 11 | wasi_context::WasiCtx, RuntimeError, 12 | }; 13 | use core::marker::PhantomData; 14 | use std::{ 15 | ffi::{c_char, CString}, 16 | fs::File, 17 | io::Read, 18 | path::Path, 19 | ptr, 20 | string::String, 21 | vec::Vec, 22 | }; 23 | use wamr_sys::{ 24 | wasm_module_t, wasm_runtime_load, wasm_runtime_set_module_name, 25 | wasm_runtime_set_wasi_addr_pool, wasm_runtime_set_wasi_args, 26 | wasm_runtime_set_wasi_ns_lookup_pool, wasm_runtime_unload, 27 | }; 28 | 29 | #[allow(dead_code)] 30 | #[derive(Debug)] 31 | pub struct Module<'runtime> { 32 | name: String, 33 | module: wasm_module_t, 34 | // to keep the module content in memory 35 | content: Vec, 36 | wasi_ctx: WasiCtx, 37 | _phantom: PhantomData<&'runtime Runtime>, 38 | } 39 | 40 | impl<'runtime> Module<'runtime> { 41 | /// compile a module with the given wasm file path, use the file name as the module name 42 | /// 43 | /// # Error 44 | /// 45 | /// If the file does not exist or the file cannot be read, an `RuntimeError::WasmFileFSError` will be returned. 46 | /// If the wasm file is not a valid wasm file, an `RuntimeError::CompilationError` will be returned. 47 | pub fn from_file(runtime: &'runtime Runtime, wasm_file: &Path) -> Result { 48 | let name = wasm_file.file_name().unwrap().to_str().unwrap(); 49 | let mut wasm_file = File::open(wasm_file)?; 50 | 51 | let mut binary: Vec = Vec::new(); 52 | wasm_file.read_to_end(&mut binary)?; 53 | 54 | Self::from_vec(runtime, binary, name) 55 | } 56 | 57 | /// compile a module int the given buffer, 58 | /// 59 | /// # Error 60 | /// 61 | /// If the file does not exist or the file cannot be read, an `RuntimeError::WasmFileFSError` will be returned. 62 | /// If the wasm file is not a valid wasm file, an `RuntimeError::CompilationError` will be returned. 63 | pub fn from_vec( 64 | _runtime: &'runtime Runtime, 65 | mut content: Vec, 66 | name: &str, 67 | ) -> Result { 68 | let mut error_buf: [c_char; DEFAULT_ERROR_BUF_SIZE] = [0; DEFAULT_ERROR_BUF_SIZE]; 69 | let module = unsafe { 70 | wasm_runtime_load( 71 | content.as_mut_ptr(), 72 | content.len() as u32, 73 | error_buf.as_mut_ptr(), 74 | error_buf.len() as u32, 75 | ) 76 | }; 77 | 78 | if module.is_null() { 79 | match error_buf.len() { 80 | 0 => { 81 | return Err(RuntimeError::CompilationError(String::from( 82 | "load module failed", 83 | ))) 84 | } 85 | _ => { 86 | return Err(RuntimeError::CompilationError(error_buf_to_string( 87 | &error_buf, 88 | ))) 89 | } 90 | } 91 | } 92 | 93 | unsafe { 94 | let name_c = CString::new(name.as_bytes()).unwrap(); 95 | if !wasm_runtime_set_module_name( 96 | module, 97 | name_c.as_ptr() as *mut c_char, 98 | error_buf.as_mut_ptr(), 99 | error_buf.len() as u32, 100 | ) { 101 | return Err(RuntimeError::CompilationError(error_buf_to_string( 102 | &error_buf, 103 | ))); 104 | } 105 | } 106 | 107 | Ok(Module { 108 | name: String::from(name), 109 | module, 110 | content, 111 | wasi_ctx: WasiCtx::default(), 112 | _phantom: PhantomData, 113 | }) 114 | } 115 | 116 | /// set Wasi context for a module 117 | /// 118 | /// This function should be called before `Instance::new` 119 | pub fn set_wasi_context(&mut self, wasi_ctx: WasiCtx) { 120 | self.wasi_ctx = wasi_ctx; 121 | 122 | let real_paths = if self.wasi_ctx.get_preopen_real_paths().is_empty() { 123 | ptr::null_mut() 124 | } else { 125 | self.wasi_ctx.get_preopen_real_paths().as_ptr() as *mut *const c_char 126 | }; 127 | 128 | let mapped_paths = if self.wasi_ctx.get_preopen_mapped_paths().is_empty() { 129 | ptr::null_mut() 130 | } else { 131 | self.wasi_ctx.get_preopen_mapped_paths().as_ptr() as *mut *const c_char 132 | }; 133 | 134 | let env = if self.wasi_ctx.get_env_vars().is_empty() { 135 | ptr::null_mut() 136 | } else { 137 | self.wasi_ctx.get_env_vars_ptrs().as_ptr() as *mut *const c_char 138 | }; 139 | 140 | let args = if self.wasi_ctx.get_arguments().is_empty() { 141 | ptr::null_mut() 142 | } else { 143 | self.wasi_ctx.get_arguments_ptrs().as_ptr() as *mut *mut c_char 144 | }; 145 | 146 | unsafe { 147 | wasm_runtime_set_wasi_args( 148 | self.get_inner_module(), 149 | real_paths, 150 | self.wasi_ctx.get_preopen_real_paths().len() as u32, 151 | mapped_paths, 152 | self.wasi_ctx.get_preopen_mapped_paths().len() as u32, 153 | env, 154 | self.wasi_ctx.get_env_vars().len() as u32, 155 | args, 156 | self.wasi_ctx.get_arguments().len() as i32, 157 | ); 158 | 159 | let ns_lookup_pool = if self.wasi_ctx.get_allowed_dns().is_empty() { 160 | ptr::null_mut() 161 | } else { 162 | self.wasi_ctx.get_allowed_dns().as_ptr() as *mut *const c_char 163 | }; 164 | 165 | wasm_runtime_set_wasi_ns_lookup_pool( 166 | self.get_inner_module(), 167 | ns_lookup_pool, 168 | self.wasi_ctx.get_allowed_dns().len() as u32, 169 | ); 170 | 171 | let addr_pool = if self.wasi_ctx.get_allowed_address().is_empty() { 172 | ptr::null_mut() 173 | } else { 174 | self.wasi_ctx.get_allowed_address().as_ptr() as *mut *const c_char 175 | }; 176 | wasm_runtime_set_wasi_addr_pool( 177 | self.get_inner_module(), 178 | addr_pool, 179 | self.wasi_ctx.get_allowed_address().len() as u32, 180 | ); 181 | } 182 | } 183 | 184 | pub fn get_inner_module(&self) -> wasm_module_t { 185 | self.module 186 | } 187 | 188 | pub fn get_name(&self) -> &str { 189 | &self.name 190 | } 191 | } 192 | 193 | impl Drop for Module<'_> { 194 | fn drop(&mut self) { 195 | unsafe { 196 | wasm_runtime_unload(self.module); 197 | } 198 | } 199 | } 200 | 201 | #[cfg(test)] 202 | mod tests { 203 | use super::*; 204 | use crate::{helper::cstr_to_string, runtime::Runtime, wasi_context::WasiCtxBuilder}; 205 | use std::path::PathBuf; 206 | use wamr_sys::wasm_runtime_get_module_name; 207 | 208 | #[test] 209 | fn test_module_not_exist() { 210 | let runtime = Runtime::new(); 211 | assert!(runtime.is_ok()); 212 | 213 | let runtime = runtime.unwrap(); 214 | 215 | let module = Module::from_file(&runtime, Path::new("not_exist")); 216 | assert!(module.is_err()); 217 | } 218 | 219 | #[test] 220 | fn test_module_from_buf() { 221 | let runtime = Runtime::new().unwrap(); 222 | 223 | // (module 224 | // (func (export "add") (param i32 i32) (result i32) 225 | // (local.get 0) 226 | // (local.get 1) 227 | // (i32.add) 228 | // ) 229 | // ) 230 | let binary = vec![ 231 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 232 | 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 233 | 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b, 234 | ]; 235 | let binary = binary.into_iter().map(|c| c as u8).collect::>(); 236 | 237 | let module = Module::from_vec(&runtime, binary, ""); 238 | assert!(module.is_ok()); 239 | } 240 | 241 | #[test] 242 | fn test_module_from_file() { 243 | let runtime = Runtime::new().unwrap(); 244 | 245 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 246 | d.push("resources/test"); 247 | d.push("gcd_wasm32_wasi.wasm"); 248 | let module = Module::from_file(&runtime, d.as_path()); 249 | assert!(module.is_ok()); 250 | } 251 | 252 | #[test] 253 | fn test_module_with_wasi_args() { 254 | let runtime = Runtime::new().unwrap(); 255 | 256 | // (module 257 | // (func (export "add") (param i32 i32) (result i32) 258 | // (local.get 0) 259 | // (local.get 1) 260 | // (i32.add) 261 | // ) 262 | // ) 263 | let binary = vec![ 264 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 265 | 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 266 | 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b, 267 | ]; 268 | let binary = binary.into_iter().map(|c| c as u8).collect::>(); 269 | 270 | let module = Module::from_vec(&runtime, binary, "add"); 271 | assert!(module.is_ok()); 272 | let mut module = module.unwrap(); 273 | 274 | let wasi_ctx = WasiCtxBuilder::new() 275 | .set_pre_open_path(vec!["."], vec![]) 276 | .set_env_vars(vec![]) 277 | .set_allowed_address(vec![]) 278 | .set_allowed_dns(vec![]) 279 | .build(); 280 | 281 | module.set_wasi_context(wasi_ctx); 282 | } 283 | 284 | #[test] 285 | fn test_module_name() -> Result<(), RuntimeError> { 286 | let runtime = Runtime::new()?; 287 | 288 | // (module 289 | // (func (export "add") (param i32 i32) (result i32) 290 | // (local.get 0) 291 | // (local.get 1) 292 | // (i32.add) 293 | // ) 294 | // ) 295 | let binary = vec![ 296 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 297 | 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 298 | 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b, 299 | ]; 300 | let binary = binary.into_iter().map(|c| c as u8).collect::>(); 301 | 302 | let module = Module::from_vec(&runtime, binary, "add")?; 303 | 304 | assert_eq!(module.get_name(), "add"); 305 | 306 | let name = 307 | cstr_to_string(unsafe { wasm_runtime_get_module_name(module.get_inner_module()) }); 308 | assert_eq!(&name, module.get_name()); 309 | 310 | Ok(()) 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /src/runtime.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | //! This is the main entry point for executing WebAssembly modules. 7 | //! Every process should have only one instance of this runtime by call 8 | //! `Runtime::new()` or `Runtime::builder().build()` once. 9 | 10 | use std::ffi::c_void; 11 | 12 | use wamr_sys::{ 13 | mem_alloc_type_t_Alloc_With_Pool, mem_alloc_type_t_Alloc_With_System_Allocator, 14 | wasm_runtime_destroy, wasm_runtime_full_init, wasm_runtime_init, NativeSymbol, 15 | RunningMode_Mode_Interp, RunningMode_Mode_LLVM_JIT, RuntimeInitArgs, 16 | }; 17 | 18 | use crate::{host_function::HostFunctionList, RuntimeError}; 19 | 20 | #[allow(dead_code)] 21 | #[derive(Debug)] 22 | pub struct Runtime { 23 | host_functions: HostFunctionList, 24 | } 25 | 26 | impl Runtime { 27 | /// return a `RuntimeBuilder` instance 28 | /// 29 | /// has to 30 | /// - select a allocation mode 31 | /// - select a running mode 32 | pub fn builder() -> RuntimeBuilder { 33 | RuntimeBuilder::default() 34 | } 35 | 36 | /// create a new `Runtime` instance with the default configuration which includes: 37 | /// - system allocator mode 38 | /// - the default running mode 39 | /// 40 | /// # Errors 41 | /// 42 | /// if the runtime initialization failed, it will return `RuntimeError::InitializationFailure` 43 | pub fn new() -> Result { 44 | match unsafe { wasm_runtime_init() } { 45 | true => Ok(Runtime { 46 | host_functions: HostFunctionList::new("empty"), 47 | }), 48 | false => Err(RuntimeError::InitializationFailure), 49 | } 50 | } 51 | } 52 | 53 | impl Drop for Runtime { 54 | fn drop(&mut self) { 55 | unsafe { 56 | wasm_runtime_destroy(); 57 | } 58 | } 59 | } 60 | 61 | /// The builder of `Runtime`. It is used to configure the runtime. 62 | /// Get one via `Runtime::builder()` 63 | pub struct RuntimeBuilder { 64 | args: RuntimeInitArgs, 65 | host_functions: HostFunctionList, 66 | } 67 | 68 | /// Can't build() until config allocator mode 69 | impl Default for RuntimeBuilder { 70 | fn default() -> Self { 71 | let args = RuntimeInitArgs::default(); 72 | RuntimeBuilder { 73 | args, 74 | host_functions: HostFunctionList::new("host"), 75 | } 76 | } 77 | } 78 | 79 | impl RuntimeBuilder { 80 | /// system allocator mode 81 | /// allocate memory from system allocator for runtime consumed memory 82 | pub fn use_system_allocator(mut self) -> RuntimeBuilder { 83 | self.args.mem_alloc_type = mem_alloc_type_t_Alloc_With_System_Allocator; 84 | self 85 | } 86 | 87 | /// system allocator mode 88 | /// allocate memory from pool, as a pre-allocated buffer, for runtime consumed memory 89 | pub fn use_memory_pool(mut self, mut pool: Vec) -> RuntimeBuilder { 90 | self.args.mem_alloc_type = mem_alloc_type_t_Alloc_With_Pool; 91 | self.args.mem_alloc_option.pool.heap_buf = pool.as_mut_ptr() as *mut c_void; 92 | self.args.mem_alloc_option.pool.heap_size = pool.len() as u32; 93 | self 94 | } 95 | 96 | /// use interpreter mode 97 | pub fn run_as_interpreter(mut self) -> RuntimeBuilder { 98 | self.args.running_mode = RunningMode_Mode_Interp; 99 | self 100 | } 101 | 102 | /// use llvm-jit mode 103 | pub fn run_as_llvm_jit(mut self, opt_level: u32, size_level: u32) -> RuntimeBuilder { 104 | self.args.running_mode = RunningMode_Mode_LLVM_JIT; 105 | self.args.llvm_jit_opt_level = opt_level; 106 | self.args.llvm_jit_size_level = size_level; 107 | self 108 | } 109 | 110 | /// register a host function 111 | pub fn register_host_function( 112 | mut self, 113 | function_name: &str, 114 | function_ptr: *mut c_void, 115 | ) -> RuntimeBuilder { 116 | self.host_functions 117 | .register_host_function(function_name, function_ptr); 118 | self 119 | } 120 | 121 | /// create a `Runtime` instance with the configuration 122 | /// 123 | /// # Errors 124 | /// 125 | /// if the runtime initialization failed, it will return `RuntimeError::InitializationFailure` 126 | pub fn build(mut self) -> Result { 127 | match unsafe { 128 | let module_name = &(self.host_functions).get_module_name(); 129 | self.args.native_module_name = module_name.as_ptr(); 130 | 131 | let native_symbols = &(self.host_functions).get_native_symbols(); 132 | self.args.n_native_symbols = native_symbols.len() as u32; 133 | self.args.native_symbols = native_symbols.as_ptr() as *mut NativeSymbol; 134 | 135 | wasm_runtime_full_init(&mut self.args) 136 | } { 137 | true => Ok(Runtime { 138 | host_functions: self.host_functions, 139 | }), 140 | false => Err(RuntimeError::InitializationFailure), 141 | } 142 | } 143 | } 144 | 145 | #[cfg(test)] 146 | mod tests { 147 | use super::*; 148 | use wamr_sys::{wasm_runtime_free, wasm_runtime_malloc}; 149 | 150 | #[test] 151 | #[ignore] 152 | fn test_runtime_new() { 153 | let runtime = Runtime::new(); 154 | assert!(runtime.is_ok()); 155 | 156 | /* use malloc to confirm */ 157 | let small_buf = unsafe { wasm_runtime_malloc(16) }; 158 | assert!(!small_buf.is_null()); 159 | unsafe { wasm_runtime_free(small_buf) }; 160 | 161 | drop(runtime); 162 | 163 | /* runtime has been destroyed. malloc should be failed */ 164 | let small_buf = unsafe { wasm_runtime_malloc(16) }; 165 | assert!(small_buf.is_null()); 166 | 167 | { 168 | let runtime = Runtime::new(); 169 | assert!(runtime.is_ok()); 170 | 171 | let runtime = Runtime::new(); 172 | assert!(runtime.is_ok()); 173 | 174 | let runtime = Runtime::new(); 175 | assert!(runtime.is_ok()); 176 | } 177 | 178 | /* runtime has been destroyed. malloc should be failed */ 179 | let small_buf = unsafe { wasm_runtime_malloc(16) }; 180 | assert!(small_buf.is_null()); 181 | } 182 | 183 | #[test] 184 | fn test_runtime_builder_default() { 185 | // use Mode_Default 186 | let runtime = Runtime::builder().use_system_allocator().build(); 187 | assert!(runtime.is_ok()); 188 | 189 | let small_buf = unsafe { wasm_runtime_malloc(16) }; 190 | assert!(!small_buf.is_null()); 191 | unsafe { wasm_runtime_free(small_buf) }; 192 | } 193 | 194 | #[test] 195 | fn test_runtime_builder_interpreter() { 196 | let runtime = Runtime::builder() 197 | .run_as_interpreter() 198 | .use_system_allocator() 199 | .build(); 200 | assert!(runtime.is_ok()); 201 | 202 | let small_buf = unsafe { wasm_runtime_malloc(16) }; 203 | assert!(!small_buf.is_null()); 204 | unsafe { wasm_runtime_free(small_buf) }; 205 | } 206 | 207 | #[test] 208 | #[cfg(feature = "llvmjit")] 209 | #[ignore] 210 | fn test_runtime_builder_llvm_jit() { 211 | let runtime = Runtime::builder() 212 | .run_as_llvm_jit(3, 3) 213 | .use_system_allocator() 214 | .build(); 215 | assert!(runtime.is_ok()); 216 | 217 | let small_buf = unsafe { wasm_runtime_malloc(16) }; 218 | assert!(!small_buf.is_null()); 219 | unsafe { wasm_runtime_free(small_buf) }; 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/value.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | //! a wasm value. Always used as function parameters and results 7 | 8 | #[derive(Debug, PartialEq)] 9 | pub enum WasmValue { 10 | Void, 11 | I32(i32), 12 | I64(i64), 13 | F32(f32), 14 | F64(f64), 15 | V128(i128), 16 | } 17 | 18 | impl WasmValue { 19 | pub fn encode(&self) -> Vec { 20 | match *self { 21 | WasmValue::Void => { 22 | vec![] 23 | } 24 | WasmValue::I32(value) => { 25 | let in_u32_array = unsafe { std::mem::transmute::(value) }; 26 | vec![in_u32_array[0]] 27 | } 28 | WasmValue::I64(value) => { 29 | let in_u32_array = unsafe { std::mem::transmute::(value) }; 30 | vec![in_u32_array[0], in_u32_array[1]] 31 | } 32 | WasmValue::F32(value) => { 33 | let in_u32_array = unsafe { std::mem::transmute::(value) }; 34 | vec![in_u32_array[0]] 35 | } 36 | WasmValue::F64(value) => { 37 | let in_u32_array = unsafe { std::mem::transmute::(value) }; 38 | vec![in_u32_array[0], in_u32_array[1]] 39 | } 40 | WasmValue::V128(value) => { 41 | let in_u32_array = unsafe { std::mem::transmute::(value) }; 42 | vec![ 43 | in_u32_array[0], 44 | in_u32_array[1], 45 | in_u32_array[2], 46 | in_u32_array[3], 47 | ] 48 | } 49 | } 50 | } 51 | 52 | pub fn decode_to_i32(binary: &[u32]) -> WasmValue { 53 | let binary: [u32; 1] = [binary[0]]; 54 | WasmValue::I32(unsafe { std::mem::transmute::<[u32; 1], i32>(binary) }) 55 | } 56 | 57 | pub fn decode_to_f32(binary: &[u32]) -> WasmValue { 58 | let binary: [u32; 1] = [binary[0]]; 59 | WasmValue::F32(unsafe { std::mem::transmute::<[u32; 1], f32>(binary) }) 60 | } 61 | 62 | pub fn decode_to_i64(binary: &[u32]) -> WasmValue { 63 | let binary: [u32; 2] = [binary[0], binary[1]]; 64 | WasmValue::I64(unsafe { std::mem::transmute::<[u32; 2], i64>(binary) }) 65 | } 66 | 67 | pub fn decode_to_f64(binary: &[u32]) -> WasmValue { 68 | let binary: [u32; 2] = [binary[0], binary[1]]; 69 | WasmValue::F64(unsafe { std::mem::transmute::<[u32; 2], f64>(binary) }) 70 | } 71 | 72 | pub fn decode_to_v128(binary: &[u32]) -> WasmValue { 73 | let binary: [u32; 4] = [binary[0], binary[1], binary[2], binary[3]]; 74 | WasmValue::V128(unsafe { std::mem::transmute::<[u32; 4], i128>(binary) }) 75 | } 76 | } 77 | 78 | #[cfg(test)] 79 | mod tests { 80 | use super::*; 81 | 82 | #[test] 83 | fn test_encode() { 84 | let params = vec![WasmValue::I32(1), WasmValue::I64(2)]; 85 | 86 | let mut ret: Vec = Vec::new(); 87 | for p in params { 88 | ret.append(&mut p.encode()); 89 | } 90 | 91 | assert_eq!(ret.len(), 3); 92 | assert_eq!(ret, vec![1, 2, 0]); 93 | } 94 | 95 | #[test] 96 | fn test_encode_decode() { 97 | let values = vec![ 98 | WasmValue::I32(1), 99 | WasmValue::I64(2), 100 | WasmValue::F32(3.0), 101 | WasmValue::F64(4.0), 102 | WasmValue::V128(5), 103 | ]; 104 | 105 | let mut binary: Vec = Vec::new(); 106 | for v in &values { 107 | binary.append(&mut v.encode()); 108 | } 109 | 110 | let decoded_values: Vec = vec![ 111 | WasmValue::decode_to_i32(&binary[0..1]), 112 | WasmValue::decode_to_i64(&binary[1..3]), 113 | WasmValue::decode_to_f32(&binary[3..4]), 114 | WasmValue::decode_to_f64(&binary[4..6]), 115 | WasmValue::decode_to_v128(&binary[6..10]), 116 | ]; 117 | 118 | assert_eq!(values, decoded_values); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/wasi_context.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Intel Corporation. All rights reserved. 3 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | */ 5 | 6 | //! prepare wasi context 7 | 8 | use std::{ffi::c_char, ffi::CString, vec::Vec}; 9 | 10 | #[derive(Debug, Default)] 11 | struct PreOpen { 12 | real_paths: Vec, 13 | mapped_paths: Vec, 14 | } 15 | 16 | #[derive(Debug, Default)] 17 | pub struct WasiCtxBuilder { 18 | pre_open: PreOpen, 19 | allowed_address: Vec, 20 | allowed_dns: Vec, 21 | env: Vec, 22 | // every element is a ptr to an env element 23 | env_cstr_ptrs: Vec<*const c_char>, 24 | args: Vec, 25 | // every element is a ptr to an args element 26 | args_cstr_ptrs: Vec<*const c_char>, 27 | } 28 | 29 | #[derive(Debug, Default)] 30 | pub struct WasiCtx { 31 | pre_open: PreOpen, 32 | allowed_address: Vec, 33 | allowed_dns: Vec, 34 | env: Vec, 35 | env_cstr_ptrs: Vec<*const c_char>, 36 | args: Vec, 37 | args_cstr_ptrs: Vec<*const c_char>, 38 | } 39 | 40 | impl WasiCtxBuilder { 41 | pub fn new() -> WasiCtxBuilder { 42 | WasiCtxBuilder::default() 43 | } 44 | 45 | pub fn build(self) -> WasiCtx { 46 | WasiCtx { 47 | pre_open: self.pre_open, 48 | allowed_address: self.allowed_address, 49 | allowed_dns: self.allowed_dns, 50 | env: self.env, 51 | env_cstr_ptrs: self.env_cstr_ptrs, 52 | args: self.args, 53 | args_cstr_ptrs: self.args_cstr_ptrs, 54 | } 55 | } 56 | 57 | /// set pre-open directories and files, which are part of WASI arguments, for the module. 58 | /// the format of each map entry: :: 59 | /// 60 | /// This function should be called before `Instance::new` 61 | pub fn set_pre_open_path( 62 | mut self, 63 | real_paths: Vec<&str>, 64 | mapped_paths: Vec<&str>, 65 | ) -> WasiCtxBuilder { 66 | self.pre_open.real_paths = real_paths 67 | .iter() 68 | .map(|s| CString::new(s.as_bytes()).unwrap()) 69 | .collect::>(); 70 | 71 | self.pre_open.mapped_paths = mapped_paths 72 | .iter() 73 | .map(|s| CString::new(s.as_bytes()).unwrap()) 74 | .collect::>(); 75 | 76 | self 77 | } 78 | 79 | /// set environment variables, which are part of WASI arguments, for the module 80 | /// 81 | /// This function should be called before `Instance::new` 82 | /// 83 | /// all wasi args of a module will be spread into the environment variables of the module 84 | pub fn set_env_vars(mut self, envs: Vec<&str>) -> WasiCtxBuilder { 85 | self.env = envs 86 | .iter() 87 | .map(|s| CString::new(s.as_bytes()).unwrap()) 88 | .collect::>(); 89 | self.env_cstr_ptrs = self 90 | .env 91 | .iter() 92 | .map(|s| s.as_ptr() as *const c_char) 93 | .collect::>(); 94 | 95 | self 96 | } 97 | 98 | /// set allowed ns , which are part of WASI arguments, for the module 99 | /// 100 | /// This function should be called before `Instance::new` 101 | pub fn set_allowed_dns(mut self, dns: Vec<&str>) -> WasiCtxBuilder { 102 | self.allowed_dns = dns 103 | .iter() 104 | .map(|s| CString::new(s.as_bytes()).unwrap()) 105 | .collect::>(); 106 | 107 | self 108 | } 109 | 110 | /// set allowed ip addresses, which are part of WASI arguments, for the module 111 | /// 112 | /// This function should be called before `Instance::new` 113 | pub fn set_allowed_address(mut self, addresses: Vec<&str>) -> WasiCtxBuilder { 114 | self.allowed_address = addresses 115 | .iter() 116 | .map(|s| CString::new(s.as_bytes()).unwrap()) 117 | .collect::>(); 118 | 119 | self 120 | } 121 | 122 | /// set arguments, which are part of WASI arguments, for the module 123 | /// 124 | /// This function should be called before `Instance::new` 125 | pub fn set_arguments(mut self, args: Vec<&str>) -> WasiCtxBuilder { 126 | self.args = args 127 | .iter() 128 | .map(|s| CString::new(s.as_bytes()).unwrap()) 129 | .collect::>(); 130 | self.args_cstr_ptrs = self 131 | .args 132 | .iter() 133 | .map(|s| s.as_ptr() as *const c_char) 134 | .collect::>(); 135 | 136 | self 137 | } 138 | } 139 | 140 | impl WasiCtx { 141 | pub fn get_preopen_real_paths(&self) -> &Vec { 142 | &self.pre_open.real_paths 143 | } 144 | 145 | pub fn get_preopen_mapped_paths(&self) -> &Vec { 146 | &self.pre_open.mapped_paths 147 | } 148 | 149 | pub fn get_allowed_address(&self) -> &Vec { 150 | &self.allowed_address 151 | } 152 | 153 | pub fn get_allowed_dns(&self) -> &Vec { 154 | &self.allowed_dns 155 | } 156 | 157 | pub fn get_env_vars(&self) -> &Vec { 158 | &self.env 159 | } 160 | 161 | pub fn get_env_vars_ptrs(&self) -> &Vec<*const c_char> { 162 | &self.env_cstr_ptrs 163 | } 164 | 165 | pub fn get_arguments(&self) -> &Vec { 166 | &self.args 167 | } 168 | 169 | pub fn get_arguments_ptrs(&self) -> &Vec<*const c_char> { 170 | &self.args_cstr_ptrs 171 | } 172 | } 173 | 174 | #[cfg(test)] 175 | mod tests { 176 | use super::*; 177 | 178 | #[test] 179 | fn test_wasi_ctx_build() { 180 | let wasi_ctx = WasiCtxBuilder::new() 181 | .set_pre_open_path(vec!["a/b/c"], vec!["/dog/cat/rabbit"]) 182 | .set_allowed_address(vec!["1.2.3.4"]) 183 | .set_allowed_dns(vec![]) 184 | .set_env_vars(vec!["path=/usr/local/bin", "HOME=/home/xxx"]) 185 | .set_arguments(vec!["arg1", "arg2"]) 186 | .build(); 187 | 188 | let mut preopen_iter = wasi_ctx.get_preopen_real_paths().iter(); 189 | assert_eq!(preopen_iter.next().unwrap().to_str().unwrap(), "a/b/c"); 190 | assert_eq!(preopen_iter.next(), None); 191 | 192 | let mut preopen_iter = wasi_ctx.get_preopen_mapped_paths().iter(); 193 | assert_eq!( 194 | preopen_iter.next().unwrap().to_str().unwrap(), 195 | "/dog/cat/rabbit" 196 | ); 197 | assert_eq!(preopen_iter.next(), None); 198 | 199 | let mut allowed_address_iter = wasi_ctx.get_allowed_address().iter(); 200 | assert_eq!( 201 | allowed_address_iter.next().unwrap().to_str().unwrap(), 202 | "1.2.3.4" 203 | ); 204 | assert_eq!(allowed_address_iter.next(), None); 205 | 206 | let mut env_vars_iter = wasi_ctx.get_env_vars().iter(); 207 | assert_eq!( 208 | env_vars_iter.next().unwrap().to_str().unwrap(), 209 | "path=/usr/local/bin" 210 | ); 211 | assert_eq!( 212 | env_vars_iter.next().unwrap().to_str().unwrap(), 213 | "HOME=/home/xxx" 214 | ); 215 | assert_eq!(env_vars_iter.next(), None); 216 | } 217 | } 218 | --------------------------------------------------------------------------------