diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0f15dd59eb..89218e0422 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,6 +75,10 @@ jobs: entries: ${{ steps.set-matrix.outputs.entries }} steps: - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.2" + bundler-cache: true - run: rake ci:pin_build_manifest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -112,18 +116,33 @@ jobs: load: true cache-from: type=gha cache-to: type=gha,mode=max - - uses: ruby/setup-ruby@v1 - with: - ruby-version: "3.2" - bundler-cache: true - - run: ./bin/setup + - name: Setup builder container + run: | + docker run -dit -v "$GITHUB_WORKSPACE:/home/me/build" -w /home/me/build \ + -e "ENABLE_GITHUB_ACTIONS_MARKUP=true" \ + -e "RUBYWASM_UID=$(id -u)" -e "RUBYWASM_GID=$(id -g)" \ + -e "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" \ + --name builder \ + ${{ steps.builder-image.outputs.imageid }} /bin/sh + echo 'docker exec -u me builder "$@"' > ./build-exec + chmod +x ./build-exec + - run: ./build-exec bundle config set --local without check + - run: ./build-exec ./bin/setup + - run: ./build-exec bundle exec rake compile - name: Pre-release configuration - run: rake ${{ matrix.entry.prerelease }}[${{ inputs.prerel_name }}] + run: ./build-exec bundle exec rake ${{ matrix.entry.prerelease }}[${{ inputs.prerel_name }}] if: ${{ inputs.prerel_name != '' && matrix.entry.prerelease != '' }} - name: rake ${{ matrix.entry.task }} - run: docker run -v "$GITHUB_WORKSPACE:/home/me/build" -w /home/me/build -e "ENABLE_GITHUB_ACTIONS_MARKUP=true" -e "RUBYWASM_UID=$(id -u)" -e "RUBYWASM_GID=$(id -g)" -e "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" ${{ steps.builder-image.outputs.imageid }} rake --verbose ${{ matrix.entry.task }} + run: ./build-exec rake --verbose ${{ matrix.entry.task }} + - uses: ruby/setup-ruby@v1 + if: ${{ matrix.entry.test != '' }} + with: + ruby-version: "3.2" + bundler-cache: false - name: rake ${{ matrix.entry.test }} - run: rake ${{ matrix.entry.test }} + run: | + bundle install --with=check --without=development + rake ${{ matrix.entry.test }} if: ${{ matrix.entry.test != '' }} - uses: actions/upload-artifact@v4 if: ${{ matrix.entry.artifact }} diff --git a/.gitignore b/.gitignore index faf9b126b6..49fde32b63 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,10 @@ dist /build /rubies /release +/tmp +/target /Gemfile.lock +/lib/ruby_wasm/ruby_wasm.so .cache compile_commands.json @@ -11,3 +14,5 @@ compile_commands.json html build_manifest.json + +vendor/bundle diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1abe34f3d7..8d6d1a3d15 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,11 +46,11 @@ To select a build profile, see [profiles section in README](https://github.com/r ```console # Build only a specific combination of ruby version, profile, and target -$ rake build:head-wasm32-unknown-wasi-full-js +$ rake build:head-wasm32-unknown-wasi-full # Clean up the build directory -$ rake build:head-wasm32-unknown-wasi-full-js:clean +$ rake build:head-wasm32-unknown-wasi-full:clean # Force to re-execute "make install" -$ rake build:head-wasm32-unknown-wasi-full-js:remake +$ rake build:head-wasm32-unknown-wasi-full:remake # Output is in the `rubies` directory $ tree -L 3 rubies/head-wasm32-unknown-wasi-full-js diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..d546e2afdd --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2452 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "ahash" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "ambient-authority" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8ad6edb4840b78c5c3d88de606b22252d552b55f3a4699fbb10fc070ec3049" + +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + +[[package]] +name = "async-trait" +version = "0.1.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.43", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.69.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" +dependencies = [ + "bitflags 2.4.1", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.43", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cap-fs-ext" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc48200a1a0fa6fba138b1802ad7def18ec1cdd92f7b2a04e21f1bd887f7b9" +dependencies = [ + "cap-primitives 1.0.15", + "cap-std 1.0.15", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "cap-primitives" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb8fca3e81fae1d91a36e9784ca22a39ef623702b5f7904d89dc31f10184a178" +dependencies = [ + "ambient-authority 0.0.1", + "errno 0.2.8", + "fs-set-times 0.15.0", + "io-extras 0.13.2", + "io-lifetimes 0.5.3", + "ipnet", + "maybe-owned", + "rustix 0.33.7", + "winapi", + "winapi-util", + "winx 0.31.0", +] + +[[package]] +name = "cap-primitives" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b6df5b295dca8d56f35560be8c391d59f0420f72e546997154e24e765e6451" +dependencies = [ + "ambient-authority 0.0.2", + "fs-set-times 0.19.2", + "io-extras 0.17.4", + "io-lifetimes 1.0.11", + "ipnet", + "maybe-owned", + "rustix 0.37.27", + "windows-sys 0.48.0", + "winx 0.35.1", +] + +[[package]] +name = "cap-rand" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25555efacb0b5244cf1d35833d55d21abc916fff0eaad254b8e2453ea9b8ab" +dependencies = [ + "ambient-authority 0.0.2", + "rand", +] + +[[package]] +name = "cap-std" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2247568946095c7765ad2b441a56caffc08027734c634a6d5edda648f04e32eb" +dependencies = [ + "cap-primitives 0.24.4", + "io-extras 0.13.2", + "io-lifetimes 0.5.3", + "ipnet", + "rustix 0.33.7", +] + +[[package]] +name = "cap-std" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3373a62accd150b4fcba056d4c5f3b552127f0ec86d3c8c102d60b978174a012" +dependencies = [ + "cap-primitives 1.0.15", + "io-extras 0.17.4", + "io-lifetimes 1.0.11", + "rustix 0.37.27", +] + +[[package]] +name = "cap-time-ext" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e95002993b7baee6b66c8950470e59e5226a23b3af39fc59c47fe416dd39821a" +dependencies = [ + "cap-primitives 1.0.15", + "once_cell", + "rustix 0.37.27", + "winx 0.35.1", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-bforest" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "182b82f78049f54d3aee5a19870d356ef754226665a695ce2fcdd5d55379718e" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c027bf04ecae5b048d3554deb888061bc26f426afff47bf06d6ac933dce0a6" +dependencies = [ + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli", + "hashbrown 0.13.2", + "log", + "regalloc2", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "649f70038235e4c81dba5680d7e5ae83e1081f567232425ab98b55b03afd9904" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a1d1c5ee2611c6a0bdc8d42d5d3dc5ce8bf53a8040561e26e88b9b21f966417" + +[[package]] +name = "cranelift-control" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da66a68b1f48da863d1d53209b8ddb1a6236411d2d72a280ffa8c2f734f7219e" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd897422dbb66621fa558f4d9209875530c53e3c8f4b13b2849fbb667c431a6" +dependencies = [ + "serde", +] + +[[package]] +name = "cranelift-frontend" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05db883114c98cfcd6959f72278d2fec42e01ea6a6982cfe4f20e88eebe86653" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84559de86e2564152c87e299c8b2559f9107e9c6d274b24ebeb04fb0a5f4abf8" + +[[package]] +name = "cranelift-native" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f40b57f187f0fe1ffaf281df4adba2b4bc623a0f6651954da9f3c184be72761" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-wasm" +version = "0.96.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3eab6084cc789b9dd0b1316241efeb2968199fee709f4bb4fe0fb0923bb468b" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "itertools", + "log", + "smallvec", + "wasmparser 0.103.0", + "wasmtime-types", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "env_logger" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fd-lock" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" +dependencies = [ + "cfg-if", + "rustix 0.38.28", + "windows-sys 0.52.0", +] + +[[package]] +name = "file-per-thread-logger" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f2e425d9790201ba4af4630191feac6dcc98765b118d4d18e91d23c2353866" +dependencies = [ + "env_logger", + "log", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs-set-times" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df62ee66ee2d532ea8d567b5a3f0d03ecd64636b98bad5be1e93dcc918b92aa" +dependencies = [ + "io-lifetimes 0.5.3", + "rustix 0.33.7", + "winapi", +] + +[[package]] +name = "fs-set-times" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d167b646a876ba8fda6b50ac645cfd96242553cbaf0ca4fccaa39afcbf0801f" +dependencies = [ + "io-lifetimes 1.0.11", + "rustix 0.38.28", + "windows-sys 0.48.0", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "fxprof-processed-profile" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" +dependencies = [ + "bitflags 2.4.1", + "debugid", + "fxhash", + "serde", + "serde_json", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "io-extras" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c937cc9891c12eaa8c63ad347e4a288364b1328b924886970b47a14ab8f8f8" +dependencies = [ + "io-lifetimes 0.5.3", + "winapi", +] + +[[package]] +name = "io-extras" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde93d48f0d9277f977a333eca8313695ddd5301dc96f7e02aeddcb0dd99096f" +dependencies = [ + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "io-lifetimes" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec58677acfea8a15352d42fc87d11d63596ade9239e0a7c9352914417515dbe6" + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.3", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is-terminal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +dependencies = [ + "hermit-abi 0.3.3", + "rustix 0.38.28", + "windows-sys 0.52.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "ittapi" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a5c0b993601cad796222ea076565c5d9f337d35592f8622c753724f06d7271" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7b5e473765060536a660eed127f758cf1a810c73e49063264959c60d1727d9" +dependencies = [ + "cc", +] + +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5284f00d480e1c39af34e72f8ad60b94f47007e3481cd3b731c1d67190ddc7b7" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "magnus" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4778544796676e8428e9c622460ebf284bea52d8b10db3aeb449d8b5e61b3a13" +dependencies = [ + "magnus-macros", + "rb-sys", + "rb-sys-env", + "seq-macro", +] + +[[package]] +name = "magnus-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5968c820e2960565f647819f5928a42d6e874551cab9d88d75e3e0660d7f71e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.43", +] + +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix 0.38.28", +] + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "object" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +dependencies = [ + "crc32fast", + "hashbrown 0.13.2", + "indexmap", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pkg-config" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "pulldown-cmark" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" +dependencies = [ + "bitflags 1.3.2", + "memchr", + "unicase", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rb-sys" +version = "0.9.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b780e6858b0b0eced1d55d0f097c024b77a37b41f83bd35341130f78e37c51" +dependencies = [ + "rb-sys-build", +] + +[[package]] +name = "rb-sys-build" +version = "0.9.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44957a3bc513dad1b0f20bdd0ee3b82e729a59da44086a6b40d8bc71958a6db8" +dependencies = [ + "bindgen", + "lazy_static", + "proc-macro2", + "quote", + "regex", + "shell-words", + "syn 2.0.43", +] + +[[package]] +name = "rb-sys-env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb" + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regalloc2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a52e724646c6c0800fc456ec43b4165d2f91fba88ceaca06d9e0b400023478" +dependencies = [ + "hashbrown 0.13.2", + "log", + "rustc-hash", + "slice-group-by", + "smallvec", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "ruby_wasm" +version = "0.0.0" +dependencies = [ + "magnus", + "wasi-cap-std-sync", + "wasi-vfs-cli", + "wasmtime-wasi", + "wizer 3.0.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.33.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938a344304321a9da4973b9ff4f9f8db9caf4597dfd9dda6a60b523340a0fff0" +dependencies = [ + "bitflags 1.3.2", + "errno 0.2.8", + "io-lifetimes 0.5.3", + "itoa", + "libc", + "linux-raw-sys 0.0.42", + "once_cell", + "winapi", +] + +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno 0.3.8", + "io-lifetimes 1.0.11", + "itoa", + "libc", + "linux-raw-sys 0.3.8", + "once_cell", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags 2.4.1", + "errno 0.3.8", + "libc", + "linux-raw-sys 0.4.12", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "seq-macro" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.43", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs", +] + +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-interface" +version = "0.25.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10081a99cbecbc363d381b9503563785f0b02735fccbb0d4c1a2cb3d39f7e7fe" +dependencies = [ + "bitflags 2.4.1", + "cap-fs-ext", + "cap-std 1.0.15", + "fd-lock", + "io-lifetimes 2.0.3", + "rustix 0.38.28", + "windows-sys 0.48.0", + "winx 0.36.3", +] + +[[package]] +name = "target-lexicon" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" + +[[package]] +name = "termcolor" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.43", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.43", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi-cap-std-sync" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d29c5da3b5cfc9212a7fa824224875cb67fb89d2a8392db655e4c59b8ab2ae7" +dependencies = [ + "anyhow", + "async-trait", + "cap-fs-ext", + "cap-rand", + "cap-std 1.0.15", + "cap-time-ext", + "fs-set-times 0.19.2", + "io-extras 0.17.4", + "io-lifetimes 1.0.11", + "is-terminal", + "once_cell", + "rustix 0.37.27", + "system-interface", + "tracing", + "wasi-common", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasi-common" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8bd905dcec1448664bf63d42d291cbae0feeea3ad41631817b8819e096d76bd" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "cap-rand", + "cap-std 1.0.15", + "io-extras 0.17.4", + "log", + "rustix 0.37.27", + "thiserror", + "tracing", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasi-vfs-cli" +version = "0.4.0" +source = "git+https://github.com/kateinoigakukun/wasi-vfs/?rev=b1e4e5d9cd6322e8745e67c092b495973835a94f#b1e4e5d9cd6322e8745e67c092b495973835a94f" +dependencies = [ + "anyhow", + "structopt", + "wasm-encoder 0.38.1", + "wasmparser 0.106.0", + "wizer 3.0.1", +] + +[[package]] +name = "wasm-encoder" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83c94f464d50e31da425794a02da1a82d4b96a657dcb152a6664e8aa915be517" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasmparser" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c437373cac5ea84f1113d648d51f71751ffbe3d90c00ae67618cf20d0b5ee7b" +dependencies = [ + "indexmap", + "url", +] + +[[package]] +name = "wasmparser" +version = "0.106.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d014e33793cab91655fa6349b0bc974984de106b2e0f6b0dfe6f6594b260624d" +dependencies = [ + "indexmap", + "url", +] + +[[package]] +name = "wasmtime" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634357e8668774b24c80b210552f3f194e2342a065d6d83845ba22c5817d0770" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "bumpalo", + "cfg-if", + "fxprof-processed-profile", + "indexmap", + "libc", + "log", + "object", + "once_cell", + "paste", + "psm", + "rayon", + "serde", + "serde_json", + "target-lexicon", + "wasmparser 0.103.0", + "wasmtime-cache", + "wasmtime-component-macro", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit", + "wasmtime-runtime", + "wat", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d33c73c24ce79b0483a3b091a9acf88871f4490b88998e8974b22236264d304c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-cache" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107809b2d9f5b2fd3ddbaddb3bb92ff8048b62f4030debf1408119ffd38c6cb" +dependencies = [ + "anyhow", + "base64", + "bincode", + "directories-next", + "file-per-thread-logger", + "log", + "rustix 0.37.27", + "serde", + "sha2", + "toml", + "windows-sys 0.48.0", + "zstd", +] + +[[package]] +name = "wasmtime-component-macro" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ba489850d9c91c6c5b9e1696ee89e7a69d9796236a005f7e9131b6746e13b6" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasmtime-component-util", + "wasmtime-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-component-util" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fa88f9e77d80f828c9d684741a9da649366c6d1cceb814755dd9cab7112d1d1" + +[[package]] +name = "wasmtime-cranelift" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5800616a28ed6bd5e8b99ea45646c956d798ae030494ac0689bc3e45d3b689c1" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli", + "log", + "object", + "target-lexicon", + "thiserror", + "wasmparser 0.103.0", + "wasmtime-cranelift-shared", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-cranelift-shared" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e4030b959ac5c5d6ee500078977e813f8768fa2b92fc12be01856cd0c76c55" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-native", + "gimli", + "object", + "target-lexicon", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-environ" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec815d01a8d38aceb7ed4678f9ba551ae6b8a568a63810ac3ad9293b0fd01c8" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli", + "indexmap", + "log", + "object", + "serde", + "target-lexicon", + "thiserror", + "wasmparser 0.103.0", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-fiber" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c5127908fdf720614891ec741c13dd70c844e102caa393e2faca1ee68e9bfb" +dependencies = [ + "cc", + "cfg-if", + "rustix 0.37.27", + "wasmtime-asm-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-jit" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2712eafe829778b426cad0e1769fef944898923dd29f0039e34e0d53ba72b234" +dependencies = [ + "addr2line", + "anyhow", + "bincode", + "cfg-if", + "cpp_demangle", + "gimli", + "ittapi", + "log", + "object", + "rustc-demangle", + "serde", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fb78eacf4a6e47260d8ef8cc81ea8ddb91397b2e848b3fb01567adebfe89b5" +dependencies = [ + "object", + "once_cell", + "rustix 0.37.27", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1364900b05f7d6008516121e8e62767ddb3e176bdf4c84dfa85da1734aeab79" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a16ffe4de9ac9669175c0ea5c6c51ffc596dfb49320aaa6f6c57eff58cef069" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "indexmap", + "libc", + "log", + "mach", + "memfd", + "memoffset", + "paste", + "rand", + "rustix 0.37.27", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit-debug", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-types" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19961c9a3b04d5e766875a5c467f6f5d693f508b3e81f8dc4a1444aa94f041c9" +dependencies = [ + "cranelift-entity", + "serde", + "thiserror", + "wasmparser 0.103.0", +] + +[[package]] +name = "wasmtime-wasi" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21080ff62878f1d7c53d9571053dbe96552c0f982f9f29eac65ea89974fabfd7" +dependencies = [ + "anyhow", + "libc", + "wasi-cap-std-sync", + "wasi-common", + "wasmtime", + "wiggle", +] + +[[package]] +name = "wasmtime-wit-bindgen" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "421f0d16cc5c612b35ae53a0be3d3124c72296f18e5be3468263c745d56d37ab" +dependencies = [ + "anyhow", + "heck 0.4.1", + "wit-parser", +] + +[[package]] +name = "wast" +version = "35.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68" +dependencies = [ + "leb128", +] + +[[package]] +name = "wast" +version = "69.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ee37317321afde358e4d7593745942c48d6d17e0e6e943704de9bbee121e7a" +dependencies = [ + "leb128", + "memchr", + "unicode-width", + "wasm-encoder 0.38.1", +] + +[[package]] +name = "wat" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeb338ee8dee4d4cd05e6426683f21c5087dc7cfc8903e839ccf48d43332da3c" +dependencies = [ + "wast 69.0.1", +] + +[[package]] +name = "wiggle" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b34e40b7b17a920d03449ca78b0319984379eed01a9a11c1def9c3d3832d85a" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 1.3.2", + "thiserror", + "tracing", + "wasmtime", + "wiggle-macro", +] + +[[package]] +name = "wiggle-generate" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eefda132eaa84fe5f15d23a55a912f8417385aee65d0141d78a3b65e46201ed" +dependencies = [ + "anyhow", + "heck 0.4.1", + "proc-macro2", + "quote", + "shellexpand", + "syn 1.0.109", + "witx", +] + +[[package]] +name = "wiggle-macro" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ca1a344a0ba781e2a94b27be5bb78f23e43d52336bd663b810d49d7189ad334" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wiggle-generate", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winx" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d5973cb8cd94a77d03ad7e23bbe14889cb29805da1cec0e4aff75e21aebded" +dependencies = [ + "bitflags 1.3.2", + "io-lifetimes 0.5.3", + "winapi", +] + +[[package]] +name = "winx" +version = "0.35.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c52a121f0fbf9320d5f2a9a5d82f6cb7557eda5e8b47fc3e7f359ec866ae960" +dependencies = [ + "bitflags 1.3.2", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags 2.4.1", + "windows-sys 0.52.0", +] + +[[package]] +name = "wit-parser" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca2581061573ef6d1754983d7a9b3ed5871ef859d52708ea9a0f5af32919172" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "pulldown-cmark", + "unicode-xid", + "url", +] + +[[package]] +name = "witx" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" +dependencies = [ + "anyhow", + "log", + "thiserror", + "wast 35.0.2", +] + +[[package]] +name = "wizer" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdbf85c6302a99e5c9d15655abd804c0e204a278fdb62c1e53a37ba4f3550b8b" +dependencies = [ + "anyhow", + "cap-std 0.24.4", + "log", + "rayon", + "wasi-cap-std-sync", + "wasm-encoder 0.28.0", + "wasmparser 0.106.0", + "wasmtime", + "wasmtime-wasi", +] + +[[package]] +name = "wizer" +version = "3.0.1" +source = "git+https://github.com/bytecodealliance/wizer.git?rev=v3.0.1#a0125eb591a77bbf61af15d4f8675243a5651229" +dependencies = [ + "anyhow", + "cap-std 0.24.4", + "log", + "rayon", + "wasi-cap-std-sync", + "wasm-encoder 0.28.0", + "wasmparser 0.106.0", + "wasmtime", + "wasmtime-wasi", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.43", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..3719c31f51 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +# This Cargo.toml is here to let externals tools (IDEs, etc.) know that this is +# a Rust project. Your extensions dependencies should be added to the Cargo.toml +# in the ext/ directory. + +[workspace] +members = ["./ext/ruby_wasm"] +resolver = "2" diff --git a/Gemfile b/Gemfile index bb52083b48..b1f12da929 100644 --- a/Gemfile +++ b/Gemfile @@ -2,9 +2,16 @@ source "https://rubygems.org" +gemspec + group :development do gem "rake" - gem "syntax_tree", "~> 3.5" + gem "rake-compiler" + gem "rb_sys", "~> 0.9.63" +end + +group :check do gem "webrick" + gem "syntax_tree", "~> 3.5" gem "steep" end diff --git a/Rakefile b/Rakefile index fb1655fdc6..268f3b7e2f 100644 --- a/Rakefile +++ b/Rakefile @@ -5,106 +5,42 @@ require "open-uri" $LOAD_PATH << File.join(File.dirname(__FILE__), "lib") require "ruby_wasm/rake_task" +require "ruby_wasm/packager" Dir.glob("tasks/**.rake").each { |f| import f } -BUILD_SOURCES = { - "head" => { - type: "github", - repo: "ruby/ruby", - rev: "master", - patches: Dir["./patches/*.patch"].map { |p| File.expand_path(p) } - }, - "3.3" => { - type: "tarball", - url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.0.tar.gz" - }, - "3.2" => { - type: "tarball", - url: "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.2.tar.gz" - } -} - -# Respect revisions specified in build_manifest.json, which is usually generated on GitHub Actions. -if File.exist?("build_manifest.json") - begin - manifest = JSON.parse(File.read("build_manifest.json")) - manifest["ruby_revisions"].each do |name, rev| - BUILD_SOURCES[name][:rev] = rev - end - rescue StandardError - $stderr.puts "Failed to load build_manifest.json" - end -end - -FULL_EXTS = - "bigdecimal,cgi/escape,continuation,coverage,date,dbm,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,fiber,gdbm,json,json/generator,json/parser,nkf,objspace,pathname,psych,racc/cparse,rbconfig/sizeof,ripper,stringio,strscan,monitor,zlib,openssl" - -BUILD_PROFILES = { - "minimal" => { - debug: false, - default_exts: "", - user_exts: [] - }, - "minimal-debug" => { - debug: true, - default_exts: "", - user_exts: [] - }, - "full" => { - debug: false, - default_exts: FULL_EXTS, - user_exts: [] - }, - "full-debug" => { - debug: true, - default_exts: FULL_EXTS, - user_exts: [] - }, - "full-js-debug" => { - debug: true, - default_exts: FULL_EXTS, - user_exts: %w[js witapi] - } -} +BUILD_SOURCES = %w[3.3 3.2 head] +BUILD_PROFILES = %w[full minimal] BUILDS = - %w[wasm32-unknown-wasi wasm32-unknown-emscripten] - .product(BUILD_SOURCES.keys, BUILD_PROFILES.keys) - .select do |target, _, profile_name| - if target == "wasm32-unknown-emscripten" - # Builds only full for Emscripten since minimal, js, debug - # builds are rarely used with Emscripten. - next profile_name == "full" - end - next true - end - .map { |t, s, p| { src: s, target: t, profile: p } } + BUILD_SOURCES + .product(BUILD_PROFILES) + .map { |src, profile| [src, "wasm32-unknown-wasi", profile] } + + BUILD_SOURCES.map { |src| [src, "wasm32-unknown-emscripten", "full"] } NPM_PACKAGES = [ { name: "ruby-head-wasm-emscripten", - build: "head-wasm32-unknown-emscripten-full", + ruby_version: "head", + gemfile: nil, target: "wasm32-unknown-emscripten" }, - { - name: "ruby-wasm-wasi", - build: "head-wasm32-unknown-wasi-full-js-debug", - target: "wasm32-unknown-wasi" - }, { name: "ruby-head-wasm-wasi", - build: "head-wasm32-unknown-wasi-full-js-debug", + ruby_version: "head", + gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile", target: "wasm32-unknown-wasi" }, { name: "ruby-3.3-wasm-wasi", - build: "3.3-wasm32-unknown-wasi-full-js-debug", + ruby_version: "3.3", + gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile", target: "wasm32-unknown-wasi" }, { name: "ruby-3.2-wasm-wasi", - build: "3.2-wasm32-unknown-wasi-full-js-debug", + ruby_version: "3.2", + gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile", target: "wasm32-unknown-wasi" } ] @@ -117,46 +53,71 @@ STANDALONE_PACKAGES = [ LIB_ROOT = File.dirname(__FILE__) TOOLCHAINS = {} +BUILDS + .map { |_, target, _| target } + .uniq + .each do |target| + build_dir = File.join(LIB_ROOT, "build") + toolchain = RubyWasm::Toolchain.get(target, build_dir) + TOOLCHAINS[toolchain.name] = toolchain + end + +class BuildTask < Struct.new(:name, :target, :build_command) + def ruby_cache_key + return @key if @key + require "open3" + cmd = build_command + ["--print-ruby-cache-key"] + stdout, status = Open3.capture2(*cmd) + unless status.success? + raise "Command failed with status (#{status.exitstatus}): #{cmd.join ""}" + end + require "json" + @key = JSON.parse(stdout) + end + + def hexdigest + ruby_cache_key["hexdigest"] + end + def artifact + ruby_cache_key["artifact"] + end +end namespace :build do BUILD_TASKS = - BUILDS.map do |params| - name = "#{params[:src]}-#{params[:target]}-#{params[:profile]}" - source = BUILD_SOURCES[params[:src]].merge(name: params[:src]) - profile = BUILD_PROFILES[params[:profile]] - options = { - src: source, - target: params[:target], - default_exts: profile[:default_exts] - } - debug = profile[:debug] - RubyWasm::BuildTask.new(name, **options) do |t| - if debug - t.crossruby.debugflags = %w[-g] - t.crossruby.wasmoptflags = %w[-O3 -g] - t.crossruby.ldflags = %w[ - -Xlinker - --stack-first - -Xlinker - -z - -Xlinker - stack-size=16777216 - ] - else - t.crossruby.debugflags = %w[-g0] - t.crossruby.ldflags = %w[-Xlinker -zstack-size=16777216] + BUILDS.map do |src, target, profile| + name = "#{src}-#{target}-#{profile}" + + build_command = [ + "exe/rbwasm", + "build", + "--ruby-version", + src, + "--target", + target, + "--build-profile", + profile, + "--disable-gems", + "-o", + "/dev/null" + ] + desc "Cross-build Ruby for #{target}" + task name do + sh *build_command + end + namespace name do + task :remake do + sh *build_command, "--remake" end - - toolchain = t.toolchain - t.crossruby.user_exts = - profile[:user_exts].map do |ext| - srcdir = File.join(LIB_ROOT, "ext", ext) - RubyWasm::CrossRubyExtProduct.new(srcdir, toolchain) - end - unless TOOLCHAINS.key? toolchain.name - TOOLCHAINS[toolchain.name] = toolchain + task :reconfigure do + sh *build_command, "--reconfigure" + end + task :clean do + sh *build_command, "--clean" end end + + BuildTask.new(name, target, build_command) end desc "Clean build directories" diff --git a/Steepfile b/Steepfile index 98977dcd8d..6bb7851cc5 100644 --- a/Steepfile +++ b/Steepfile @@ -14,6 +14,11 @@ target :lib do library "uri" library "shellwords" library "io-console" + library "optparse" + library "json" + library "logger" + library "pathname" + library "forwardable" configure_code_diagnostics(D::Ruby.default) end diff --git a/bin/setup b/bin/setup index ffa93c6bcc..b98faf9dbc 100755 --- a/bin/setup +++ b/bin/setup @@ -3,5 +3,8 @@ set -euo pipefail IFS=$'\n\t' set -vx -bundle install +root="$(cd "$(dirname "$0")/.." && pwd)" + +env BUNDLE_GEMFILE="$root/Gemfile" bundle install +env BUNDLE_GEMFILE="$root/packages/npm-packages/ruby-wasm-wasi/Gemfile" bundle install npm ci diff --git a/builders/wasm32-unknown-emscripten/Dockerfile b/builders/wasm32-unknown-emscripten/Dockerfile index 35148ac156..0bd16e0cd5 100644 --- a/builders/wasm32-unknown-emscripten/Dockerfile +++ b/builders/wasm32-unknown-emscripten/Dockerfile @@ -4,16 +4,36 @@ ARG NODE_MAJOR_VERSION=20 RUN set -eux; \ apt-get update; \ - apt-get install ruby bison make autoconf git curl build-essential libyaml-dev zlib1g-dev gosu -y; \ apt-get install -y ca-certificates curl gnupg; \ mkdir -p /etc/apt/keyrings; \ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR_VERSION.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list; \ apt-get update; \ - apt-get install nodejs -y; \ + apt-get install ruby ruby-dev ruby-bundler nodejs \ + bison make autoconf git curl build-essential \ + libyaml-dev zlib1g-dev gosu \ + libclang-13-dev -y; \ apt-get clean; \ rm -r /var/lib/apt/lists/* +# Prefer apt-installed nodejs instead of emsdk's old one. +ENV PATH=/usr/bin:$PATH + +ENV RUSTUP_HOME=/usr/local/rustup \ + CARGO_HOME=/usr/local/cargo \ + PATH=/usr/local/cargo/bin:$PATH \ + RUST_VERSION=1.74 + +RUN set -eux pipefail; \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ + sh -s -- -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION; \ + chmod -R a+w $RUSTUP_HOME $CARGO_HOME + +ENV BUNDLE_PATH=/usr/local/gems +RUN set -eux; \ + mkdir -p $BUNDLE_PATH; \ + chmod -R 777 $BUNDLE_PATH + COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/builders/wasm32-unknown-wasi/Dockerfile b/builders/wasm32-unknown-wasi/Dockerfile index 270d6e0056..a02cd36a7e 100644 --- a/builders/wasm32-unknown-wasi/Dockerfile +++ b/builders/wasm32-unknown-wasi/Dockerfile @@ -5,13 +5,15 @@ ARG NODE_MAJOR_VERSION=20 RUN set -eux; \ apt-get update; \ - apt-get install ruby bison make autoconf git curl build-essential libyaml-dev zlib1g-dev gosu -y; \ apt-get install -y ca-certificates curl gnupg; \ mkdir -p /etc/apt/keyrings; \ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR_VERSION.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list; \ apt-get update; \ - apt-get install nodejs -y; \ + apt-get install ruby ruby-dev ruby-bundler nodejs \ + bison make autoconf git curl build-essential \ + libyaml-dev zlib1g-dev gosu \ + libclang-13-dev -y; \ apt-get clean; \ rm -r /var/lib/apt/lists/* @@ -21,6 +23,21 @@ RUN set -eux pipefail; \ unzip wasi-preset-args-x86_64-unknown-linux-gnu.zip; \ mv wasi-preset-args /usr/local/bin/wasi-preset-args +ENV RUSTUP_HOME=/usr/local/rustup \ + CARGO_HOME=/usr/local/cargo \ + PATH=/usr/local/cargo/bin:$PATH \ + RUST_VERSION=1.74 + +RUN set -eux pipefail; \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ + sh -s -- -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION; \ + chmod -R a+w $RUSTUP_HOME $CARGO_HOME + +ENV BUNDLE_PATH=/usr/local/gems +RUN set -eux; \ + mkdir -p $BUNDLE_PATH; \ + chmod -R 777 $BUNDLE_PATH + COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/exe/rbwasm b/exe/rbwasm new file mode 100755 index 0000000000..484ebea4dc --- /dev/null +++ b/exe/rbwasm @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby + +$LOAD_PATH << File.join(__dir__, "../lib") +require "ruby_wasm" +require "ruby_wasm/cli" + +RubyWasm::CLI.new(stdout: $stdout, stderr: $stderr).run(ARGV) diff --git a/ext/extinit.c.erb b/ext/extinit.c.erb index 2d74013839..8fab120a7f 100644 --- a/ext/extinit.c.erb +++ b/ext/extinit.c.erb @@ -14,7 +14,8 @@ end exts = ARGV c_src = ERB.new(DATA.read).result -IO.popen("#{@cc} -c -xc - -o #{@o}", "w") {|f| f << c_src } +IO.popen([@cc, "-c", "-xc", "-", "-o", @o], "w") {|f| f << c_src } +exit $?.exitstatus __END__ #define init(func, name) { \ @@ -26,6 +27,6 @@ void ruby_init_ext(const char *name, void (*init)(void)); void Init_extra_exts(void) { <% exts.each do |ext| %> - init(<%= "Init_#{ext}" %>, "<%= ext %>"); + init(<%= "Init_#{File.basename ext}" %>, "<%= ext %>"); <% end %> } diff --git a/ext/ruby_wasm/Cargo.toml b/ext/ruby_wasm/Cargo.toml new file mode 100644 index 0000000000..82672798e6 --- /dev/null +++ b/ext/ruby_wasm/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "ruby_wasm" +version = "0.0.0" +edition = "2021" +authors = ["Yuta Saito "] +license = "MIT" +publish = false + +[lib] +crate-type = ["cdylib"] + +[dependencies] +magnus = "0.6.2" +wizer = "3.0.0" +wasmtime-wasi = "9.0.4" +wasi-cap-std-sync = "9.0.4" +wasi-vfs-cli = { git = "https://github.com/kateinoigakukun/wasi-vfs/", rev = "b1e4e5d9cd6322e8745e67c092b495973835a94f" } diff --git a/ext/ruby_wasm/extconf.rb b/ext/ruby_wasm/extconf.rb new file mode 100644 index 0000000000..48b4f12841 --- /dev/null +++ b/ext/ruby_wasm/extconf.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +require "mkmf" +require "rb_sys/mkmf" + +create_rust_makefile("ruby_wasm/ruby_wasm") diff --git a/ext/ruby_wasm/src/lib.rs b/ext/ruby_wasm/src/lib.rs new file mode 100644 index 0000000000..cd907aa22f --- /dev/null +++ b/ext/ruby_wasm/src/lib.rs @@ -0,0 +1,69 @@ +use std::path::PathBuf; + +use magnus::{ + eval, exception, function, method, + prelude::*, + value::{self, InnerValue}, + wrap, Error, ExceptionClass, RModule, Ruby, +}; +use wizer::Wizer; + +static RUBY_WASM: value::Lazy = + value::Lazy::new(|ruby| ruby.define_module("RubyWasmExt").unwrap()); + +fn preinit(core_module: Vec) -> Result, Error> { + let rbwasm_error = eval("RubyWasmExt::Error")?; + let rbwasm_error = ExceptionClass::from_value(rbwasm_error).unwrap(); + let mut wizer = Wizer::new(); + wizer + .wasm_bulk_memory(true) + .inherit_stdio(true) + .inherit_env(true) + .allow_wasi(true) + .map_err(|e| Error::new(rbwasm_error, format!("failed to create wizer: {}", e)))?; + + wizer + .run(&core_module) + .map_err(|e| Error::new(rbwasm_error, format!("failed to run wizer: {}", e))) +} + +struct WasiVfsInner { + map_dirs: Vec<(PathBuf, PathBuf)>, +} + +#[wrap(class = "RubyWasmExt::WasiVfs")] +struct WasiVfs(std::cell::RefCell); + +impl WasiVfs { + fn new() -> Self { + Self(std::cell::RefCell::new(WasiVfsInner { map_dirs: vec![] })) + } + + fn map_dir(&self, guest_dir: String, host_dir: String) { + self.0.borrow_mut().map_dirs.push((guest_dir.into(), host_dir.into())); + } + + fn pack(&self, wasm_bytes: Vec) -> Result, Error> { + let output_bytes = wasi_vfs_cli::pack(&wasm_bytes, self.0.borrow().map_dirs.clone()).map_err(|e| { + Error::new( + exception::standard_error(), + format!("failed to pack wasi vfs: {}", e), + ) + })?; + Ok(output_bytes) + } +} + +#[magnus::init] +fn init(ruby: &Ruby) -> Result<(), Error> { + let module = RUBY_WASM.get_inner_with(ruby); + module.define_error("Error", exception::standard_error())?; + + module.define_singleton_method("preinitialize", function!(preinit, 1))?; + + let wasi_vfs = module.define_class("WasiVfs", ruby.class_object())?; + wasi_vfs.define_singleton_method("new", function!(WasiVfs::new, 0))?; + wasi_vfs.define_method("map_dir", method!(WasiVfs::map_dir, 2))?; + wasi_vfs.define_method("pack", method!(WasiVfs::pack, 1))?; + Ok(()) +} diff --git a/lib/ruby_wasm.rb b/lib/ruby_wasm.rb new file mode 100644 index 0000000000..fb94e0478a --- /dev/null +++ b/lib/ruby_wasm.rb @@ -0,0 +1,33 @@ +require "logger" + +require_relative "ruby_wasm/version" +require_relative "ruby_wasm/util" +require_relative "ruby_wasm/build" +require_relative "ruby_wasm/packager" +require_relative "ruby_wasm/packager/file_system" +require_relative "ruby_wasm/packager/core" + +module RubyWasm + class << self + attr_accessor :log_level + + def logger + @logger ||= + begin + logger = + Logger.new( + $stderr, + level: @log_level || Logger::INFO, + progname: "rbwasm" + ) + logger.formatter = + proc { |severity, datetime, progname, msg| "#{severity}: #{msg}\n" } + logger + end + end + + def logger=(logger) + @logger = logger + end + end +end diff --git a/lib/ruby_wasm/build.rb b/lib/ruby_wasm/build.rb index 379890dfb7..ade5366533 100644 --- a/lib/ruby_wasm/build.rb +++ b/lib/ruby_wasm/build.rb @@ -1,190 +1,88 @@ require_relative "build/build_params" require_relative "build/product" require_relative "build/toolchain" - -module RubyWasm - # Build executor to run the actual build commands. - class BuildExecutor - attr_reader :process_count - - def initialize(verbose: false, process_count: nil) - @verbose = verbose - @github_actions_markup = ENV["ENABLE_GITHUB_ACTIONS_MARKUP"] != nil - __skip__ = - begin - require "etc" - @process_count = process_count || Etc.nprocessors - rescue LoadError - @process_count = process_count || 1 - end - end - - def system(*args, chdir: nil, env: nil) - require "open3" - - _print_command(args, env) - - # @type var kwargs: Hash[Symbol, untyped] - kwargs = {} - kwargs[:chdir] = chdir if chdir - - args = args.to_a.map(&:to_s) - # TODO: Remove __skip__ once we have open3 RBS definitions. - __skip__ = - if @verbose || !$stdout.tty? - kwargs[:exception] = true - if env - Kernel.system(env, *args, **kwargs) - else - Kernel.system(*args, **kwargs) - end - else - printer = StatusPrinter.new - block = - proc do |stdin, stdout, stderr, wait_thr| - mux = Mutex.new - out = String.new - err = String.new - readers = - [ - [stdout, :stdout, out], - [stderr, :stderr, err] - ].map do |io, name, str| - reader = - Thread.new do - while (line = io.gets) - mux.synchronize do - printer.send(name, line) - str << line - end - end - end - reader.report_on_exception = false - reader - end - - readers.each(&:join) - - [out, err, wait_thr.value] - end - begin - stdout, stderr, status = - if env - Open3.popen3(env, *args, **kwargs, &block) - else - Open3.popen3(*args, **kwargs, &block) - end - unless status.success? - $stderr.puts stdout - $stderr.puts stderr - raise "Command failed with status (#{status.exitstatus}): #{args.join(" ")}" - end - ensure - printer.done - end - end - return - rescue => e - $stdout.flush - $stderr.puts "Try running with `rake --verbose` for more complete output." - raise e - end - - def begin_section(klass, name, note) - message = "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- #{note}\e[0m" - if @github_actions_markup - puts "::group::#{message}" - else - puts message - end - - # Record the start time - @start_times ||= Hash.new - @start_times[[klass, name]] = Time.now - - $stdout.flush - end - - def end_section(klass, name) - took = Time.now - @start_times[[klass, name]] - puts "::endgroup::" if @github_actions_markup - puts "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- done in #{took.round(2)}s\e[0m" - end - - def rm_rf(list) - FileUtils.rm_rf(list) - end - - def rm_f(list) - FileUtils.rm_f(list) - end - - def cp_r(src, dest) - FileUtils.cp_r(src, dest) - end - - def mv(src, dest) - FileUtils.mv(src, dest) - end - - def mkdir_p(list) - FileUtils.mkdir_p(list) - end - - def write(path, data) - File.write(path, data) - end - - private - - def _print_command(args, env) - require "shellwords" - # Bold cyan - print "\e[1;36m ==>\e[0m " - print "env " + env.map { |k, v| "#{k}=#{v}" }.join(" ") + " " if env - print args.map { |arg| Shellwords.escape(arg.to_s) }.join(" ") + "\n" - end +require_relative "build/executor" + +class RubyWasm::Build + # Source to build from. + attr_reader :source + + # Target to build for. + attr_reader :target + + # Toolchain for the build. + # Defaults to the Toolchain.get for the target. + attr_reader :toolchain + + # LibYAML product to build. + attr_reader :libyaml + + # zlib product to build. + attr_reader :zlib + + # wasi-vfs product used by the crossruby. + attr_reader :wasi_vfs + + # BaseRuby product to build. + attr_reader :baseruby + + # CrossRuby product to build. + attr_reader :crossruby + + def initialize( + name, + target:, + src:, + toolchain:, + build_dir:, + rubies_dir:, + **options + ) + @target = target + @build_dir = build_dir + @rubies_dir = rubies_dir + @toolchain = (toolchain || RubyWasm::Toolchain.get(target, @build_dir)) + + @libyaml = RubyWasm::LibYAMLProduct.new(@build_dir, @target, @toolchain) + @zlib = RubyWasm::ZlibProduct.new(@build_dir, @target, @toolchain) + @wasi_vfs = RubyWasm::WasiVfsProduct.new(@build_dir) + @source = RubyWasm::BuildSource.new(src, @build_dir) + @baseruby = RubyWasm::BaseRubyProduct.new(@build_dir, @source) + @openssl = RubyWasm::OpenSSLProduct.new(@build_dir, @target, @toolchain) + + build_params = + RubyWasm::BuildParams.new( + name: name, + target: target, + default_exts: options[:default_exts] + ) + + @crossruby = + RubyWasm::CrossRubyProduct.new( + build_params, + @build_dir, + @rubies_dir, + @baseruby, + @source, + @toolchain + ) + + @crossruby.with_libyaml @libyaml + @crossruby.with_zlib @zlib + @crossruby.with_wasi_vfs @wasi_vfs + @crossruby.with_openssl @openssl end - # Human readable status printer for the build. - class StatusPrinter - def initialize - @mutex = Mutex.new - @counter = 0 - @indicators = "|/-\\" - end - - def stdout(message) - require "io/console" - @mutex.synchronize do - $stdout.print "\e[K" - first_line = message.lines(chomp: true).first || "" - - # Make sure we don't line-wrap the output - size = - __skip__ = - IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize - terminal_width = size[1].to_i.nonzero? || 80 - width_limit = terminal_width / 2 - 3 - - if first_line.length > width_limit - first_line = (first_line[0..width_limit - 5] || "") + "..." - end - indicator = @indicators[@counter] || " " - to_print = " " + indicator + " " + first_line - $stdout.print to_print - $stdout.print "\e[1A\n" - @counter += 1 - @counter = 0 if @counter >= @indicators.length - end - end - - def stderr(message) - @mutex.synchronize { $stdout.print message } - end - - def done - @mutex.synchronize { $stdout.print "\e[K" } - end + def cache_key(digest) + @source.cache_key(digest) + @crossruby.cache_key(digest) + digest << @build_dir + digest << @rubies_dir + digest << @target + digest << @toolchain.name + digest << @libyaml.name + digest << @zlib.name + digest << @openssl.name + digest << @wasi_vfs.name end end diff --git a/lib/ruby_wasm/build/downloader.rb b/lib/ruby_wasm/build/downloader.rb index 38946eda14..b6e80019f7 100644 --- a/lib/ruby_wasm/build/downloader.rb +++ b/lib/ruby_wasm/build/downloader.rb @@ -1,15 +1,5 @@ module RubyWasm class Downloader - def format_size(size) - units = %w[B KB MB GB TB] - unit = 0 - while size > 1024 and unit < units.size - 1 - size /= 1024.0 - unit += 1 - end - "%s #{units[unit]}" % size.round(2) - end - def download(url, dest, message) require "open-uri" content_length = 0 @@ -18,7 +8,7 @@ def download(url, dest, message) uri, content_length_proc: ->(len) { content_length = len }, progress_proc: ->(size) do - print "\r#{message} (#{format_size(content_length)}) %.2f%%" % + print "\r#{message} (#{SizeFormatter.format(content_length)}) %.2f%%" % (size.to_f / content_length * 100) end ) { |f| File.open(dest, "wb") { |out| out.write f.read } } diff --git a/lib/ruby_wasm/build/executor.rb b/lib/ruby_wasm/build/executor.rb new file mode 100644 index 0000000000..f1e10d4926 --- /dev/null +++ b/lib/ruby_wasm/build/executor.rb @@ -0,0 +1,187 @@ +module RubyWasm + # Build executor to run the actual build commands. + class BuildExecutor + attr_reader :process_count + + def initialize(verbose: false, process_count: nil) + @verbose = verbose + @github_actions_markup = ENV["ENABLE_GITHUB_ACTIONS_MARKUP"] != nil + __skip__ = + begin + require "etc" + @process_count = process_count || Etc.nprocessors + rescue LoadError + @process_count = process_count || 1 + end + end + + def system(*args, chdir: nil, env: nil) + require "open3" + + _print_command(args, env) + + # @type var kwargs: Hash[Symbol, untyped] + kwargs = {} + kwargs[:chdir] = chdir if chdir + + args = args.to_a.map(&:to_s) + # TODO: Remove __skip__ once we have open3 RBS definitions. + __skip__ = + if @verbose || !$stdout.tty? + kwargs[:exception] = true + if env + Kernel.system(env, *args, **kwargs) + else + Kernel.system(*args, **kwargs) + end + else + printer = StatusPrinter.new + block = + proc do |stdin, stdout, stderr, wait_thr| + mux = Mutex.new + out = String.new + err = String.new + readers = + [ + [stdout, :stdout, out], + [stderr, :stderr, err] + ].map do |io, name, str| + reader = + Thread.new do + while (line = io.gets) + mux.synchronize do + printer.send(name, line) + str << line + end + end + end + reader.report_on_exception = false + reader + end + + readers.each(&:join) + + [out, err, wait_thr.value] + end + begin + stdout, stderr, status = + if env + Open3.popen3(env, *args, **kwargs, &block) + else + Open3.popen3(*args, **kwargs, &block) + end + unless status.success? + $stderr.puts stdout + $stderr.puts stderr + cmd_to_print = args.map { |a| "'#{a}'" }.join(" ") + raise "Command failed with status (#{status.exitstatus}): #{cmd_to_print}" + end + ensure + printer.done + end + end + return + rescue => e + $stdout.flush + $stderr.puts "Try running with `rake --verbose` for more complete output." + raise e + end + + def begin_section(klass, name, note) + message = "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- #{note}\e[0m" + if @github_actions_markup + puts "::group::#{message}" + else + puts message + end + + # Record the start time + @start_times ||= Hash.new + @start_times[[klass, name]] = Time.now + + $stdout.flush + end + + def end_section(klass, name) + took = Time.now - @start_times[[klass, name]] + puts "::endgroup::" if @github_actions_markup + puts "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- done in #{took.round(2)}s\e[0m" + end + + def rm_rf(list) + FileUtils.rm_rf(list) + end + + def rm_f(list) + FileUtils.rm_f(list) + end + + def cp_r(src, dest) + FileUtils.cp_r(src, dest) + end + + def mv(src, dest) + FileUtils.mv(src, dest) + end + + def mkdir_p(list) + FileUtils.mkdir_p(list) + end + + def write(path, data) + File.write(path, data) + end + + private + + def _print_command(args, env) + require "shellwords" + # Bold cyan + print "\e[1;36m ==>\e[0m " + print "env " + env.map { |k, v| "#{k}=#{v}" }.join(" ") + " " if env + print args.map { |arg| Shellwords.escape(arg.to_s) }.join(" ") + "\n" + end + end + + # Human readable status printer for the build. + class StatusPrinter + def initialize + @mutex = Mutex.new + @counter = 0 + @indicators = "|/-\\" + end + + def stdout(message) + require "io/console" + @mutex.synchronize do + $stdout.print "\e[K" + first_line = message.lines(chomp: true).first || "" + + # Make sure we don't line-wrap the output + size = + __skip__ = + IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize + terminal_width = size[1].to_i.nonzero? || 80 + width_limit = terminal_width / 2 - 3 + + if first_line.length > width_limit + first_line = (first_line[0..width_limit - 5] || "") + "..." + end + indicator = @indicators[@counter] || " " + to_print = " " + indicator + " " + first_line + $stdout.print to_print + $stdout.print "\e[1A\n" + @counter += 1 + @counter = 0 if @counter >= @indicators.length + end + end + + def stderr(message) + @mutex.synchronize { $stdout.print message } + end + + def done + @mutex.synchronize { $stdout.print "\e[K" } + end + end +end diff --git a/lib/ruby_wasm/build/product/crossruby.rb b/lib/ruby_wasm/build/product/crossruby.rb index ddbb91240a..323ddce315 100644 --- a/lib/ruby_wasm/build/product/crossruby.rb +++ b/lib/ruby_wasm/build/product/crossruby.rb @@ -1,21 +1,35 @@ require_relative "./product" +require "json" module RubyWasm class CrossRubyExtProduct < BuildProduct attr_reader :name - def initialize(srcdir, toolchain, name: nil) + + def initialize(srcdir, toolchain, ext_relative_path: nil) @srcdir, @toolchain = srcdir, toolchain - @name = name || File.basename(srcdir) + # ext_relative_path is relative path from build dir + # e.g. cgi-0.3.6/ext/cgi/escape + @ext_relative_path = ext_relative_path || File.basename(srcdir) + @name = @ext_relative_path end def product_build_dir(crossruby) - File.join(crossruby.ext_build_dir, @name) + File.join(crossruby.ext_build_dir, @ext_relative_path) end def linklist(crossruby) File.join(product_build_dir(crossruby), "link.filelist") end + def metadata_json(crossruby) + File.join(product_build_dir(crossruby), "rbwasm.metadata.json") + end + + def feature_name(crossruby) + metadata = JSON.parse(File.read(metadata_json(crossruby))) + metadata["target"] + end + def make_args(crossruby) make_args = [] make_args << "CC=#{@toolchain.cc}" @@ -28,7 +42,6 @@ def make_args(crossruby) end def build(executor, crossruby) - lib = @name objdir = product_build_dir crossruby executor.mkdir_p objdir do_extconf executor, crossruby @@ -37,7 +50,7 @@ def build(executor, crossruby) "-C", "#{objdir}", *make_args(crossruby), - "#{lib}.a" + "static" # A ext can provide link args by link.filelist. It contains only built archive file by default. unless File.exist?(linklist(crossruby)) executor.write( @@ -58,6 +71,9 @@ def do_extconf(executor, crossruby) # HACK: extout is required to find config.h "-e", %Q($extout="#{crossruby.build_dir}/.ext"), + # HACK: skip have_devel check since ruby is not installed yet + "-e", + "$have_devel = true", # HACK: force static ext build by imitating extmk "-e", "$static = true; trace_var(:$static) {|v| $static = true }", @@ -68,6 +84,10 @@ def do_extconf(executor, crossruby) %Q($0="#{@srcdir}/extconf.rb"), "-e", %Q(require_relative "#{@srcdir}/extconf.rb"), + # HACK: extract "$target" from extconf.rb to get a full target name + # like "cgi/escape" instead of "escape" + "-e", + %Q(require "json"; File.write("#{metadata_json(crossruby)}", JSON.dump({target: $target}))), "-I#{crossruby.build_dir}" ] # Clear RUBYOPT to avoid loading unrelated bundle setup @@ -108,22 +128,14 @@ class CrossRubyProduct < AutoconfProduct :xcflags, :xldflags - def initialize( - params, - build_dir, - rubies_dir, - baseruby, - source, - toolchain, - user_exts: [] - ) + def initialize(params, build_dir, rubies_dir, baseruby, source, toolchain) @params = params @rubies_dir = rubies_dir @build_dir = build_dir @baseruby = baseruby @source = source @toolchain = toolchain - @user_exts = user_exts + @user_exts = [] @wasmoptflags = [] @cppflags = [] @cflags = [] @@ -170,7 +182,7 @@ def build(executor, remake: false, reconfigure: false) executor.mkdir_p File.dirname(extinit_obj) executor.system "ruby", extinit_c_erb, - *@user_exts.map(&:name), + *@user_exts.map { |ext| ext.feature_name(self) }, "--cc", toolchain.cc, "--output", @@ -187,7 +199,7 @@ def build(executor, remake: false, reconfigure: false) executor.rm_rf dest_dir executor.cp_r install_dir, dest_dir @user_exts.each { |ext| ext.do_install_rb(executor, self) } - executor.system "tar", "cfz", artifact, "-C", "rubies", name + executor.system "tar", "cfz", artifact, "-C", @rubies_dir, name executor.end_section self.class, name end @@ -245,7 +257,7 @@ def dest_dir end def artifact - File.join(@rubies_dir, "ruby-#{name}.tar.gz") + File.join(@rubies_dir, "#{name}.tar.gz") end def extinit_obj diff --git a/lib/ruby_wasm/build/product/openssl.rb b/lib/ruby_wasm/build/product/openssl.rb index ed5e0c086b..4bea0ddb45 100644 --- a/lib/ruby_wasm/build/product/openssl.rb +++ b/lib/ruby_wasm/build/product/openssl.rb @@ -1,4 +1,3 @@ -require "rake" require_relative "./product" module RubyWasm diff --git a/lib/ruby_wasm/cli.rb b/lib/ruby_wasm/cli.rb new file mode 100644 index 0000000000..7d6d48c37f --- /dev/null +++ b/lib/ruby_wasm/cli.rb @@ -0,0 +1,195 @@ +require "optparse" +require "rbconfig" + +module RubyWasm + class CLI + def initialize(stdout:, stderr:) + @stdout = stdout + @stderr = stderr + end + + def run(args) + available_commands = %w[build] + parser = + OptionParser.new do |opts| + opts.banner = <<~USAGE + Usage: rbwasm [options...] [command] + + Available commands: #{available_commands.join(", ")} + USAGE + opts.version = RubyWasm::VERSION + opts.on("-h", "--help", "Prints this help") do + @stderr.puts opts + exit + end + opts.on("--log-level LEVEL", "Log level") do |level| + RubyWasm.log_level = level.to_sym + end + end + parser.order!(args) + + command = args.shift + case command + when "build" + build(args) + else + @stderr.puts parser + exit + end + end + + def build(args) + # @type var options: Hash[Symbol, untyped] + options = { + save_temps: false, + optimize: false, + remake: false, + reconfigure: false, + clean: false, + ruby_version: "3.3", + target_triplet: "wasm32-unknown-wasi", + profile: "full", + stdlib: true, + disable_gems: false + } + OptionParser + .new do |opts| + opts.banner = "Usage: rbwasm componentize [options]" + opts.on("-h", "--help", "Prints this help") do + @stdout.puts opts + exit + end + + opts.on("--save-temps", "Save temporary files") do + options[:save_temps] = true + end + + opts.on("--ruby-version VERSION", "Ruby version") do |version| + options[:ruby_version] = version + end + + opts.on("--target TRIPLET", "Target triplet") do |triplet| + options[:target_triplet] = triplet + end + + opts.on( + "--build-profile PROFILE", + "Build profile. full or minimal" + ) { |profile| options[:profile] = profile } + + opts.on("--optimize", "Optimize the output") do + options[:optimize] = true + end + + opts.on("--remake", "Re-execute make for Ruby") do + options[:remake] = true + end + + opts.on("--reconfigure", "Re-execute configure for Ruby") do + options[:reconfigure] = true + end + + opts.on("--clean", "Clean build artifacts") { options[:clean] = true } + + opts.on("-o", "--output FILE", "Output file") do |file| + options[:output] = file + end + + opts.on("--[no-]stdlib", "Include stdlib") do |stdlib| + options[:stdlib] = stdlib + end + + opts.on("--disable-gems", "Disable gems") do + options[:disable_gems] = true + end + + opts.on("--format FORMAT", "Output format") do |format| + options[:format] = format + end + + opts.on("--print-ruby-cache-key", "Print Ruby cache key") do + options[:print_ruby_cache_key] = true + end + end + .parse!(args) + + verbose = RubyWasm.logger.level == :debug + executor = RubyWasm::BuildExecutor.new(verbose: verbose) + packager = self.derive_packager(options) + + if options[:print_ruby_cache_key] + self.do_print_ruby_cache_key(packager) + exit + end + + unless options[:output] + @stderr.puts "Output file is not specified" + exit 1 + end + + require "tmpdir" + + if options[:save_temps] + tmpdir = Dir.mktmpdir + self.do_build(executor, tmpdir, packager, options) + @stderr.puts "Temporary files are saved to #{tmpdir}" + exit + else + Dir.mktmpdir do |tmpdir| + self.do_build(executor, tmpdir, packager, options) + end + end + end + + private + + def build_config(options) + config = { target: options[:target_triplet], src: options[:ruby_version] } + case options[:profile] + when "full" + config[:default_exts] = RubyWasm::Packager::ALL_DEFAULT_EXTS + when "minimal" + config[:default_exts] = "" + else + RubyWasm.logger.error "Unknown profile: #{options[:profile]} (available: full, minimal)" + exit 1 + end + config[:suffix] = "-#{options[:profile]}" + config + end + + def derive_packager(options) + __skip__ = + if defined?(Bundler) && !options[:disable_gems] + definition = Bundler.definition + end + RubyWasm::Packager.new(build_config(options), definition) + end + + def do_print_ruby_cache_key(packager) + ruby_core_build = packager.ruby_core_build + require "digest" + digest = Digest::SHA256.new + ruby_core_build.cache_key(digest) + hexdigest = digest.hexdigest + require "json" + @stdout.puts JSON.generate( + hexdigest: hexdigest, + artifact: ruby_core_build.artifact + ) + end + + def do_build(executor, tmpdir, packager, options) + require_relative "ruby_wasm.so" + wasm_bytes = packager.package(executor, tmpdir, options) + RubyWasm.logger.info "Size: #{SizeFormatter.format(wasm_bytes.size)}" + case options[:output] + when "-" + @stdout.write wasm_bytes.pack("C*") + else + File.binwrite(options[:output], wasm_bytes.pack("C*")) + RubyWasm.logger.debug "Wrote #{options[:output]}" + end + end + end +end diff --git a/lib/ruby_wasm/packager.rb b/lib/ruby_wasm/packager.rb new file mode 100644 index 0000000000..3a95446609 --- /dev/null +++ b/lib/ruby_wasm/packager.rb @@ -0,0 +1,159 @@ +# A class responsible for packaging whole Ruby project +class RubyWasm::Packager + # Initializes a new instance of the RubyWasm::Packager class. + # + # @param config [Hash] The build config used for building Ruby. + # @param definition [Bundler::Definition] The Bundler definition. + def initialize(config = nil, definition = nil) + @definition = definition + @config = config + end + + # Packages the Ruby code into a Wasm binary. (including extensions) + # + # @param executor [RubyWasm::BuildExecutor] The executor for building the Wasm binary. + # @param dest_dir [String] The destination used to construct the filesystem. + # @param options [Hash] The packaging options. + # @return [Array] The bytes of the packaged Wasm binary. + def package(executor, dest_dir, options) + ruby_core = self.ruby_core_build() + tarball = ruby_core.build(executor, options) + + fs = RubyWasm::Packager::FileSystem.new(dest_dir, self) + fs.package_ruby_root(tarball, executor) + + ruby_wasm_bin = File.expand_path("bin/ruby", fs.ruby_root) + wasm_bytes = File.binread(ruby_wasm_bin).bytes + + fs.package_gems + fs.remove_non_runtime_files(executor) + fs.remove_stdlib(executor) unless options[:stdlib] + + if full_build_options[:target] == "wasm32-unknown-wasi" + # wasi-vfs supports only WASI target + wasi_vfs = RubyWasmExt::WasiVfs.new + wasi_vfs.map_dir("/bundle", fs.bundle_dir) + wasi_vfs.map_dir("/usr", File.dirname(fs.ruby_root)) + + wasm_bytes = wasi_vfs.pack(wasm_bytes) + end + + wasm_bytes = RubyWasmExt.preinitialize(wasm_bytes) if options[:optimize] + wasm_bytes + end + + def ruby_core_build + @ruby_core_build ||= RubyWasm::Packager::Core.new(self) + end + + # The list of excluded gems from the Bundler definition. + EXCLUDED_GEMS = %w[ruby_wasm bundler] + + # Retrieves the specs from the Bundler definition, excluding the excluded gems. + def specs + return [] unless @definition + @definition.specs.reject { |spec| EXCLUDED_GEMS.include?(spec.name) } + end + + # Checks if dynamic linking is supported. + def support_dynamic_linking? + @ruby_channel == "head" + end + + # Retrieves the root directory of the Ruby project. + # The root directory contains the following stuff: + # * patches/*.patch + # * build_manifest.json + # * rubies + # * build + def root + __skip__ = + @root ||= + begin + if explicit = ENV["RUBY_WASM_ROOT"] + File.expand_path(explicit) + elsif defined?(Bundler) + Bundler.root + else + Dir.pwd + end + rescue Bundler::GemfileNotFound + Dir.pwd + end + end + + # Retrieves the alias definitions for the Ruby sources. + def self.build_source_aliases(root) + patches = Dir[File.join(root, "patches", "*.patch")] + sources = { + "head" => { + type: "github", + repo: "ruby/ruby", + rev: "997124fc0b7697bb9383e8feb8e1d88017c4bcb8", + patches: patches.map { |p| File.expand_path(p) } + }, + "3.3" => { + type: "tarball", + url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.0.tar.gz" + }, + "3.2" => { + type: "tarball", + url: "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.2.tar.gz" + } + } + sources.each { |name, source| source[:name] = name } + + build_manifest = File.join(root, "build_manifest.json") + if File.exist?(build_manifest) + begin + manifest = JSON.parse(File.read(build_manifest)) + manifest["ruby_revisions"].each do |name, rev| + sources[name][:rev] = rev + end + rescue StandardError => e + RubyWasm.logger.warn "Failed to load build_manifest.json: #{e}" + end + end + sources + end + + ALL_DEFAULT_EXTS = + "bigdecimal,cgi/escape,continuation,coverage,date,dbm,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,fiber,gdbm,json,json/generator,json/parser,nkf,objspace,pathname,psych,racc/cparse,rbconfig/sizeof,ripper,stringio,strscan,monitor,zlib,openssl" + + # Retrieves the build options used for building Ruby itself. + def build_options + default = { + target: "wasm32-unknown-wasi", + src: "3.3", + default_exts: ALL_DEFAULT_EXTS + } + override = @config || {} + # Merge the default options with the config options + default.merge(override) + end + + # Retrieves the resolved build options + def full_build_options + options = build_options + build_dir = File.join(root, "build") + rubies_dir = File.join(root, "rubies") + toolchain = RubyWasm::Toolchain.get(options[:target], build_dir) + src = + if options[:src].is_a?(Hash) + options[:src] + else + src_name = options[:src] + aliases = self.class.build_source_aliases(root) + aliases[src_name] || + raise( + "Unknown Ruby source: #{src_name} (available: #{aliases.keys.join(", ")})" + ) + end + options.merge( + toolchain: toolchain, + build_dir: build_dir, + rubies_dir: rubies_dir, + src: src + ) + end +end diff --git a/lib/ruby_wasm/packager/core.rb b/lib/ruby_wasm/packager/core.rb new file mode 100644 index 0000000000..b1049f27f7 --- /dev/null +++ b/lib/ruby_wasm/packager/core.rb @@ -0,0 +1,156 @@ +require "forwardable" + +class RubyWasm::Packager::Core + def initialize(packager) + @packager = packager + end + + def build(executor, options) + strategy = build_strategy + strategy.build(executor, options) + end + + extend Forwardable + + def_delegators :build_strategy, :cache_key, :artifact + + private + + def build_strategy + @build_strategy ||= + begin + has_exts = @packager.specs.any? { |spec| spec.extensions.any? } + if @packager.support_dynamic_linking? + DynamicLinking.new(@packager) + else + StaticLinking.new(@packager) + end + end + end + + class BuildStrategy + def initialize(packager) + @packager = packager + end + + def build(executor, options) + raise NotImplementedError + end + + # Array of paths to extconf.rb files. + def specs_with_extensions + @packager.specs.filter_map do |spec| + exts = + spec.extensions.select do |ext| + # Filter out extensions of default gems (e.g. json, openssl) + # for the exactly same gem version. + File.exist?(File.join(spec.full_gem_path, ext)) + end + next nil if exts.empty? + [spec, exts] + end + end + + def cache_key(digest) + raise NotImplementedError + end + + def artifact + raise NotImplementedError + end + end + + class DynamicLinking < BuildStrategy + end + + class StaticLinking < BuildStrategy + def build(executor, options) + build = derive_build + force_rebuild = + options[:remake] || options[:clean] || options[:reconfigure] + if File.exist?(build.crossruby.artifact) && !force_rebuild + return build.crossruby.artifact + end + build.crossruby.clean(executor) if options[:clean] + + do_build = + proc do + build.crossruby.build( + executor, + remake: options[:remake], + reconfigure: options[:reconfigure] + ) + end + + __skip__ = + if defined?(Bundler) + Bundler.with_unbundled_env(&do_build) + else + do_build.call + end + build.crossruby.artifact + end + + def cache_key(digest) + derive_build.cache_key(digest) + end + + def artifact + derive_build.crossruby.artifact + end + + def derive_build + return @build if @build + __skip__ = + build ||= RubyWasm::Build.new(name, **@packager.full_build_options) + build.crossruby.user_exts = user_exts(build) + # Emscripten uses --global-base=1024 by default, but it conflicts with + # --stack-first and -z stack-size since global-base 1024 is smaller than + # the large stack size. + # Also -g produces some warnings on Emscripten and it confuses the configure + # script of Ruby. + if @packager.full_build_options[:target] != "wasm32-unknown-emscripten" + build.crossruby.debugflags = %w[-g] + build.crossruby.wasmoptflags = %w[-O3 -g] + build.crossruby.ldflags = %w[ + -Xlinker + --stack-first + -Xlinker + -z + -Xlinker + stack-size=16777216 + ] + end + @build = build + build + end + + def user_exts(build) + @user_exts ||= + specs_with_extensions.flat_map do |spec, exts| + exts.map do |ext| + ext_feature = File.dirname(ext) # e.g. "ext/cgi/escape" + ext_srcdir = File.join(spec.full_gem_path, ext_feature) + ext_relative_path = File.join(spec.full_name, ext_feature) + RubyWasm::CrossRubyExtProduct.new( + ext_srcdir, + build.toolchain, + ext_relative_path: ext_relative_path + ) + end + end + end + + def name + require "digest" + options = @packager.full_build_options + src_channel = options[:src][:name] + target_triplet = options[:target] + base = "ruby-#{src_channel}-#{target_triplet}#{options[:suffix]}" + exts = specs_with_extensions.sort + hash = ::Digest::MD5.new + specs_with_extensions.each { |spec, _| hash << spec.full_name } + exts.empty? ? base : "#{base}-#{hash.hexdigest}" + end + end +end diff --git a/lib/ruby_wasm/packager/file_system.rb b/lib/ruby_wasm/packager/file_system.rb new file mode 100644 index 0000000000..8aebb70a87 --- /dev/null +++ b/lib/ruby_wasm/packager/file_system.rb @@ -0,0 +1,157 @@ +# Package Ruby code into a mountable directory. +class RubyWasm::Packager::FileSystem + def initialize(dest_dir, packager) + @dest_dir = dest_dir + @packager = packager + @ruby_root = File.join(@dest_dir, "usr", "local") + end + + def package_ruby_root(tarball, executor) + usr_dir = File.dirname(@ruby_root) + executor.mkdir_p usr_dir + executor.system( + "tar", + "-C", + usr_dir, + "-xzf", + tarball, + "--strip-components=2" + ) + end + + def remove_stdlib(executor) + # Include only rbconfig.rb + rbconfig = + File.join( + @ruby_root, + "lib", + "ruby", + ruby_version, + "wasm32-wasi", + "rbconfig.rb" + ) + # Remove all files except rbconfig.rb + RubyWasm.logger.info "Removing stdlib (except rbconfig.rb: #{rbconfig})" + rbconfig_contents = File.read(rbconfig) + executor.rm_rf @ruby_root + executor.mkdir_p File.dirname(rbconfig) + File.write(rbconfig, rbconfig_contents) + end + + def package_gems + @packager.specs.each do |spec| + RubyWasm.logger.info "Packaging gem: #{spec.full_name}" + end + self.each_gem_content_path do |relative, source| + RubyWasm.logger.debug "Packaging gem file: #{relative}" + dest = File.join(@dest_dir, relative) + FileUtils.mkdir_p File.dirname(dest) + FileUtils.cp_r source, dest + end + + setup_rb_path = File.join(bundle_relative_path, "setup.rb") + RubyWasm.logger.info "Packaging setup.rb: #{setup_rb_path}" + full_setup_rb_path = File.join(@dest_dir, setup_rb_path) + FileUtils.mkdir_p File.dirname(full_setup_rb_path) + File.write(full_setup_rb_path, setup_rb_content) + end + + def setup_rb_content + content = "" + self.each_gem_require_path do |relative, _| + content << %Q[$:.unshift File.expand_path("#{File.join("/", relative)}")\n] + end + content + end + + def remove_non_runtime_files(executor) + %w[ + **/*.so + usr/local/lib/libruby-static.a + usr/local/bin/ruby + usr/local/include + ].each do |pattern| + Dir + .glob(File.join(@dest_dir, pattern)) + .each do |entry| + RubyWasm.logger.debug do + relative_entry = Pathname.new(entry).relative_path_from(@dest_dir) + "Removing non-runtime file: #{relative_entry}" + end + executor.rm_rf entry + end + end + end + + def bundle_dir + File.join(@dest_dir, bundle_relative_path) + end + + def ruby_root + @ruby_root + end + + private + + # Iterates over each gem's require path and extension path. + # Yields the installation relative path and the source path. + def each_gem_require_path(&block) + each_gem_extension_path(&block) + @packager.specs.each do |spec| + spec.raw_require_paths.each do |require_path| + source = File.expand_path(require_path, spec.full_gem_path) + next unless File.exist?(source) + relative = + File.join(bundle_relative_path, "gems", spec.full_name, require_path) + yield relative, source + end + end + end + + def each_gem_content_path(&block) + each_gem_extension_path(&block) + + @packager.specs.each do |spec| + next unless File.exist?(spec.full_gem_path) + + Dir + .children(spec.full_gem_path) + .each do |require_path| + source = File.expand_path(require_path, spec.full_gem_path) + next unless File.exist?(source) + relative = + File.join( + bundle_relative_path, + "gems", + spec.full_name, + require_path + ) + yield relative, source + end + end + end + + def each_gem_extension_path + @packager.specs.each do |spec| + if !spec.extensions.empty? && File.exist?(spec.extension_dir) + relative = File.join(bundle_relative_path, "extensions", spec.full_name) + yield relative, spec.extension_dir + end + end + end + + def bundle_relative_path + "bundle" + end + + def ruby_version + rubyarchdir = self.rubyarchdir + File.basename(File.dirname(rubyarchdir)) + end + + def rubyarchdir + maybe = + Dir.glob(File.join(@ruby_root, "lib", "ruby", "*", "wasm32-wasi")).first + maybe || raise("Cannot find rubyarchdir") + end +end diff --git a/lib/ruby_wasm/rake_task.rb b/lib/ruby_wasm/rake_task.rb index eb403617c8..2540f0d4d1 100644 --- a/lib/ruby_wasm/rake_task.rb +++ b/lib/ruby_wasm/rake_task.rb @@ -5,31 +5,6 @@ class RubyWasm::BuildTask < ::Rake::TaskLib # Name of the task. attr_accessor :name - # Source to build from. - attr_reader :source - - # Target to build for. - attr_reader :target - - # Toolchain for the build. - # Defaults to the Toolchain.get for the target. - attr_reader :toolchain - - # LibYAML product to build. - attr_reader :libyaml - - # zlib product to build. - attr_reader :zlib - - # wasi-vfs product used by the crossruby. - attr_reader :wasi_vfs - - # BaseRuby product to build. - attr_reader :baseruby - - # CrossRuby product to build. - attr_reader :crossruby - def initialize( name, target:, @@ -37,40 +12,22 @@ def initialize( toolchain: nil, build_dir: nil, rubies_dir: nil, - **options + **options, + &block ) - @name = name - @target = target - @build_dir = build_dir || File.join(Dir.pwd, "build") - @rubies_dir = rubies_dir || File.join(Dir.pwd, "rubies") - @toolchain = (toolchain || RubyWasm::Toolchain.get(target, @build_dir)) - - @libyaml = RubyWasm::LibYAMLProduct.new(@build_dir, @target, @toolchain) - @zlib = RubyWasm::ZlibProduct.new(@build_dir, @target, @toolchain) - @wasi_vfs = RubyWasm::WasiVfsProduct.new(@build_dir) - @source = RubyWasm::BuildSource.new(src, @build_dir) - @baseruby = RubyWasm::BaseRubyProduct.new(@build_dir, @source) - @openssl = RubyWasm::OpenSSLProduct.new(@build_dir, @target, @toolchain) - - build_params = - RubyWasm::BuildParams.new(options.merge(name: name, target: target)) - - @crossruby = - RubyWasm::CrossRubyProduct.new( - build_params, - @build_dir, - @rubies_dir, - @baseruby, - @source, - @toolchain + @build = + RubyWasm::Build.new( + name, + target: target, + src: src, + toolchain: toolchain, + build_dir: build_dir || File.join(Dir.pwd, "build"), + rubies_dir: rubies_dir || File.join(Dir.pwd, "rubies"), + **options, + &block ) - yield self if block_given? - - @crossruby.with_libyaml @libyaml - @crossruby.with_zlib @zlib - @crossruby.with_wasi_vfs @wasi_vfs - @crossruby.with_openssl @openssl - + yield @build if block_given? + @crossruby = @build.crossruby # Rake.verbose can be Object.new by default, so compare with true explicitly. executor = RubyWasm::BuildExecutor.new(verbose: Rake.verbose == true) @@ -95,16 +52,7 @@ def initialize( def hexdigest require "digest" digest = Digest::SHA256.new - @source.cache_key(digest) - @crossruby.cache_key(digest) - digest << @build_dir - digest << @rubies_dir - digest << @target - digest << @toolchain.name - digest << @libyaml.name - digest << @zlib.name - digest << @openssl.name - digest << @wasi_vfs.name + @build.cache_key(digest) digest.hexdigest end end diff --git a/lib/ruby_wasm/util.rb b/lib/ruby_wasm/util.rb new file mode 100644 index 0000000000..f19530ee0f --- /dev/null +++ b/lib/ruby_wasm/util.rb @@ -0,0 +1,15 @@ +module RubyWasm + module SizeFormatter + def format(size) + units = %w[B KB MB GB TB] + unit = 0 + while size > 1024 and unit < units.size - 1 + size /= 1024.0 + unit += 1 + end + "%s #{units[unit]}" % size.round(2) + end + + module_function :format + end +end diff --git a/ext/js/bindgen/.clang-format b/packages/gems/js/ext/js/bindgen/.clang-format similarity index 100% rename from ext/js/bindgen/.clang-format rename to packages/gems/js/ext/js/bindgen/.clang-format diff --git a/ext/js/bindgen/rb-js-abi-host.c b/packages/gems/js/ext/js/bindgen/rb-js-abi-host.c similarity index 100% rename from ext/js/bindgen/rb-js-abi-host.c rename to packages/gems/js/ext/js/bindgen/rb-js-abi-host.c diff --git a/ext/js/bindgen/rb-js-abi-host.h b/packages/gems/js/ext/js/bindgen/rb-js-abi-host.h similarity index 100% rename from ext/js/bindgen/rb-js-abi-host.h rename to packages/gems/js/ext/js/bindgen/rb-js-abi-host.h diff --git a/ext/js/bindgen/rb-js-abi-host.wit b/packages/gems/js/ext/js/bindgen/rb-js-abi-host.wit similarity index 100% rename from ext/js/bindgen/rb-js-abi-host.wit rename to packages/gems/js/ext/js/bindgen/rb-js-abi-host.wit diff --git a/ext/js/depend b/packages/gems/js/ext/js/depend similarity index 100% rename from ext/js/depend rename to packages/gems/js/ext/js/depend diff --git a/ext/js/extconf.rb b/packages/gems/js/ext/js/extconf.rb similarity index 100% rename from ext/js/extconf.rb rename to packages/gems/js/ext/js/extconf.rb diff --git a/ext/js/js-core.c b/packages/gems/js/ext/js/js-core.c similarity index 100% rename from ext/js/js-core.c rename to packages/gems/js/ext/js/js-core.c diff --git a/ext/witapi/bindgen/.clang-format b/packages/gems/js/ext/witapi/bindgen/.clang-format similarity index 100% rename from ext/witapi/bindgen/.clang-format rename to packages/gems/js/ext/witapi/bindgen/.clang-format diff --git a/ext/witapi/bindgen/rb-abi-guest.c b/packages/gems/js/ext/witapi/bindgen/rb-abi-guest.c similarity index 100% rename from ext/witapi/bindgen/rb-abi-guest.c rename to packages/gems/js/ext/witapi/bindgen/rb-abi-guest.c diff --git a/ext/witapi/bindgen/rb-abi-guest.h b/packages/gems/js/ext/witapi/bindgen/rb-abi-guest.h similarity index 100% rename from ext/witapi/bindgen/rb-abi-guest.h rename to packages/gems/js/ext/witapi/bindgen/rb-abi-guest.h diff --git a/ext/witapi/bindgen/rb-abi-guest.wit b/packages/gems/js/ext/witapi/bindgen/rb-abi-guest.wit similarity index 100% rename from ext/witapi/bindgen/rb-abi-guest.wit rename to packages/gems/js/ext/witapi/bindgen/rb-abi-guest.wit diff --git a/ext/witapi/depend b/packages/gems/js/ext/witapi/depend similarity index 100% rename from ext/witapi/depend rename to packages/gems/js/ext/witapi/depend diff --git a/ext/witapi/extconf.rb b/packages/gems/js/ext/witapi/extconf.rb similarity index 100% rename from ext/witapi/extconf.rb rename to packages/gems/js/ext/witapi/extconf.rb diff --git a/ext/witapi/witapi-core.c b/packages/gems/js/ext/witapi/witapi-core.c similarity index 100% rename from ext/witapi/witapi-core.c rename to packages/gems/js/ext/witapi/witapi-core.c diff --git a/packages/gems/js/js.gemspec b/packages/gems/js/js.gemspec new file mode 100644 index 0000000000..dbe8becb6a --- /dev/null +++ b/packages/gems/js/js.gemspec @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require_relative "../../../lib/ruby_wasm/version" + +Gem::Specification.new do |spec| + spec.name = "js" + spec.version = RubyWasm::VERSION + spec.authors = ["Yuta Saito"] + spec.email = ["kateinoigakukun@gmail.com"] + + spec.summary = "JavaScript bindings for ruby.wasm" + + spec.license = "MIT" + + spec.files = Dir.chdir(__dir__) do + `git ls-files -z`.split("\x0").reject do |f| + (File.expand_path(f) == __FILE__) || + f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile]) + end + end + spec.require_paths = ["lib"] + spec.extensions = ["ext/js/extconf.rb", "ext/witapi/extconf.rb"] +end diff --git a/ext/js/lib/js.rb b/packages/gems/js/lib/js.rb similarity index 100% rename from ext/js/lib/js.rb rename to packages/gems/js/lib/js.rb diff --git a/ext/js/lib/js/array.rb b/packages/gems/js/lib/js/array.rb similarity index 100% rename from ext/js/lib/js/array.rb rename to packages/gems/js/lib/js/array.rb diff --git a/ext/js/lib/js/hash.rb b/packages/gems/js/lib/js/hash.rb similarity index 100% rename from ext/js/lib/js/hash.rb rename to packages/gems/js/lib/js/hash.rb diff --git a/ext/js/lib/js/nil_class.rb b/packages/gems/js/lib/js/nil_class.rb similarity index 100% rename from ext/js/lib/js/nil_class.rb rename to packages/gems/js/lib/js/nil_class.rb diff --git a/ext/js/lib/js/require_remote.rb b/packages/gems/js/lib/js/require_remote.rb similarity index 100% rename from ext/js/lib/js/require_remote.rb rename to packages/gems/js/lib/js/require_remote.rb diff --git a/ext/js/lib/js/require_remote/evaluator.rb b/packages/gems/js/lib/js/require_remote/evaluator.rb similarity index 100% rename from ext/js/lib/js/require_remote/evaluator.rb rename to packages/gems/js/lib/js/require_remote/evaluator.rb diff --git a/ext/js/lib/js/require_remote/url_resolver.rb b/packages/gems/js/lib/js/require_remote/url_resolver.rb similarity index 100% rename from ext/js/lib/js/require_remote/url_resolver.rb rename to packages/gems/js/lib/js/require_remote/url_resolver.rb diff --git a/packages/npm-packages/ruby-3.2-wasm-wasi/package.json b/packages/npm-packages/ruby-3.2-wasm-wasi/package.json index 2e67620c94..e390b32ae7 100644 --- a/packages/npm-packages/ruby-3.2-wasm-wasi/package.json +++ b/packages/npm-packages/ruby-3.2-wasm-wasi/package.json @@ -28,9 +28,8 @@ "build:static:files": "../ruby-wasm-wasi/tools/pack-static-files.sh ./dist", "build:static:compat": "../ruby-wasm-wasi/tools/pack-compat-shim.mjs --dist=./dist --pkg=ruby-3.2-wasm-wasi", "build:static": "npm run build:static:files && npm run build:static:compat", - "build:wasm": "../ruby-wasm-wasi/tools/pack-ruby-wasm.sh ../../../rubies/3.2-wasm32-unknown-wasi-full-js-debug ./dist", "build:rollup": "rollup -c rollup.config.mjs", - "build": "npm run build:deps && npm run build:static && npm run build:wasm && npm run build:rollup && ../ruby-wasm-wasi/tools/post-build.sh ./dist" + "build": "npm run build:deps && npm run build:static && npm run build:rollup && ../ruby-wasm-wasi/tools/post-build.sh ./dist" }, "repository": "https://github.com/ruby/ruby.wasm", "homepage": "https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-3.2-wasm-wasi", diff --git a/packages/npm-packages/ruby-3.3-wasm-wasi/package.json b/packages/npm-packages/ruby-3.3-wasm-wasi/package.json index 33416719f1..be1b7d4cf2 100644 --- a/packages/npm-packages/ruby-3.3-wasm-wasi/package.json +++ b/packages/npm-packages/ruby-3.3-wasm-wasi/package.json @@ -28,9 +28,8 @@ "build:static:files": "../ruby-wasm-wasi/tools/pack-static-files.sh ./dist", "build:static:compat": "../ruby-wasm-wasi/tools/pack-compat-shim.mjs --dist=./dist --pkg=ruby-3.3-wasm-wasi", "build:static": "npm run build:static:files && npm run build:static:compat", - "build:wasm": "../ruby-wasm-wasi/tools/pack-ruby-wasm.sh ../../../rubies/3.3-wasm32-unknown-wasi-full-js-debug ./dist", "build:rollup": "rollup -c rollup.config.mjs", - "build": "npm run build:deps && npm run build:static && npm run build:wasm && npm run build:rollup && ../ruby-wasm-wasi/tools/post-build.sh ./dist" + "build": "npm run build:deps && npm run build:static && npm run build:rollup && ../ruby-wasm-wasi/tools/post-build.sh ./dist" }, "repository": "https://github.com/ruby/ruby.wasm", "homepage": "https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-3.3-wasm-wasi", diff --git a/packages/npm-packages/ruby-head-wasm-emscripten/package.json b/packages/npm-packages/ruby-head-wasm-emscripten/package.json index 0cb0b43311..a1960af56b 100644 --- a/packages/npm-packages/ruby-head-wasm-emscripten/package.json +++ b/packages/npm-packages/ruby-head-wasm-emscripten/package.json @@ -11,7 +11,7 @@ "README.md" ], "scripts": { - "build": "./build-package.sh ../../../rubies/head-wasm32-unknown-emscripten-full" + "build": "./build-package.sh ../../../rubies/ruby-head-wasm32-unknown-emscripten-full" }, "repository": "https://github.com/ruby/ruby.wasm", "homepage": "https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-head-wasm-emscripten", diff --git a/packages/npm-packages/ruby-head-wasm-wasi/package.json b/packages/npm-packages/ruby-head-wasm-wasi/package.json index 5de9cfd4de..f8258e2174 100644 --- a/packages/npm-packages/ruby-head-wasm-wasi/package.json +++ b/packages/npm-packages/ruby-head-wasm-wasi/package.json @@ -28,9 +28,8 @@ "build:static:files": "../ruby-wasm-wasi/tools/pack-static-files.sh ./dist", "build:static:compat": "../ruby-wasm-wasi/tools/pack-compat-shim.mjs --dist=./dist --pkg=ruby-head-wasm-wasi", "build:static": "npm run build:static:files && npm run build:static:compat", - "build:wasm": "../ruby-wasm-wasi/tools/pack-ruby-wasm.sh ../../../rubies/head-wasm32-unknown-wasi-full-js-debug ./dist", "build:rollup": "rollup -c rollup.config.mjs", - "build": "npm run build:deps && npm run build:static && npm run build:wasm && npm run build:rollup && ../ruby-wasm-wasi/tools/post-build.sh ./dist" + "build": "npm run build:deps && npm run build:static && npm run build:rollup && ../ruby-wasm-wasi/tools/post-build.sh ./dist" }, "repository": "https://github.com/ruby/ruby.wasm", "homepage": "https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-head-wasm-wasi", diff --git a/packages/npm-packages/ruby-wasm-wasi/Gemfile b/packages/npm-packages/ruby-wasm-wasi/Gemfile new file mode 100644 index 0000000000..5fc9e696ce --- /dev/null +++ b/packages/npm-packages/ruby-wasm-wasi/Gemfile @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "js", path: "../../gems/js" +gem "ruby_wasm", path: "../../../" diff --git a/packages/npm-packages/ruby-wasm-wasi/Gemfile.lock b/packages/npm-packages/ruby-wasm-wasi/Gemfile.lock new file mode 100644 index 0000000000..821cb70969 --- /dev/null +++ b/packages/npm-packages/ruby-wasm-wasi/Gemfile.lock @@ -0,0 +1,24 @@ +PATH + remote: ../../.. + specs: + ruby_wasm (2.4.1) + +PATH + remote: ../../gems/js + specs: + js (2.4.1) + +GEM + remote: https://rubygems.org/ + specs: + +PLATFORMS + ruby + x86_64-linux + +DEPENDENCIES + js! + ruby_wasm! + +BUNDLED WITH + 2.5.3 diff --git a/packages/npm-packages/ruby-wasm-wasi/package.json b/packages/npm-packages/ruby-wasm-wasi/package.json index 77a502b443..d509312757 100644 --- a/packages/npm-packages/ruby-wasm-wasi/package.json +++ b/packages/npm-packages/ruby-wasm-wasi/package.json @@ -40,14 +40,12 @@ "license": "MIT", "scripts": { "test:run": "npm run test:unit && npm run test:jest && npm run test:e2e", - "test:head": "RUBY_ROOT=../../../rubies/head-wasm32-unknown-wasi-full-js-debug npm run test:run", - "test": "npm run test:head", "test:jest": "NODE_OPTIONS=\"--experimental-wasi-unstable-preview1\" jest --coverage", "test:unit": "./tools/run-test-unit.mjs", "test:e2e": "playwright install && npm run test:e2e:examples && npm run test:e2e:integrations", "test:e2e:examples": "playwright test -c test-e2e/playwright.examples.config.ts", "test:e2e:integrations": "playwright test -c test-e2e/playwright.integrations.config.ts", - "serve:example": "bundle exec ruby -run -e httpd ./example -p 8085", + "serve:example": "BUNDLE_GEMFILE=../../../Gemfile bundle exec ruby -run -e httpd ./example -p 8085", "format": "prettier --write .", "build:static": "./tools/pack-bindgen-src.sh ./dist", "build:rollup": "rollup -c rollup.config.mjs", diff --git a/packages/npm-packages/ruby-wasm-wasi/src/index.ts b/packages/npm-packages/ruby-wasm-wasi/src/index.ts index 32a73ed1f6..46f6c2130a 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/index.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/index.ts @@ -87,13 +87,12 @@ export class RubyVM { * @param args The command line arguments to pass to Ruby. Must be * an array of strings starting with the Ruby program name. */ - initialize( - args: string[] = ["ruby.wasm", "--disable-gems", "-EUTF-8", "-e_=0"], - ) { + initialize(args: string[] = ["ruby.wasm", "-EUTF-8", "-e_=0"]) { const c_args = args.map((arg) => arg + "\0"); this.guest.rubyInit(); this.guest.rubySysinit(c_args); this.guest.rubyOptions(c_args); + this.eval(`require "/bundle/setup"`); } /** diff --git a/packages/npm-packages/ruby-wasm-wasi/tools/pack-ruby-wasm.sh b/packages/npm-packages/ruby-wasm-wasi/tools/pack-ruby-wasm.sh deleted file mode 100755 index 7bf6c57b37..0000000000 --- a/packages/npm-packages/ruby-wasm-wasi/tools/pack-ruby-wasm.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -set -eu - -usage() { - echo "Usage: $(basename $0) ruby_root dist_dir" - exit 1 -} - -if [ $# -lt 2 ]; then - usage -fi - -ruby_root="$1" -dist_dir="$2" -package_dir="$(cd "$(dirname "$0")/.." && pwd)" - -mkdir -p "$dist_dir" - -"$WASMOPT" --strip-debug "$ruby_root/usr/local/bin/ruby" -o "$dist_dir/ruby.wasm" - -# Build +stdlib versions (removing files that are not used in normal use cases) - -workdir="$(mktemp -d)" -cp -R "$ruby_root" "$workdir/ruby-root" -rm -rf $workdir/ruby-root/usr/local/include -rm -f $workdir/ruby-root/usr/local/lib/libruby-static.a -rm -f $workdir/ruby-root/usr/local/bin/ruby -"$WASI_VFS_CLI" pack "$dist_dir/ruby.wasm" --mapdir /usr::$workdir/ruby-root/usr -o "$dist_dir/ruby+stdlib.wasm" -"$WASI_VFS_CLI" pack "$ruby_root/usr/local/bin/ruby" --mapdir /usr::$workdir/ruby-root/usr -o "$dist_dir/ruby.debug+stdlib.wasm" - -cp $dist_dir/*.wasm "$package_dir/dist/" diff --git a/packages/npm-packages/ruby-wasm-wasi/tools/run-test-unit.mjs b/packages/npm-packages/ruby-wasm-wasi/tools/run-test-unit.mjs index 22422b2879..e2b0e7ee96 100755 --- a/packages/npm-packages/ruby-wasm-wasi/tools/run-test-unit.mjs +++ b/packages/npm-packages/ruby-wasm-wasi/tools/run-test-unit.mjs @@ -149,19 +149,6 @@ const test = async (instantiate) => { Error.stackTraceLimit = Infinity; await vm.evalAsync(` - # HACK: Until we've fixed the issue in the test-unit or power_assert - # See https://github.com/test-unit/test-unit/pull/221 - module Kernel - alias test_unit_original_require require - - def require(path) - if path == "power_assert" - raise LoadError, "power_assert is not supported in this environment" - end - test_unit_original_require(path) - end - end - require 'test/unit' require_relative '${rootTestFile}' Test::Unit::AutoRunner.run diff --git a/ruby_wasm.gemspec b/ruby_wasm.gemspec index 3a8d73cb00..8315e8d9b6 100644 --- a/ruby_wasm.gemspec +++ b/ruby_wasm.gemspec @@ -27,4 +27,5 @@ Gem::Specification.new do |spec| spec.bindir = "exe" spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] + spec.extensions = ["ext/ruby_wasm/Cargo.toml"] end diff --git a/sig/ruby_wasm/build.rbs b/sig/ruby_wasm/build.rbs index 9a9838f672..8b0b9a0a26 100644 --- a/sig/ruby_wasm/build.rbs +++ b/sig/ruby_wasm/build.rbs @@ -1,10 +1,45 @@ module RubyWasm VERSION: String + interface _Cacheable + def cache_key: (Digest::SHA256 digest) -> void + end + + class Build + include _Cacheable + + @target: String + @build_dir: String + @rubies_dir: String + @toolchain: Toolchain + @libyaml: LibYAMLProduct + @zlib: ZlibProduct + @openssl: OpenSSLProduct + @wasi_vfs: WasiVfsProduct + @baseruby: BaseRubyProduct + @crossruby: CrossRubyProduct + @source: BuildSource + + attr_reader toolchain: Toolchain + + def initialize: ( + string name, + target: String, + src: Packager::build_source, + toolchain: Toolchain?, + build_dir: string, + rubies_dir: string, + **untyped + ) -> void + def crossruby: () -> CrossRubyProduct + end + class BuildParams attr_accessor name: String attr_accessor target: String attr_accessor default_exts: String + + def initialize: (name: string, target: string, default_exts: string) -> void end class BuildProduct @@ -109,21 +144,28 @@ module RubyWasm end class CrossRubyExtProduct < BuildProduct + include RubyWasm::_Cacheable + @toolchain: Toolchain @srcdir: String + @ext_relative_path: String attr_reader name: String - def initialize: (String srcdir, Toolchain toolchain, ?name: nil) -> void + def initialize: (String srcdir, Toolchain toolchain, ?ext_relative_path: String?) -> void def product_build_dir: (CrossRubyProduct crossruby) -> String def linklist: (CrossRubyProduct crossruby) -> String + def metadata_json: (CrossRubyProduct crossruby) -> String + def feature_name: (CrossRubyProduct crossruby) -> String + def make_args: (CrossRubyProduct crossruby) -> Array[String] def build: (BuildExecutor executor, CrossRubyProduct crossruby) -> void def do_extconf: (BuildExecutor executor, CrossRubyProduct crossruby) -> void def do_install_rb: (BuildExecutor executor, CrossRubyProduct crossruby) -> void - def cache_key: (Digest::SHA256 digest) -> void end class CrossRubyProduct < AutoconfProduct + include RubyWasm::_Cacheable + @params: BuildParams @rubies_dir: String @build_dir: String @@ -143,13 +185,12 @@ module RubyWasm attr_accessor debugflags: Array[String] attr_accessor xcflags: Array[String] attr_accessor xldflags: Array[String] - def initialize: (BuildParams params, String build_dir, String rubies_dir, BaseRubyProduct baseruby, BuildSource source, Toolchain toolchain, ?user_exts: Array[CrossRubyExtProduct]) -> void + def initialize: (BuildParams params, String build_dir, String rubies_dir, BaseRubyProduct baseruby, BuildSource source, Toolchain toolchain) -> void def configure: (BuildExecutor executor, ?reconfigure: bool) -> void def build_exts: (BuildExecutor executor) -> void def build: (BuildExecutor executor, ?remake: bool, ?reconfigure: bool) -> void def clean: (BuildExecutor executor) -> void def name: -> String - def cache_key: (Digest::SHA256 digest) -> void def build_dir: -> String def ext_build_dir: -> String def with_libyaml: (LibYAMLProduct libyaml) -> LibYAMLProduct diff --git a/sig/ruby_wasm/cli.rbs b/sig/ruby_wasm/cli.rbs new file mode 100644 index 0000000000..1392ef3079 --- /dev/null +++ b/sig/ruby_wasm/cli.rbs @@ -0,0 +1,24 @@ +module RubyWasm + class CLI + DEFAULT_RUBIES_DIR: string + + @stdout: IO + @stderr: IO + + def initialize: (stdout: IO, stderr: IO) -> void + + def build: (Array[String] args) -> void + + private + + def build_config: (Hash[untyped, untyped] options) -> Hash[untyped, untyped] + + def derive_packager: (Hash[untyped, untyped] options) -> Packager + def do_print_ruby_cache_key: (Packager) -> void + def do_build: (BuildExecutor, string tmpdir, Packager, Hash[untyped, untyped] options) -> void + end + + self.@logger: Logger? + def self.logger: () -> Logger + attr_accessor self.log_level: Symbol +end diff --git a/sig/ruby_wasm/ext.rbs b/sig/ruby_wasm/ext.rbs new file mode 100644 index 0000000000..115fd7b87f --- /dev/null +++ b/sig/ruby_wasm/ext.rbs @@ -0,0 +1,11 @@ +module RubyWasmExt + def self.preinitialize: (Array[Integer] module_bytes) -> Array[Integer] + + class WasiVfs + def initialize: () -> void + + def map_dir: (String guest_path, String host_path) -> void + + def pack: (Array[Integer] module_bytes) -> Array[Integer] + end +end \ No newline at end of file diff --git a/sig/ruby_wasm/packager.rbs b/sig/ruby_wasm/packager.rbs new file mode 100644 index 0000000000..999d147f3e --- /dev/null +++ b/sig/ruby_wasm/packager.rbs @@ -0,0 +1,91 @@ + +class RubyWasm::Packager + @definition: untyped + @config: Hash[untyped, untyped] + + def initialize: (untyped?, Hash[untyped, untyped]?) -> void + + def package: (RubyWasm::BuildExecutor, string dest_dir, untyped options) -> Array[Integer] + + @ruby_core_build: RubyWasm::Packager::Core? + def ruby_core_build: () -> RubyWasm::Packager::Core + + EXCLUDED_GEMS: Array[string] + + def specs: () -> Array[untyped] + def support_dynamic_linking?: () -> bool + + def root: () -> string + + type build_source = Hash[Symbol, (String | Array[String])] + def self.build_source_aliases: (string root) -> Hash[string, build_source] + + ALL_DEFAULT_EXTS: string + + def build_options: () -> Hash[Symbol, untyped] + def full_build_options: () -> Hash[Symbol, untyped] + + class Core + include RubyWasm::_Cacheable + + @packager: RubyWasm::Packager + def initialize: (RubyWasm::Packager) -> void + def build: (RubyWasm::BuildExecutor, untyped options) -> String + + extend Forwardable + + def artifact: () -> string + + private + + @build_strategy: BuildStrategy? + def build_strategy: () -> BuildStrategy + + class BuildStrategy + @packager: RubyWasm::Packager + def initialize: (RubyWasm::Packager) -> void + def build: (RubyWasm::BuildExecutor, untyped options) -> String + def specs_with_extensions: () -> Array[[untyped, Array[string]]] + end + + class DynamicLinking < RubyWasm::Packager::Core::BuildStrategy + end + + class StaticLinking < RubyWasm::Packager::Core::BuildStrategy + @build: RubyWasm::Build + def derive_build: () -> RubyWasm::Build + @user_exts: Array[RubyWasm::CrossRubyExtProduct]? + def user_exts: (RubyWasm::Build) -> Array[RubyWasm::CrossRubyExtProduct] + + def name: () -> string + end + end + + class FileSystem + @dest_dir: string + @packager: RubyWasm::Packager + @ruby_root: string + + def initialize: (string dest_dir, RubyWasm::Packager) -> void + def package_ruby_root: (String tarball, RubyWasm::BuildExecutor) -> void + def remove_stdlib: (RubyWasm::BuildExecutor) -> void + def package_gems: () -> void + + def setup_rb_content: () -> String + + def remove_non_runtime_files: (RubyWasm::BuildExecutor) -> void + + def bundle_dir: () -> String + def ruby_root: () -> string + + private + + def each_gem_content_path: () { (String, String) -> void } -> void + def each_gem_require_path: () { (String, String) -> void } -> void + def each_gem_extension_path: () { (String, String) -> void } -> void + + def bundle_relative_path: () -> String + def ruby_version: () -> String + def rubyarchdir: () -> String + end +end diff --git a/sig/ruby_wasm/util.rbs b/sig/ruby_wasm/util.rbs new file mode 100644 index 0000000000..d011e7a87f --- /dev/null +++ b/sig/ruby_wasm/util.rbs @@ -0,0 +1,5 @@ +module RubyWasm + module SizeFormatter + def self?.format: (Integer size) -> String + end +end \ No newline at end of file diff --git a/tasks/check.rake b/tasks/check.rake index c02e82999d..95b1f1fa5a 100644 --- a/tasks/check.rake +++ b/tasks/check.rake @@ -5,8 +5,8 @@ namespace :check do end task bindgen_c: :install_wit_bindgen do wits = [ - %w[ext/witapi/bindgen/rb-abi-guest.wit --export], - %w[ext/js/bindgen/rb-js-abi-host.wit --import] + %w[packages/gems/js/ext/witapi/bindgen/rb-abi-guest.wit --export], + %w[packages/gems/js/ext/js/bindgen/rb-js-abi-host.wit --import] ] wits.each do |wit| path, mode = wit @@ -20,9 +20,9 @@ namespace :check do "host", "js", "--import", - "ext/witapi/bindgen/rb-abi-guest.wit", + "packages/gems/js/ext/witapi/bindgen/rb-abi-guest.wit", "--export", - "ext/js/bindgen/rb-js-abi-host.wit", + "packages/gems/js/ext/js/bindgen/rb-js-abi-host.wit", "--out-dir", "packages/npm-packages/ruby-wasm-wasi/src/bindgen" ] diff --git a/tasks/ci.rake b/tasks/ci.rake index a28db8afbe..5057310c52 100644 --- a/tasks/ci.rake +++ b/tasks/ci.rake @@ -1,6 +1,7 @@ def latest_build_sources BUILD_SOURCES - .filter_map do |name, src| + .filter_map do |name| + src = RubyWasm::Packager.build_source_aliases(LIB_ROOT)[name] case src[:type] when "github" url = "repos/#{src[:repo]}/commits/#{src[:rev]}" @@ -21,7 +22,8 @@ def release_note |:-------:|:------:| EOS - BUILD_SOURCES.each do |name, source| + BUILD_SOURCES.each do |name| + source = RubyWasm::Packager.build_source_aliases(LIB_ROOT)[name] case source[:type] when "github" output += @@ -52,11 +54,8 @@ def rake_task_matrix { task: "build:#{build.name}", artifact: - Pathname - .new(build.crossruby.artifact) - .relative_path_from(LIB_ROOT) - .to_s, - artifact_name: File.basename(build.crossruby.artifact, ".tar.gz"), + Pathname.new(build.artifact).relative_path_from(LIB_ROOT).to_s, + artifact_name: File.basename(build.artifact, ".tar.gz"), builder: build.target, rubies_cache_key: ruby_cache_keys[build.name] } @@ -69,7 +68,7 @@ def rake_task_matrix artifact: "packages/npm-packages/#{pkg[:name]}/#{pkg[:name]}-*.tgz", artifact_name: "npm-#{pkg[:name]}", builder: pkg[:target], - rubies_cache_key: ruby_cache_keys[pkg[:build]] + rubies_cache_key: npm_pkg_rubies_cache_key(pkg) } # Run tests only if the package has 'test' script package_json = diff --git a/tasks/gem.rake b/tasks/gem.rake new file mode 100644 index 0000000000..b051a8272a --- /dev/null +++ b/tasks/gem.rake @@ -0,0 +1,19 @@ +require "bundler/gem_tasks" +require "rake/testtask" + +Rake::TestTask.new(:test) do |t| + t.libs << "test" + t.libs << "lib" + t.test_files = FileList["test/**/test_*.rb"] +end + +begin + require "rb_sys/extensiontask" + + RbSys::ExtensionTask.new("ruby_wasm") { |ext| ext.lib_dir = "lib/ruby_wasm" } +rescue LoadError => e + task :compile do + $stderr.puts "Skipping compilation of ruby_wasm extension: #{e.message}" + exit 1 + end +end diff --git a/tasks/packaging.rake b/tasks/packaging.rake index f7fad2afe7..606d8b8709 100644 --- a/tasks/packaging.rake +++ b/tasks/packaging.rake @@ -5,14 +5,83 @@ tools = { "WASMOPT" => wasi_sdk.wasm_opt } +def npm_pkg_build_command(pkg) + [ + "bundle", + "exec", + "rbwasm", + "build", + "--ruby-version", + pkg[:ruby_version], + "--target", + pkg[:target], + "--build-profile", + "full" + ] +end + +def npm_pkg_rubies_cache_key(pkg) + build_command = npm_pkg_build_command(pkg) + require "open3" + cmd = build_command + ["--print-ruby-cache-key"] + stdout, status = Open3.capture2(*cmd) + unless status.success? + raise "Command failed with status (#{status.exitstatus}): #{cmd.join ""}" + end + require "json" + JSON.parse(stdout)["hexdigest"] +end + namespace :npm do NPM_PACKAGES.each do |pkg| base_dir = Dir.pwd pkg_dir = "#{Dir.pwd}/packages/npm-packages/#{pkg[:name]}" namespace pkg[:name] do + build_command = npm_pkg_build_command(pkg) + + desc "Build ruby for npm package #{pkg[:name]}" + task "ruby" do + env = { + # Share ./build and ./rubies in the same workspace + "RUBY_WASM_ROOT" => base_dir + } + if gemfile_path = pkg[:gemfile] + env["BUNDLE_GEMFILE"] = File.join(base_dir, gemfile_path) + else + # Explicitly disable rubygems integration since Bundler finds + # Gemfile in the repo root directory. + build_command.push "--disable-gems" + end + dist_dir = File.join(pkg_dir, "dist") + mkdir_p dist_dir + if pkg[:target] == "wasm32-unknown-wasi" + sh env, + *build_command, + "--no-stdlib", + "-o", + File.join(dist_dir, "ruby.wasm") + sh env, + *build_command, + "-o", + File.join(dist_dir, "ruby.debug+stdlib.wasm") + sh wasi_sdk.wasm_opt, + "--strip-debug", + File.join(dist_dir, "ruby.wasm"), + "-o", + File.join(dist_dir, "ruby.wasm") + sh wasi_sdk.wasm_opt, + "--strip-debug", + File.join(dist_dir, "ruby.debug+stdlib.wasm"), + "-o", + File.join(dist_dir, "ruby+stdlib.wasm") + elsif pkg[:target] == "wasm32-unknown-emscripten" + sh env, *build_command, "-o", "/dev/null" + end + end + desc "Build npm package #{pkg[:name]}" - task "build" => ["build:#{pkg[:build]}"] do + task "build" => ["ruby"] do sh tools, "npm run build", chdir: pkg_dir end @@ -72,7 +141,7 @@ namespace :standalone do wasi_sdk.install_binaryen base_dir = Dir.pwd sh tools, - "./build-package.sh #{base_dir}/rubies/#{pkg[:build]}", + "./build-package.sh #{base_dir}/rubies/ruby-#{pkg[:build]}", chdir: pkg_dir end end