diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27465c4..a3af7f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,8 +16,8 @@ concurrency: cancel-in-progress: ${{ github.ref_name != 'main' }} jobs: - check: - name: Check + test: + name: Check & Test strategy: fail-fast: false matrix: @@ -25,10 +25,23 @@ jobs: - os: windows-latest - os: ubuntu-latest - os: macos-latest + - os: ubuntu-latest + env: + CARGO_BUILD_TARGET: wasm32-wasi + CARGO_TARGET_WASM32_WASI_RUNNER: /home/runner/.wasmtime/bin/wasmtime --dir=. runs-on: ${{ matrix.os }} + env: ${{ matrix.env || fromJSON('{}') }} steps: - uses: actions/checkout@v3 + - name: Install Wasm deps + if: matrix.env.CARGO_BUILD_TARGET == 'wasm32-wasi' + run: | + rustup target add wasm32-wasi + curl -LO https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk_20.0_amd64.deb + sudo dpkg --install wasi-sdk_20.0_amd64.deb + curl https://wasmtime.dev/install.sh -sSf | bash + - uses: Swatinem/rust-cache@v2 with: shared-key: ci @@ -37,10 +50,10 @@ jobs: - run: rustup show - name: Cargo Check - shell: bash - run: | - cargo check --all-targets --all-features --locked - cargo test --no-run --all-targets --all-features + run: cargo check --all-targets --all-features --locked + + - name: Cargo Test + run: cargo test --all-targets --all-features format: name: Format @@ -66,25 +79,3 @@ jobs: - run: rustup show - run: cargo clippy -- -D warnings - - test: - name: Test - strategy: - fail-fast: false - matrix: - include: - - os: windows-latest - - os: ubuntu-latest - - os: macos-latest - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v3 - - - uses: Swatinem/rust-cache@v2 - with: - shared-key: ci - save-if: false - - - run: rustup show - - - run: cargo test diff --git a/Cargo.lock b/Cargo.lock index ec34350..ff0d23a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,12 +48,6 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - [[package]] name = "cast" version = "0.3.0" @@ -62,20 +56,14 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", "libc", ] -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - [[package]] name = "ciborium" version = "0.2.1" @@ -144,8 +132,6 @@ dependencies = [ "num-traits", "once_cell", "oorandom", - "plotters", - "rayon", "regex", "serde", "serde_derive", @@ -164,49 +150,6 @@ dependencies = [ "itertools", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - [[package]] name = "either" version = "1.9.0" @@ -300,15 +243,6 @@ dependencies = [ "libc", ] -[[package]] -name = "js-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] - [[package]] name = "libc" version = "0.2.147" @@ -327,27 +261,12 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" -[[package]] -name = "log" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" - [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "num-traits" version = "0.2.16" @@ -357,16 +276,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "once_cell" version = "1.18.0" @@ -385,34 +294,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" -[[package]] -name = "plotters" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" - -[[package]] -name = "plotters-svg" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" -dependencies = [ - "plotters-backend", -] - [[package]] name = "proc-macro2" version = "1.0.66" @@ -431,28 +312,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - [[package]] name = "regex" version = "1.9.3" @@ -510,12 +369,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "serde" version = "1.0.183" @@ -645,70 +498,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index ad919a6..e137e4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,13 +32,13 @@ thiserror = "1" serde = { version = "1.0", optional = true, features = ["derive"] } [dev-dependencies] -criterion = "0.5" +criterion = { version = "0.5", default-features = false, features = ["cargo_bench_support"] } url = "2" # Used by benchmarks serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" [build-dependencies] -cc = { version = "1.0", features = ["parallel"] } +cc = { version = "1.0.83", features = ["parallel"] } link_args = "0.6" [package.metadata.docs.rs] diff --git a/build.rs b/build.rs index 0eea0de..1850795 100644 --- a/build.rs +++ b/build.rs @@ -11,20 +11,45 @@ fn main() { .file("./deps/ada.cpp") .include("./deps/ada.h") .include("./deps/ada_c.h") - .cpp(true); + .cpp(true) + .std("c++17"); + let compile_target_arch = env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH"); let compile_target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS"); let compile_target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV"); - if !(compile_target_os == "windows" && compile_target_env == "msvc") { - build.compiler("clang++"); - build.flag("-std=c++17"); - #[cfg(feature = "libcpp")] - { - build.cpp_set_stdlib("c++"); - println!("cargo:rustc-link-lib=c++"); + // Except for Emscripten target (which emulates POSIX environment), compile to Wasm via WASI SDK + // which is currently the only standalone provider of stdlib for compilation of C/C++ libraries. + if compile_target_arch.starts_with("wasm") && compile_target_os != "emscripten" { + let wasi_sdk = env::var("WASI_SDK").unwrap_or_else(|_| "/opt/wasi-sdk".to_owned()); + assert!( + std::path::Path::new(&wasi_sdk).exists(), + "WASI SDK not found at {wasi_sdk}" + ); + build.compiler(format!("{wasi_sdk}/bin/clang++")); + println!("cargo:rustc-link-search={wasi_sdk}/share/wasi-sysroot/lib/wasm32-wasi"); + // Wasm exceptions are new and not yet supported by WASI SDK. + build.flag("-fno-exceptions"); + // WASI SDK only has libc++ available. + build.cpp_set_stdlib("c++"); + // Explicitly link C++ ABI to avoid linking errors (it takes care of C++ -> C "lowering"). + println!("cargo:rustc-link-lib=c++abi"); + // Because Ada is a pure parsing library that doesn't need any OS syscalls, + // it's also possible to compile it to wasm32-unknown-unknown. + // This still requires WASI SDK for libc & libc++, but then we need a few hacks / overrides to get a pure Wasm w/o imports instead. + if compile_target_os == "unknown" { + build.target("wasm32-wasi"); + println!("cargo:rustc-link-lib=c"); + build.file("./deps/wasi_to_unknown.cpp"); } - } else { - build.flag("/std:c++17").static_crt(true); + } else if !(compile_target_os == "windows" && compile_target_env == "msvc") { + build.compiler("clang++"); + } + + let compiler = build.get_compiler(); + // Note: it's possible to use Clang++ explicitly on Windows as well, so this check + // should be specifically for "is target compiler MSVC" and not "is target OS Windows". + if compiler.is_like_msvc() { + build.static_crt(true); link_args::windows! { unsafe { no_default_lib( @@ -32,6 +57,8 @@ fn main() { ); } }; + } else if compiler.is_like_clang() && cfg!(feature = "libcpp") { + build.cpp_set_stdlib("c++"); } build.compile("ada"); diff --git a/deps/wasi_to_unknown.cpp b/deps/wasi_to_unknown.cpp new file mode 100644 index 0000000..1e65c54 --- /dev/null +++ b/deps/wasi_to_unknown.cpp @@ -0,0 +1,50 @@ +// Some shims for WASI symbols used by the WASI libc environment initializer, +// but not actually required by Ada. This allows to compile Ada Rust to +// wasm32-unknown-unknown with WASI SDK. + +#include + +extern "C" { + +int32_t __imported_wasi_snapshot_preview1_environ_get(int32_t, int32_t) { + __builtin_unreachable(); +} + +int32_t __imported_wasi_snapshot_preview1_environ_sizes_get(int32_t, int32_t) { + __builtin_unreachable(); +} + +int32_t __imported_wasi_snapshot_preview1_fd_close(int32_t) { + __builtin_unreachable(); +} + +int32_t __imported_wasi_snapshot_preview1_fd_fdstat_get(int32_t, int32_t) { + __builtin_unreachable(); +} + +int32_t __imported_wasi_snapshot_preview1_fd_read(int32_t, + int32_t, + int32_t, + int32_t) { + __builtin_unreachable(); +} + +int32_t __imported_wasi_snapshot_preview1_fd_seek(int32_t, + int64_t, + int32_t, + int32_t) { + __builtin_unreachable(); +} + +int32_t __imported_wasi_snapshot_preview1_fd_write(int32_t, + int32_t, + int32_t, + int32_t) { + __builtin_unreachable(); +} + +_Noreturn void __imported_wasi_snapshot_preview1_proc_exit(int32_t) { + __builtin_unreachable(); +} + +} // extern "C"