├── .github ├── release-please │ ├── config.json │ └── manifest.json └── workflows │ ├── ci.yml │ └── release-please.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE.md ├── README.md ├── examples └── hello-world │ ├── Cargo.toml │ └── src │ └── lib.rs ├── rust-toolchain.toml └── src ├── bin ├── cargo-wapm.rs └── cargo-wasmer.rs ├── lib.rs ├── metadata.rs ├── pack.rs └── publish.rs /.github/release-please/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "release-type": "rust", 3 | "packages": { 4 | ".": { 5 | "component": "cargo-wasmer", 6 | "exclude-paths": [ 7 | "examples" 8 | ] 9 | } 10 | }, 11 | "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" 12 | } 13 | -------------------------------------------------------------------------------- /.github/release-please/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.4.0" 3 | } 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | check: 11 | name: Compile and Test 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Setup Rust 16 | uses: dsherret/rust-toolchain-file@v1 17 | - name: Rust Cache 18 | uses: Swatinem/rust-cache@v2 19 | - name: Install Nextest 20 | uses: taiki-e/install-action@nextest 21 | - name: Type Checking 22 | run: cargo check --workspace --verbose --locked 23 | - name: Build 24 | run: cargo build --workspace --verbose --locked 25 | - name: Test 26 | run: cargo nextest run --workspace --verbose --locked 27 | 28 | lints: 29 | name: Linting and Formatting 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v2 33 | - name: Rust Cache 34 | uses: Swatinem/rust-cache@v2 35 | - name: Setup Rust 36 | uses: dsherret/rust-toolchain-file@v1 37 | - name: Check Formatting 38 | run: cargo fmt --all --verbose --check 39 | - name: Clippy 40 | run: cargo clippy --workspace --verbose 41 | 42 | api-docs: 43 | name: Publish API Docs to GitHub Pages 44 | runs-on: ubuntu-latest 45 | steps: 46 | - uses: actions/checkout@v2 47 | - name: Setup Rust 48 | uses: dtolnay/rust-toolchain@nightly 49 | - name: Rust Cache 50 | uses: Swatinem/rust-cache@v2 51 | - name: Generate API docs 52 | run: cargo doc --workspace --verbose --locked 53 | - name: Redirect top-level GitHub Pages 54 | run: 'echo '''' > target/doc/index.html' 55 | shell: bash 56 | - name: Upload API Docs 57 | uses: JamesIves/github-pages-deploy-action@4.1.1 58 | if: github.ref == 'refs/heads/main' 59 | with: 60 | branch: gh-pages 61 | folder: target/doc 62 | 63 | workflow-times: 64 | name: Workflow Timings 65 | runs-on: ubuntu-latest 66 | needs: 67 | - check 68 | steps: 69 | - name: Time Reporter 70 | uses: Michael-F-Bryan/workflow-timer@v0.2.3 71 | with: 72 | token: ${{ secrets.GITHUB_TOKEN }} 73 | jobs: | 74 | Compile and Test 75 | -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | name: Release Please 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: "*" 8 | repository_dispatch: 9 | 10 | env: 11 | RUST_BACKTRACE: 1 12 | 13 | jobs: 14 | release: 15 | name: Create Release 16 | runs-on: ubuntu-latest 17 | concurrency: release-please 18 | steps: 19 | - name: Install release-please 20 | run: npm install --global release-please@15.11 21 | - name: Update the Release PR 22 | run: | 23 | release-please release-pr \ 24 | --debug \ 25 | --token=${{ secrets.RELEASE_PLEASE_GH_TOKEN }} \ 26 | --repo-url=${{ github.repositoryUrl }} \ 27 | --config-file=.github/release-please/config.json \ 28 | --manifest-file=.github/release-please/manifest.json 29 | - name: Publish the GitHub Release 30 | run: | 31 | release-please github-release \ 32 | --debug \ 33 | --token=${{ secrets.RELEASE_PLEASE_GH_TOKEN }} \ 34 | --repo-url=${{ github.repositoryUrl }} \ 35 | --config-file=.github/release-please/config.json \ 36 | --manifest-file=.github/release-please/manifest.json 37 | 38 | publish-to-crates-io: 39 | name: Publish to crates.io (if necessary) 40 | runs-on: ubuntu-latest 41 | needs: 42 | - release 43 | concurrency: release-please-publish-crates-io 44 | steps: 45 | - uses: actions/checkout@v2 46 | - name: Setup Rust 47 | uses: dsherret/rust-toolchain-file@v1 48 | - name: Rust Cache 49 | uses: Swatinem/rust-cache@v2 50 | - name: Install cargo-workspaces 51 | uses: taiki-e/install-action@v2 52 | with: 53 | tool: cargo-workspaces 54 | - name: Publish 55 | run: cargo workspaces publish --from-git --token "${{ secrets.CRATES_IO_TOKEN }}" --yes 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [0.4.0](https://github.com/wasmerio/cargo-wasmer/compare/cargo-wasmer-v0.3.6...cargo-wasmer-v0.4.0) (2023-10-26) 4 | 5 | ### ⚠ BREAKING CHANGES 6 | 7 | - Renamed the `cargo wapm` command to `cargo wasmer` 8 | 9 | ### Features 10 | 11 | - renamed `cargo wapm` command to `cargo wasmer` ([ca2934d](https://github.com/wasmerio/cargo-wasmer/commit/ca2934d5d18f71851e701c888a84aa1dc1327cd2)) 12 | 13 | ### Bug Fixes 14 | 15 | * Added the cargo-wapm executable back in for backwards compatibility ([0cfa867](https://github.com/wasmerio/cargo-wasmer/commit/0cfa867f978e71cce791e3dd4c11f9b66953cba8)) 16 | * Bumped the proc-macro2 version because it used nightly features that no longer exist ([a0982e8](https://github.com/wasmerio/cargo-wasmer/commit/a0982e8773f091b249131712f99f95a126ec9fa7)) 17 | * For backwards compatibility, made sure the publishing will still respect the `[package.metadata.wapm]` table ([099cc36](https://github.com/wasmerio/cargo-wasmer/commit/099cc368ffcf1c1ccd55726460e47152ea26802b)) 18 | -------------------------------------------------------------------------------- /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 = "anyhow" 7 | version = "1.0.69" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" 10 | 11 | [[package]] 12 | name = "autocfg" 13 | version = "1.1.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 16 | 17 | [[package]] 18 | name = "bitflags" 19 | version = "1.3.2" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 22 | 23 | [[package]] 24 | name = "camino" 25 | version = "1.1.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055" 28 | dependencies = [ 29 | "serde", 30 | ] 31 | 32 | [[package]] 33 | name = "cargo-platform" 34 | version = "0.1.2" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" 37 | dependencies = [ 38 | "serde", 39 | ] 40 | 41 | [[package]] 42 | name = "cargo-wasmer" 43 | version = "0.4.0" 44 | dependencies = [ 45 | "anyhow", 46 | "cargo_metadata", 47 | "clap", 48 | "clap-cargo", 49 | "serde", 50 | "toml 0.7.2", 51 | "tracing", 52 | "tracing-subscriber", 53 | "wapm-toml", 54 | ] 55 | 56 | [[package]] 57 | name = "cargo_metadata" 58 | version = "0.15.3" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" 61 | dependencies = [ 62 | "camino", 63 | "cargo-platform", 64 | "semver", 65 | "serde", 66 | "serde_json", 67 | "thiserror", 68 | ] 69 | 70 | [[package]] 71 | name = "cc" 72 | version = "1.0.79" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 75 | 76 | [[package]] 77 | name = "cfg-if" 78 | version = "1.0.0" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 81 | 82 | [[package]] 83 | name = "clap" 84 | version = "4.1.4" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" 87 | dependencies = [ 88 | "bitflags", 89 | "clap_derive", 90 | "clap_lex", 91 | "is-terminal", 92 | "once_cell", 93 | "strsim", 94 | "termcolor", 95 | ] 96 | 97 | [[package]] 98 | name = "clap-cargo" 99 | version = "0.10.0" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "eca953650a7350560b61db95a0ab1d9c6f7b74d146a9e08fb258b834f3cf7e2c" 102 | dependencies = [ 103 | "cargo_metadata", 104 | "clap", 105 | "doc-comment", 106 | ] 107 | 108 | [[package]] 109 | name = "clap_derive" 110 | version = "4.1.0" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" 113 | dependencies = [ 114 | "heck", 115 | "proc-macro-error", 116 | "proc-macro2", 117 | "quote", 118 | "syn", 119 | ] 120 | 121 | [[package]] 122 | name = "clap_lex" 123 | version = "0.3.1" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" 126 | dependencies = [ 127 | "os_str_bytes", 128 | ] 129 | 130 | [[package]] 131 | name = "doc-comment" 132 | version = "0.3.3" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" 135 | 136 | [[package]] 137 | name = "errno" 138 | version = "0.2.8" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 141 | dependencies = [ 142 | "errno-dragonfly", 143 | "libc", 144 | "winapi", 145 | ] 146 | 147 | [[package]] 148 | name = "errno-dragonfly" 149 | version = "0.1.2" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 152 | dependencies = [ 153 | "cc", 154 | "libc", 155 | ] 156 | 157 | [[package]] 158 | name = "half" 159 | version = "1.8.2" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" 162 | 163 | [[package]] 164 | name = "hashbrown" 165 | version = "0.12.3" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 168 | 169 | [[package]] 170 | name = "heck" 171 | version = "0.4.1" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 174 | 175 | [[package]] 176 | name = "hello-world" 177 | version = "0.0.0" 178 | 179 | [[package]] 180 | name = "hermit-abi" 181 | version = "0.3.1" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 184 | 185 | [[package]] 186 | name = "indexmap" 187 | version = "1.9.2" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 190 | dependencies = [ 191 | "autocfg", 192 | "hashbrown", 193 | ] 194 | 195 | [[package]] 196 | name = "io-lifetimes" 197 | version = "1.0.5" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" 200 | dependencies = [ 201 | "libc", 202 | "windows-sys", 203 | ] 204 | 205 | [[package]] 206 | name = "is-terminal" 207 | version = "0.4.3" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" 210 | dependencies = [ 211 | "hermit-abi", 212 | "io-lifetimes", 213 | "rustix", 214 | "windows-sys", 215 | ] 216 | 217 | [[package]] 218 | name = "itoa" 219 | version = "1.0.5" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 222 | 223 | [[package]] 224 | name = "lazy_static" 225 | version = "1.4.0" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 228 | 229 | [[package]] 230 | name = "libc" 231 | version = "0.2.139" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 234 | 235 | [[package]] 236 | name = "linux-raw-sys" 237 | version = "0.1.4" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 240 | 241 | [[package]] 242 | name = "log" 243 | version = "0.4.17" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 246 | dependencies = [ 247 | "cfg-if", 248 | ] 249 | 250 | [[package]] 251 | name = "matchers" 252 | version = "0.1.0" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 255 | dependencies = [ 256 | "regex-automata", 257 | ] 258 | 259 | [[package]] 260 | name = "memchr" 261 | version = "2.5.0" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 264 | 265 | [[package]] 266 | name = "nom8" 267 | version = "0.2.0" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" 270 | dependencies = [ 271 | "memchr", 272 | ] 273 | 274 | [[package]] 275 | name = "nu-ansi-term" 276 | version = "0.46.0" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 279 | dependencies = [ 280 | "overload", 281 | "winapi", 282 | ] 283 | 284 | [[package]] 285 | name = "once_cell" 286 | version = "1.17.0" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" 289 | 290 | [[package]] 291 | name = "os_str_bytes" 292 | version = "6.4.1" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" 295 | 296 | [[package]] 297 | name = "overload" 298 | version = "0.1.1" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 301 | 302 | [[package]] 303 | name = "pin-project-lite" 304 | version = "0.2.9" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 307 | 308 | [[package]] 309 | name = "proc-macro-error" 310 | version = "1.0.4" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 313 | dependencies = [ 314 | "proc-macro-error-attr", 315 | "proc-macro2", 316 | "quote", 317 | "syn", 318 | "version_check", 319 | ] 320 | 321 | [[package]] 322 | name = "proc-macro-error-attr" 323 | version = "1.0.4" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 326 | dependencies = [ 327 | "proc-macro2", 328 | "quote", 329 | "version_check", 330 | ] 331 | 332 | [[package]] 333 | name = "proc-macro2" 334 | version = "1.0.69" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" 337 | dependencies = [ 338 | "unicode-ident", 339 | ] 340 | 341 | [[package]] 342 | name = "quote" 343 | version = "1.0.23" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 346 | dependencies = [ 347 | "proc-macro2", 348 | ] 349 | 350 | [[package]] 351 | name = "regex" 352 | version = "1.7.1" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" 355 | dependencies = [ 356 | "regex-syntax", 357 | ] 358 | 359 | [[package]] 360 | name = "regex-automata" 361 | version = "0.1.10" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 364 | dependencies = [ 365 | "regex-syntax", 366 | ] 367 | 368 | [[package]] 369 | name = "regex-syntax" 370 | version = "0.6.28" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 373 | 374 | [[package]] 375 | name = "rustix" 376 | version = "0.36.8" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" 379 | dependencies = [ 380 | "bitflags", 381 | "errno", 382 | "io-lifetimes", 383 | "libc", 384 | "linux-raw-sys", 385 | "windows-sys", 386 | ] 387 | 388 | [[package]] 389 | name = "ryu" 390 | version = "1.0.12" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 393 | 394 | [[package]] 395 | name = "semver" 396 | version = "1.0.16" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" 399 | dependencies = [ 400 | "serde", 401 | ] 402 | 403 | [[package]] 404 | name = "serde" 405 | version = "1.0.152" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 408 | dependencies = [ 409 | "serde_derive", 410 | ] 411 | 412 | [[package]] 413 | name = "serde_cbor" 414 | version = "0.11.2" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" 417 | dependencies = [ 418 | "half", 419 | "serde", 420 | ] 421 | 422 | [[package]] 423 | name = "serde_derive" 424 | version = "1.0.152" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 427 | dependencies = [ 428 | "proc-macro2", 429 | "quote", 430 | "syn", 431 | ] 432 | 433 | [[package]] 434 | name = "serde_json" 435 | version = "1.0.93" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" 438 | dependencies = [ 439 | "itoa", 440 | "ryu", 441 | "serde", 442 | ] 443 | 444 | [[package]] 445 | name = "serde_spanned" 446 | version = "0.6.1" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" 449 | dependencies = [ 450 | "serde", 451 | ] 452 | 453 | [[package]] 454 | name = "serde_yaml" 455 | version = "0.9.17" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" 458 | dependencies = [ 459 | "indexmap", 460 | "itoa", 461 | "ryu", 462 | "serde", 463 | "unsafe-libyaml", 464 | ] 465 | 466 | [[package]] 467 | name = "sharded-slab" 468 | version = "0.1.4" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 471 | dependencies = [ 472 | "lazy_static", 473 | ] 474 | 475 | [[package]] 476 | name = "smallvec" 477 | version = "1.10.0" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 480 | 481 | [[package]] 482 | name = "strsim" 483 | version = "0.10.0" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 486 | 487 | [[package]] 488 | name = "syn" 489 | version = "1.0.107" 490 | source = "registry+https://github.com/rust-lang/crates.io-index" 491 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 492 | dependencies = [ 493 | "proc-macro2", 494 | "quote", 495 | "unicode-ident", 496 | ] 497 | 498 | [[package]] 499 | name = "termcolor" 500 | version = "1.2.0" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" 503 | dependencies = [ 504 | "winapi-util", 505 | ] 506 | 507 | [[package]] 508 | name = "thiserror" 509 | version = "1.0.38" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" 512 | dependencies = [ 513 | "thiserror-impl", 514 | ] 515 | 516 | [[package]] 517 | name = "thiserror-impl" 518 | version = "1.0.38" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" 521 | dependencies = [ 522 | "proc-macro2", 523 | "quote", 524 | "syn", 525 | ] 526 | 527 | [[package]] 528 | name = "thread_local" 529 | version = "1.1.7" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" 532 | dependencies = [ 533 | "cfg-if", 534 | "once_cell", 535 | ] 536 | 537 | [[package]] 538 | name = "toml" 539 | version = "0.5.11" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" 542 | dependencies = [ 543 | "serde", 544 | ] 545 | 546 | [[package]] 547 | name = "toml" 548 | version = "0.7.2" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" 551 | dependencies = [ 552 | "serde", 553 | "serde_spanned", 554 | "toml_datetime", 555 | "toml_edit", 556 | ] 557 | 558 | [[package]] 559 | name = "toml_datetime" 560 | version = "0.6.1" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" 563 | dependencies = [ 564 | "serde", 565 | ] 566 | 567 | [[package]] 568 | name = "toml_edit" 569 | version = "0.19.3" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "5e6a7712b49e1775fb9a7b998de6635b299237f48b404dde71704f2e0e7f37e5" 572 | dependencies = [ 573 | "indexmap", 574 | "nom8", 575 | "serde", 576 | "serde_spanned", 577 | "toml_datetime", 578 | ] 579 | 580 | [[package]] 581 | name = "tracing" 582 | version = "0.1.37" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 585 | dependencies = [ 586 | "cfg-if", 587 | "pin-project-lite", 588 | "tracing-attributes", 589 | "tracing-core", 590 | ] 591 | 592 | [[package]] 593 | name = "tracing-attributes" 594 | version = "0.1.23" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 597 | dependencies = [ 598 | "proc-macro2", 599 | "quote", 600 | "syn", 601 | ] 602 | 603 | [[package]] 604 | name = "tracing-core" 605 | version = "0.1.30" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 608 | dependencies = [ 609 | "once_cell", 610 | "valuable", 611 | ] 612 | 613 | [[package]] 614 | name = "tracing-log" 615 | version = "0.1.3" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 618 | dependencies = [ 619 | "lazy_static", 620 | "log", 621 | "tracing-core", 622 | ] 623 | 624 | [[package]] 625 | name = "tracing-subscriber" 626 | version = "0.3.16" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" 629 | dependencies = [ 630 | "matchers", 631 | "nu-ansi-term", 632 | "once_cell", 633 | "regex", 634 | "sharded-slab", 635 | "smallvec", 636 | "thread_local", 637 | "tracing", 638 | "tracing-core", 639 | "tracing-log", 640 | ] 641 | 642 | [[package]] 643 | name = "unicode-ident" 644 | version = "1.0.6" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 647 | 648 | [[package]] 649 | name = "unsafe-libyaml" 650 | version = "0.2.5" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" 653 | 654 | [[package]] 655 | name = "valuable" 656 | version = "0.1.0" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 659 | 660 | [[package]] 661 | name = "version_check" 662 | version = "0.9.4" 663 | source = "registry+https://github.com/rust-lang/crates.io-index" 664 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 665 | 666 | [[package]] 667 | name = "wapm-toml" 668 | version = "0.4.0" 669 | source = "registry+https://github.com/rust-lang/crates.io-index" 670 | checksum = "994ef26447f3158955d2e3fca96021d1f1c47b830e2053569177673dca1447a9" 671 | dependencies = [ 672 | "anyhow", 673 | "semver", 674 | "serde", 675 | "serde_cbor", 676 | "serde_json", 677 | "serde_yaml", 678 | "thiserror", 679 | "toml 0.5.11", 680 | ] 681 | 682 | [[package]] 683 | name = "winapi" 684 | version = "0.3.9" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 687 | dependencies = [ 688 | "winapi-i686-pc-windows-gnu", 689 | "winapi-x86_64-pc-windows-gnu", 690 | ] 691 | 692 | [[package]] 693 | name = "winapi-i686-pc-windows-gnu" 694 | version = "0.4.0" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 697 | 698 | [[package]] 699 | name = "winapi-util" 700 | version = "0.1.5" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 703 | dependencies = [ 704 | "winapi", 705 | ] 706 | 707 | [[package]] 708 | name = "winapi-x86_64-pc-windows-gnu" 709 | version = "0.4.0" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 712 | 713 | [[package]] 714 | name = "windows-sys" 715 | version = "0.45.0" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 718 | dependencies = [ 719 | "windows-targets", 720 | ] 721 | 722 | [[package]] 723 | name = "windows-targets" 724 | version = "0.42.1" 725 | source = "registry+https://github.com/rust-lang/crates.io-index" 726 | checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" 727 | dependencies = [ 728 | "windows_aarch64_gnullvm", 729 | "windows_aarch64_msvc", 730 | "windows_i686_gnu", 731 | "windows_i686_msvc", 732 | "windows_x86_64_gnu", 733 | "windows_x86_64_gnullvm", 734 | "windows_x86_64_msvc", 735 | ] 736 | 737 | [[package]] 738 | name = "windows_aarch64_gnullvm" 739 | version = "0.42.1" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 742 | 743 | [[package]] 744 | name = "windows_aarch64_msvc" 745 | version = "0.42.1" 746 | source = "registry+https://github.com/rust-lang/crates.io-index" 747 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 748 | 749 | [[package]] 750 | name = "windows_i686_gnu" 751 | version = "0.42.1" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 754 | 755 | [[package]] 756 | name = "windows_i686_msvc" 757 | version = "0.42.1" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 760 | 761 | [[package]] 762 | name = "windows_x86_64_gnu" 763 | version = "0.42.1" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 766 | 767 | [[package]] 768 | name = "windows_x86_64_gnullvm" 769 | version = "0.42.1" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 772 | 773 | [[package]] 774 | name = "windows_x86_64_msvc" 775 | version = "0.42.1" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 778 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cargo-wasmer" 3 | version = "0.4.0" 4 | authors = [ 5 | "Michael-F-Bryan ", 6 | "Hammer of the Gods ", 7 | "Wasmer Engineering Team ", 8 | "Rudra ", 9 | ] 10 | categories = ["command-line-utilities", "development-tools::cargo-plugins"] 11 | description = "Publish a Rust crate to the WebAssembly Package Manager." 12 | edition = "2021" 13 | keywords = ["wasmer", "WebAssembly", "publish", "registry"] 14 | license = "Apache-2.0" 15 | readme = "README.md" 16 | repository = "https://github.com/wasmerio/cargo-wapm" 17 | rust-version = "1.65" 18 | default-run = "cargo-wasmer" 19 | 20 | [dependencies] 21 | anyhow = "1" 22 | cargo_metadata = "0.15" 23 | clap = { version = "4", features = ["derive", "env"] } 24 | clap-cargo = { version = "0.10.0", features = ["cargo_metadata"] } 25 | serde = "1" 26 | toml = "0.7" 27 | tracing = { version = "0.1.34", features = ["attributes"] } 28 | tracing-subscriber = { version = "0.3.11", features = ["env-filter"] } 29 | wapm-toml = "0.4" 30 | 31 | [profile.release] 32 | strip = "debuginfo" 33 | 34 | [workspace] 35 | members = [".", "examples/hello-world"] 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cargo Wasmer 2 | 3 | [![Continuous Integration](https://github.com/wasmerio/cargo-wasmer/actions/workflows/ci.yml/badge.svg)](https://github.com/wasmerio/cargo-wasmer/actions/workflows/ci.yml) 4 | 5 | ([API Docs]) 6 | 7 | A `cargo` sub-command for publishing Rust crates to the [Wasmer package 8 | registry](https://wasmer.io/). 9 | 10 | If you want a deeper understanding of how `cargo wasmer` works, check out 11 | [*Announcing Cargo WAPM*][announcement]. 12 | 13 | > **Note:** This command used to be called `cargo wapm` back when `wapm` was a 14 | > separate command. Most interactions with the Wasmer registry have been merged 15 | > into the `wasmer` CLI nowadays, so the command was renamed to `cargo wasmer`. 16 | 17 | ## Getting Started 18 | 19 | You can install the `cargo wasmer` command from crates.io. 20 | 21 | ```console 22 | $ cargo install cargo-wasmer --locked 23 | ``` 24 | 25 | You will also need to [install the `wasmer` CLI][install-wasmer] and 26 | [authenticate][auth] with the registry. 27 | 28 | ```console 29 | $ curl https://get.wasmer.io -sSfL | sh 30 | $ wasmer login 31 | Username: my-user 32 | Password: **** 33 | ``` 34 | 35 | Once you have done that, open the `Cargo.toml` for your crate and add a metadata 36 | section to tell `cargo wasmer` how your crate will be packaged. 37 | 38 | ```toml 39 | # Cargo.toml 40 | [package.metadata.wasmer] 41 | namespace = "Michael-F-Bryan" 42 | abi = "none" 43 | ``` 44 | 45 | The `abi` argument tells `cargo wasmer` which target to use when compiling to 46 | WebAssembly. 47 | 48 | | ABI | Target Triple | 49 | | ------------ | ------------------------ | 50 | | `none` | `wasm32-unknown-unknown` | 51 | | `wasi` | `wasm32-wasi` | 52 | | `emscripten` | `wasm32-emscripten` | 53 | 54 | You also need to add `cdylib` to the `crate-type` list. You should also add the 55 | `rlib` crate type if other crates depend on this crate (integration tests, doc 56 | tests, examples, etc.). 57 | 58 | ```toml 59 | # Cargo.toml 60 | [lib] 61 | crate-type = ["cdylib", "rlib"] 62 | ``` 63 | 64 | Now the `Cargo.toml` is up to date, we can do a dry run to make sure everything 65 | is correct. 66 | 67 | ```console 68 | $ cd examples/hello-world/ 69 | $ cargo wasmer --dry-run 70 | 2022-05-03T17:33:31.929353Z INFO publish: cargo_wasmer: Publishing dry_run=true pkg="hello-world" 71 | Successfully published package `Michael-F-Bryan/hello-world@0.1.0` 72 | [INFO] Publish succeeded, but package was not published because it was run in dry-run mode 73 | 2022-05-03T17:33:32.366576Z INFO publish: cargo_wasmer: Published! pkg="hello-world" 74 | ``` 75 | 76 | We can see that some files have been written to the `target/wasmer/` folder. 77 | 78 | ```console 79 | $ tree ../../target/wasmer 80 | ../../target/wasmer 81 | └── hello-world 82 | ├── hello_world.wasm 83 | ├── LICENSE_MIT.md 84 | ├── README.md 85 | └── wasmer.toml 86 | 87 | 1 directory, 4 files 88 | 89 | $ cat ../../target/wasmer/hello-world/wasmer.toml 90 | [package] 91 | name = "Michael-F-Bryan/hello-world" 92 | version = "0.1.0" 93 | description = "A dummy package." 94 | license-file = "LICENSE_MIT.md" 95 | readme = "README.md" 96 | 97 | [[module]] 98 | name = "hello-world" 99 | source = "hello_world.wasm" 100 | abi = "none" 101 | ``` 102 | 103 | If you are happy with the generated files, remove the `--dry-run` command to 104 | publish the crate for real. 105 | 106 | The `cargo wasmer` command doesn't take care of any version bumping, so the 107 | `version` being published is read directly from `Cargo.toml`. Check out [the 108 | `cargo release` tool](https://crates.io/crates/cargo-release) if you something 109 | that can manage routine release tasks like bumping versions, tagging commits, or 110 | updating your changelog. 111 | 112 | ## Workspaces 113 | 114 | Normally, the `cargo wasmer` command will only publish the crate in the current 115 | directory. 116 | 117 | However, by using the `--workspace` flag you can publish every crate in the 118 | current workspace as long as they have a `[package.metadata.wasmer]` section in 119 | their `Cargo.toml`. The `--exclude` argument lets you skip a particular crate 120 | while publishing. 121 | 122 | ### Releasing 123 | 124 | This repository uses [Release Please][release-please] to automate a lot of the 125 | work around creating releases. 126 | 127 | Every time a commit following the [Conventional Commit Style][conv] is merged 128 | into `main`, the [`release-please.yml`](.github/workflows/release-please.yml) 129 | workflow will run and update the "Release PR" to reflect the new changes. 130 | 131 | For commits that just fix bugs (i.e. the message starts with `"fix: "`), the 132 | associated crate will receive a changelog entry and a patch version bump. 133 | Similarly, adding a new feature (i.e. `"feat:"`) does a minor version bump and 134 | adding breaking changes (i.e. `"fix!:"` or `"feat!:"`) will result in a major 135 | version bump. 136 | 137 | When the release PR is merged, the updated changelogs and bumped version numbers 138 | will be merged into the `main` branch, the `release-please.yml` workflow will 139 | automatically generate GitHub Releases, and CI will publish the crate if 140 | necessary. 141 | 142 | TL;DR: 143 | 144 | 1. Use [Conventional Commit Messages][conv] whenever you make a noteworthy change 145 | 2. Merge the release PR when ready to release 146 | 3. Let the automation do everything else 147 | 148 | ## License 149 | 150 | This project is licensed under the Apache License, Version 2.0 151 | ([LICENSE-APACHE](LICENSE.md) or http://www.apache.org/licenses/LICENSE-2.0). 152 | 153 | It is recommended to always use [cargo-crev][crev] to verify the 154 | trustworthiness of each of your dependencies, including this one. 155 | 156 | ### Contribution 157 | 158 | Unless you explicitly state otherwise, any contribution intentionally 159 | submitted for inclusion in the work by you, as defined in the Apache-2.0 160 | license, shall be dual licensed as above, without any additional terms or 161 | conditions. 162 | 163 | The intent of this crate is to be free of soundness bugs. The developers will 164 | do their best to avoid them, and welcome help in analysing and fixing them. 165 | 166 | [announcement]: https://adventures.michaelfbryan.com/posts/announcing-cargo-wapm/ 167 | [API Docs]: https://wasmerio.github.io/cargo-wasmer 168 | [auth]: https://docs.wasmer.io/registry/get-started#log-in-into-wasmer 169 | [conv]: https://www.conventionalcommits.org/en/v1.0.0/ 170 | [crev]: https://github.com/crev-dev/cargo-crev 171 | [install-wasmer]: https://docs.wasmer.io/install 172 | [release-please]: https://github.com/googleapis/release-please 173 | -------------------------------------------------------------------------------- /examples/hello-world/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello-world" 3 | version = "0.0.0" 4 | edition = "2021" 5 | description = "A dummy package." 6 | readme = "../../README.md" 7 | license = "Apache-2.0" 8 | publish = false 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | 14 | [package.metadata.wapm] 15 | namespace = "Michael-F-Bryan" 16 | abi = "wasi" 17 | 18 | [lib] 19 | crate-type = ["cdylib", "rlib"] 20 | -------------------------------------------------------------------------------- /examples/hello-world/src/lib.rs: -------------------------------------------------------------------------------- 1 | /// Add two numbers. 2 | #[no_mangle] 3 | pub extern "C" fn add(a: i32, b: i32) -> i32 { 4 | a + b 5 | } 6 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | components = ["rustfmt", "clippy"] 3 | channel = "1.65" 4 | -------------------------------------------------------------------------------- /src/bin/cargo-wapm.rs: -------------------------------------------------------------------------------- 1 | // Make sure we generate a cargo-wapm executable for backwards compatibility. 2 | 3 | include!("./cargo-wasmer.rs"); 4 | -------------------------------------------------------------------------------- /src/bin/cargo-wasmer.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Error; 2 | use cargo_wasmer::Publish; 3 | use clap::Parser; 4 | use tracing_subscriber::EnvFilter; 5 | 6 | fn main() -> Result<(), Error> { 7 | if std::env::var_os("RUST_LOG").is_none() { 8 | std::env::set_var("RUST_LOG", "warn,cargo_wasmer=info"); 9 | } 10 | 11 | tracing_subscriber::fmt() 12 | .with_env_filter(EnvFilter::from_default_env()) 13 | .compact() 14 | .init(); 15 | 16 | let args = Cargo::parse(); 17 | tracing::debug!(?args, "Started"); 18 | 19 | match args { 20 | Cargo::Wasmer(p) => p.execute(), 21 | } 22 | } 23 | 24 | #[derive(Debug, Parser)] 25 | #[clap(name = "cargo", bin_name = "cargo", version, author)] 26 | enum Cargo { 27 | #[clap(alias = "wapm")] 28 | Wasmer(Publish), 29 | } 30 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub extern crate clap_cargo; 2 | 3 | pub mod metadata; 4 | mod pack; 5 | mod publish; 6 | 7 | pub use crate::{pack::Pack, publish::Publish}; 8 | -------------------------------------------------------------------------------- /src/metadata.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, path::PathBuf}; 2 | 3 | use wapm_toml::Bindings; 4 | 5 | #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] 6 | #[serde(rename_all = "kebab-case")] 7 | pub struct MetadataTable { 8 | #[serde(alias = "wapm")] 9 | pub wasmer: Wasmer, 10 | } 11 | 12 | #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] 13 | #[serde(rename_all = "kebab-case")] 14 | pub struct Wasmer { 15 | pub namespace: String, 16 | pub package: Option, 17 | pub wasmer_extra_flags: Option, 18 | pub abi: wapm_toml::Abi, 19 | #[serde(default, skip_serializing_if = "Option::is_none")] 20 | pub fs: Option>, 21 | pub bindings: Option, 22 | } 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use serde::Deserialize; 27 | use wapm_toml::{WaiBindings, WitBindings}; 28 | 29 | use super::*; 30 | 31 | #[test] 32 | fn parse_wai_bindings() { 33 | let table = toml::toml! { 34 | [wasmer] 35 | namespace = "wasmer" 36 | abi = "none" 37 | bindings = { wai-version = "0.1.0", exports = "hello-world.wai" } 38 | }; 39 | let should_be = MetadataTable { 40 | wasmer: Wasmer { 41 | namespace: "wasmer".to_string(), 42 | package: None, 43 | wasmer_extra_flags: None, 44 | abi: wapm_toml::Abi::None, 45 | fs: None, 46 | bindings: Some(Bindings::Wai(WaiBindings { 47 | exports: Some("hello-world.wai".into()), 48 | imports: Vec::new(), 49 | wai_version: "0.1.0".parse().unwrap(), 50 | })), 51 | }, 52 | }; 53 | 54 | let got = MetadataTable::deserialize(table).unwrap(); 55 | 56 | assert_eq!(got, should_be); 57 | } 58 | 59 | #[test] 60 | fn parse_wit_bindings() { 61 | let table = toml::toml! { 62 | [wasmer] 63 | namespace = "wasmer" 64 | abi = "none" 65 | bindings = { wit-bindgen = "0.1.0", wit-exports = "hello-world.wit" } 66 | }; 67 | let should_be = MetadataTable { 68 | wasmer: Wasmer { 69 | namespace: "wasmer".to_string(), 70 | package: None, 71 | wasmer_extra_flags: None, 72 | abi: wapm_toml::Abi::None, 73 | fs: None, 74 | bindings: Some(Bindings::Wit(WitBindings { 75 | wit_bindgen: "0.1.0".parse().unwrap(), 76 | wit_exports: "hello-world.wit".into(), 77 | })), 78 | }, 79 | }; 80 | 81 | let got = MetadataTable::deserialize(table).unwrap(); 82 | 83 | assert_eq!(got, should_be); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/pack.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | path::{Path, PathBuf}, 3 | process::Command, 4 | }; 5 | 6 | use anyhow::{Context, Error}; 7 | use cargo_metadata::{Metadata, Package, Target}; 8 | use clap::Parser; 9 | use serde::Deserialize; 10 | use wapm_toml::{Manifest, Module}; 11 | 12 | use crate::metadata::MetadataTable; 13 | 14 | /// Compile a Rust crate to a WAPM package. 15 | /// 16 | /// # Examples 17 | /// 18 | /// ```rust,no_run 19 | /// use clap::Parser; 20 | /// use cargo_wasmer::Pack; 21 | /// 22 | /// # fn main() -> Result<(), anyhow::Error> { 23 | /// let pack = Pack::parse(); 24 | /// let meta = pack.metadata()?; 25 | /// 26 | /// for pkg in pack.resolve_packages(&meta) { 27 | /// let dest = pack.generate_wapm_package(pkg, meta.target_directory.as_ref())?; 28 | /// println!("Wrote the WAPM package for {} to {}", pkg.name, dest.display()); 29 | /// } 30 | /// # Ok(()) 31 | /// # } 32 | /// ``` 33 | #[derive(Debug, Default, Parser)] 34 | #[non_exhaustive] 35 | pub struct Pack { 36 | #[command(flatten)] 37 | pub manifest: clap_cargo::Manifest, 38 | #[command(flatten)] 39 | pub workspace: clap_cargo::Workspace, 40 | #[command(flatten)] 41 | pub features: clap_cargo::Features, 42 | /// Compile in debug mode. 43 | #[clap(long)] 44 | pub debug: bool, 45 | /// Where to save the compiled WAPM package(s) 46 | #[clap(long, env)] 47 | pub out_dir: Option, 48 | } 49 | 50 | impl Pack { 51 | /// Use the `cargo metadata` subcommand to learn about the workspace. 52 | #[tracing::instrument(skip_all)] 53 | pub fn metadata(&self) -> Result { 54 | let mut cmd = self.manifest.metadata(); 55 | self.features.forward_metadata(&mut cmd); 56 | let meta = cmd.exec()?; 57 | 58 | Ok(meta) 59 | } 60 | 61 | /// Figure out which packages the user wants to pack. 62 | #[tracing::instrument(skip_all)] 63 | pub fn resolve_packages<'meta>(&self, metadata: &'meta Metadata) -> Vec<&'meta Package> { 64 | let (packages, _excluded) = self.workspace.partition_packages(metadata); 65 | packages 66 | } 67 | 68 | /// Compile a crate to a Wasmer package and save it on disk. 69 | #[tracing::instrument(skip_all)] 70 | pub fn generate_wasmer_package( 71 | &self, 72 | pkg: &Package, 73 | target_dir: &Path, 74 | ) -> Result { 75 | let dest = self.out_dir(pkg, target_dir); 76 | tracing::debug!(dest=%dest.display(), "Generating the Wasmer package"); 77 | 78 | if dest.exists() { 79 | tracing::debug!( 80 | dir=%dest.display(), 81 | "Removing previous generated package", 82 | ); 83 | std::fs::remove_dir_all(&dest) 84 | .with_context(|| format!("Unable to remove \"{}\"", dest.display()))?; 85 | } 86 | 87 | let target = determine_target(pkg)?; 88 | let manifest: Manifest = generate_manifest(pkg, target)?; 89 | let modules = manifest 90 | .module 91 | .as_deref() 92 | .expect("We will always compile one module"); 93 | let wasm_path = self.compile_to_wasm(pkg, target_dir, &modules[0], target)?; 94 | pack(&dest, &manifest, &wasm_path, pkg)?; 95 | 96 | Ok(dest) 97 | } 98 | 99 | /// Figure which directory to save the compiled artefacts to. 100 | /// 101 | /// This will default to using `$target_dir/wapm/`, but will try to 102 | /// use the output directory if one was specified. Namespacing using the 103 | /// package name is added when the build would generate multiple WAPM 104 | /// packages. 105 | fn out_dir(&self, pkg: &Package, target_dir: &Path) -> PathBuf { 106 | let dir = self 107 | .out_dir 108 | .clone() 109 | .unwrap_or_else(|| target_dir.join("wasmer")); 110 | 111 | if self.workspace.all || self.workspace.workspace || !self.workspace.package.is_empty() { 112 | // Add some sort of namespacing so package directories don't collide. 113 | dir.join(&pkg.name) 114 | } else { 115 | dir 116 | } 117 | } 118 | 119 | fn compile_to_wasm( 120 | &self, 121 | pkg: &Package, 122 | target_dir: &Path, 123 | module: &Module, 124 | target: &Target, 125 | ) -> Result { 126 | let mut cmd = Command::new(cargo_bin()); 127 | let target_triple = match module.abi { 128 | wapm_toml::Abi::Emscripten => "wasm32-unknown-emscripten", 129 | wapm_toml::Abi::Wasi => "wasm32-wasi", 130 | wapm_toml::Abi::None | wapm_toml::Abi::WASM4 => "wasm32-unknown-unknown", 131 | }; 132 | 133 | cmd.arg("build") 134 | .arg("--quiet") 135 | .args(["--manifest-path", pkg.manifest_path.as_str()]) 136 | .args(["--target", target_triple]); 137 | 138 | let clap_cargo::Features { 139 | all_features, 140 | no_default_features, 141 | ref features, 142 | .. 143 | } = self.features; 144 | if all_features { 145 | cmd.arg("--all-features"); 146 | } 147 | if no_default_features { 148 | cmd.arg("--no-default-features"); 149 | } 150 | if !features.is_empty() { 151 | cmd.arg(format!("--features={}", self.features.features.join(","))); 152 | } 153 | 154 | if !self.debug { 155 | cmd.arg("--release"); 156 | } 157 | 158 | tracing::debug!(?cmd, "Compiling the WebAssembly package"); 159 | 160 | let status = cmd.status().with_context(|| { 161 | format!( 162 | "Unable to start \"{}\". Is it installed?", 163 | cmd.get_program().to_string_lossy() 164 | ) 165 | })?; 166 | 167 | if !status.success() { 168 | match status.code() { 169 | Some(code) => anyhow::bail!("Cargo exited unsuccessfully with exit code {}", code), 170 | None => anyhow::bail!("Cargo exited unsuccessfully"), 171 | } 172 | } 173 | 174 | let binary = target_dir 175 | .join(target_triple) 176 | .join(if self.debug { "debug" } else { "release" }) 177 | .join(wasm_binary_name(target)) 178 | .with_extension("wasm"); 179 | 180 | anyhow::ensure!( 181 | binary.exists(), 182 | "Expected \"{}\" to exist", 183 | binary.display() 184 | ); 185 | 186 | Ok(binary) 187 | } 188 | } 189 | 190 | fn determine_target(pkg: &Package) -> Result<&Target, Error> { 191 | let candidates: Vec<_> = pkg 192 | .targets 193 | .iter() 194 | .filter(|t| is_webassembly_library(t) || t.is_bin()) 195 | .collect(); 196 | match *candidates.as_slice() { 197 | [single_target] => Ok(single_target), 198 | [] => anyhow::bail!( 199 | "The {} package doesn't contain any binaries or \"cdylib\" libraries", 200 | pkg.name 201 | ), 202 | [..] => anyhow::bail!( 203 | "Unable to decide what to publish. Expected one executable or \"cdylib\" library, but found {}", 204 | candidates.iter() 205 | .map(|t| format!("{} ({:?})", t.name, t.kind)) 206 | .collect::>() 207 | .join(", ") 208 | ), 209 | } 210 | } 211 | 212 | fn is_webassembly_library(target: &Target) -> bool { 213 | target.kind.iter().any(|k| k == "cdylib") 214 | } 215 | 216 | #[tracing::instrument(skip_all)] 217 | fn pack(dest: &Path, manifest: &Manifest, wasm_path: &Path, pkg: &Package) -> Result<(), Error> { 218 | std::fs::create_dir_all(dest) 219 | .with_context(|| format!("Unable to create the \"{}\" directory", dest.display()))?; 220 | 221 | let manifest_path = dest.join("wasmer.toml"); 222 | let toml = toml::to_string(manifest).context("Unable to serialize the wasmer.toml")?; 223 | tracing::debug!( 224 | path = %manifest_path.display(), 225 | bytes = toml.len(), 226 | "Writing manifest", 227 | ); 228 | std::fs::write(&manifest_path, toml.as_bytes()) 229 | .with_context(|| format!("Unable to write to \"{}\"", manifest_path.display()))?; 230 | 231 | let new_wasm_path = dest.join(wasm_path.file_name().unwrap()); 232 | copy(wasm_path, new_wasm_path)?; 233 | 234 | let base_dir = pkg.manifest_path.parent().unwrap(); 235 | 236 | if let Some(license_file) = pkg.license_file.as_ref() { 237 | if let Some(filename) = license_file.file_name() { 238 | let dest = dest.join(filename); 239 | let license_file = base_dir.join(license_file); 240 | copy(license_file, dest)?; 241 | } 242 | } 243 | 244 | if let Some(readme) = pkg.readme.as_ref() { 245 | if let Some(filename) = readme.file_name() { 246 | let dest = dest.join(filename); 247 | let readme = base_dir.join(readme); 248 | copy(readme, dest)?; 249 | } 250 | } 251 | 252 | for module in manifest.module.as_deref().unwrap_or_default() { 253 | if let Some(bindings) = &module.bindings { 254 | let base_dir = base_dir.as_std_path(); 255 | for path in bindings.referenced_files(base_dir)? { 256 | // Note: we want to maintain the same location relative to the 257 | // Cargo.toml file 258 | let relative_path = path.strip_prefix(base_dir).with_context(|| { 259 | format!( 260 | "\"{}\" should be inside \"{}\"", 261 | path.display(), 262 | base_dir.display(), 263 | ) 264 | })?; 265 | let dest = dest.join(relative_path); 266 | copy(path, dest)?; 267 | } 268 | } 269 | } 270 | 271 | Ok(()) 272 | } 273 | 274 | fn copy(from: impl AsRef, to: impl AsRef) -> Result<(), Error> { 275 | let from = from.as_ref(); 276 | let to = to.as_ref(); 277 | 278 | tracing::debug!( 279 | from = %from.display(), 280 | to = %to.display(), 281 | "Copying file", 282 | ); 283 | std::fs::copy(from, to).with_context(|| { 284 | format!( 285 | "Unable to copy \"{}\" to \"{}\"", 286 | from.display(), 287 | to.display() 288 | ) 289 | })?; 290 | 291 | Ok(()) 292 | } 293 | 294 | fn wasm_binary_name(target: &Target) -> String { 295 | // Because reasons, `rustc` will leave dashes in a binary's name but 296 | // libraries are converted to underscores. 297 | if target.is_bin() { 298 | target.name.clone() 299 | } else { 300 | target.name.replace('-', "_") 301 | } 302 | } 303 | 304 | fn cargo_bin() -> String { 305 | std::env::var("CARGO").unwrap_or_else(|_| String::from("cargo")) 306 | } 307 | 308 | #[tracing::instrument(skip_all)] 309 | fn generate_manifest(pkg: &Package, target: &Target) -> Result { 310 | tracing::trace!(?target, "Generating manifest"); 311 | 312 | let MetadataTable { 313 | wasmer: 314 | crate::metadata::Wasmer { 315 | wasmer_extra_flags, 316 | fs, 317 | abi, 318 | namespace, 319 | package, 320 | bindings, 321 | }, 322 | } = MetadataTable::deserialize(&pkg.metadata) 323 | .context("Unable to deserialize the [metadata] table")?; 324 | 325 | match pkg.description.as_deref() { 326 | Some("") => anyhow::bail!("The \"description\" field in your Cargo.toml is empty"), 327 | Some(_) => {} 328 | None => anyhow::bail!("The \"description\" field in your Cargo.toml wasn't set"), 329 | } 330 | 331 | let package_name = format!("{}/{}", namespace, package.as_deref().unwrap_or(&pkg.name)); 332 | 333 | let module = Module { 334 | name: target.name.clone(), 335 | source: PathBuf::from(wasm_binary_name(target)).with_extension("wasm"), 336 | abi, 337 | bindings, 338 | interfaces: None, 339 | kind: None, 340 | }; 341 | 342 | let command = if target.is_bin() { 343 | let cmd = wapm_toml::Command::V1(wapm_toml::CommandV1 { 344 | module: target.name.clone(), 345 | name: target.name.clone(), 346 | package: Some(package_name.clone()), 347 | main_args: None, 348 | }); 349 | Some(vec![cmd]) 350 | } else { 351 | None 352 | }; 353 | 354 | // Note: the readme and license will be hoisted to the top-level directory 355 | let license_file = pkg 356 | .license_file() 357 | .as_ref() 358 | .and_then(|p| p.file_name()) 359 | .map(PathBuf::from); 360 | let readme = pkg 361 | .readme() 362 | .as_ref() 363 | .and_then(|p| p.file_name()) 364 | .map(PathBuf::from); 365 | 366 | Ok(Manifest { 367 | package: wapm_toml::Package { 368 | name: package_name, 369 | version: pkg.version.clone(), 370 | description: pkg.description.clone().unwrap_or_default(), 371 | license: pkg.license.clone(), 372 | license_file, 373 | readme, 374 | repository: pkg.repository.clone(), 375 | homepage: pkg.homepage.clone(), 376 | wasmer_extra_flags, 377 | disable_command_rename: false, 378 | rename_commands_to_raw_command_name: false, 379 | }, 380 | module: Some(vec![module]), 381 | command, 382 | fs, 383 | dependencies: None, 384 | base_directory_path: PathBuf::new(), 385 | }) 386 | } 387 | -------------------------------------------------------------------------------- /src/publish.rs: -------------------------------------------------------------------------------- 1 | use std::{path::Path, process::Command}; 2 | 3 | use anyhow::{Context, Error}; 4 | use cargo_metadata::Package; 5 | use clap::Parser; 6 | 7 | use crate::Pack; 8 | 9 | /// Publish a crate to the WebAssembly Package Manager. 10 | #[derive(Debug, Parser)] 11 | #[clap(author, about, version)] 12 | pub struct Publish { 13 | /// Build the package, but don't publish it. 14 | #[clap(short, long, env)] 15 | pub dry_run: bool, 16 | #[clap(flatten)] 17 | pub pack: Pack, 18 | } 19 | 20 | impl Publish { 21 | /// Run the [`Publish`] command. 22 | pub fn execute(self) -> Result<(), Error> { 23 | let metadata = self 24 | .pack 25 | .metadata() 26 | .context("Unable to parse the workspace's metadata")?; 27 | 28 | let packages_to_publish = self.pack.resolve_packages(&metadata); 29 | 30 | for pkg in packages_to_publish { 31 | // We only want to publish things that have a 32 | // [package.metadata.wasmer] table 33 | if !has_package_metadata_table(pkg, "wasmer") 34 | && !has_package_metadata_table(pkg, "wapm") 35 | { 36 | tracing::info!( 37 | pkg.name = pkg.name, 38 | "No [package.metadata.wasmer] found in the package. Skipping..." 39 | ); 40 | continue; 41 | } 42 | 43 | self.publish(pkg, metadata.target_directory.as_ref()) 44 | .with_context(|| format!("Unable to publish \"{}\"", pkg.name))?; 45 | } 46 | 47 | Ok(()) 48 | } 49 | 50 | #[tracing::instrument(fields(pkg = pkg.name.as_str()), skip_all)] 51 | fn publish(&self, pkg: &Package, target_dir: &Path) -> Result<(), Error> { 52 | tracing::info!(dry_run = self.dry_run, "Getting ready to publish"); 53 | 54 | let dest = self.pack.generate_wasmer_package(pkg, target_dir)?; 55 | upload_to_wasmer(&dest, self.dry_run)?; 56 | 57 | tracing::info!("Published!"); 58 | 59 | Ok(()) 60 | } 61 | } 62 | 63 | fn has_package_metadata_table(pkg: &Package, table_name: &str) -> bool { 64 | pkg.metadata 65 | .as_object() 66 | .map(|obj| obj.contains_key(table_name)) 67 | .unwrap_or(false) 68 | } 69 | 70 | #[tracing::instrument(skip_all)] 71 | fn upload_to_wasmer(dir: &Path, dry_run: bool) -> Result<(), Error> { 72 | let mut cmd = Command::new("wasmer"); 73 | 74 | cmd.arg("publish"); 75 | if dry_run { 76 | cmd.arg("--dry-run"); 77 | } 78 | 79 | cmd.current_dir(dir); 80 | 81 | tracing::debug!(?cmd, "Publishing with the wasmer CLI"); 82 | 83 | let status = cmd.status().with_context(|| { 84 | format!( 85 | "Unable to start \"{}\". Is it installed?", 86 | cmd.get_program().to_string_lossy() 87 | ) 88 | })?; 89 | 90 | if !status.success() { 91 | match status.code() { 92 | Some(code) => { 93 | anyhow::bail!( 94 | "The wasmer CLI exited unsuccessfully with exit code {}", 95 | code 96 | ) 97 | } 98 | None => anyhow::bail!("The wasmer CLI exited unsuccessfully"), 99 | } 100 | } 101 | 102 | Ok(()) 103 | } 104 | --------------------------------------------------------------------------------