diff --git a/.github/workflows/test-sys.yaml b/.github/workflows/test-sys.yaml index 3afacb5b53f..6e7402fbc54 100644 --- a/.github/workflows/test-sys.yaml +++ b/.github/workflows/test-sys.yaml @@ -210,7 +210,7 @@ jobs: - name: Test if: matrix.run_test && matrix.os != 'windows-2019' run: | - make test + make build-capi && make package-capi && export WASMER_DIR=`pwd`/package && make test env: TARGET: ${{ matrix.target }} TARGET_DIR: target/${{ matrix.target }}/release @@ -235,12 +235,14 @@ jobs: CARGO_TARGET: --target ${{ matrix.target }} - name: Test if: matrix.run_test && matrix.os == 'windows-2019' + shell: bash run: | - make test + make build-capi && make package-capi && export WASMER_DIR=`pwd`/package && make test - name: Test C API if: matrix.run_test_capi && matrix.os == 'windows-2019' + shell: bash run: | - make test-capi + export WASMER_DIR=`pwd`/package && make test-capi - name: Build Doc if: matrix.run_build_docs run: | diff --git a/Cargo.lock b/Cargo.lock index b8703ce5106..ac52e11755a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -57,15 +57,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.63" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26fa4d7e3f2eebadf743988fc8aec9fa9a9e82611acafd77c1462ed6262440a" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "arbitrary" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8931eb436ab9bf1980c6cb2b9d1ba5390cd6793b2c6e2d2ea8147da3570c2a2e" +checksum = "f44124848854b941eafdb34f05b3bcf59472f643c7e151eba7c2b69daa469ed5" dependencies = [ "derive_arbitrary", ] @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -279,7 +279,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb" dependencies = [ - "clap 3.2.20", + "clap 3.2.21", "heck", "indexmap", "log", @@ -364,9 +364,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.20" +version = "3.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" +checksum = "1ed5341b2301a26ab80be5cbdced622e80ed808483c52e45e3310a877d3b37d7" dependencies = [ "atty", "bitflags", @@ -759,9 +759,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d749b611838b7e92cba33b8552187059f2dc32f91d4d66bdc4fe5da9526b4e07" +checksum = "226ad66541d865d7a7173ad6a9e691c33fdb910ac723f4bc734b3e5294a1f931" dependencies = [ "proc-macro2", "quote", @@ -1177,9 +1177,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.47" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" +checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1281,9 +1281,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "d8bf247779e67a9082a4790b45e71ac7cfd1321331a5c856a74a9faebdab78d0" dependencies = [ "either", ] @@ -1311,9 +1311,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1474,9 +1474,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] @@ -1587,9 +1587,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "oorandom" @@ -1666,9 +1666,9 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pest" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4" +checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" dependencies = [ "thiserror", "ucd-trie", @@ -1688,9 +1688,9 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "716b4eeb6c4a1d3ecc956f75b43ec2e8e8ba80026413e70a3f41fd3313d3492b" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -2098,7 +2098,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.13", + "semver 1.0.14", ] [[package]] @@ -2220,9 +2220,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -2562,18 +2562,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" +checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" +checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" dependencies = [ "proc-macro2", "quote", @@ -2752,9 +2752,9 @@ dependencies = [ [[package]] name = "ucd-trie" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "unicase" @@ -2767,15 +2767,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unix_mode" @@ -2847,9 +2847,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2857,9 +2857,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -2872,9 +2872,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2884,9 +2884,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2894,9 +2894,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -2907,15 +2907,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "wasm-bindgen-test" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "513df541345bb9fcc07417775f3d51bbb677daf307d8035c0afafd87dc2e6599" +checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d" dependencies = [ "console_error_panic_hook", "js-sys", @@ -2927,9 +2927,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6150d36a03e90a3cf6c12650be10626a9902d70c5270fd47d7a47e5389a10d56" +checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7" dependencies = [ "proc-macro2", "quote", @@ -3031,11 +3031,22 @@ dependencies = [ "wasmer-compiler-llvm", "wasmer-compiler-singlepass", "wasmer-emscripten", + "wasmer-inline-c", "wasmer-middlewares", "wasmer-types", "wasmer-wasi", ] +[[package]] +name = "wasmer-c-api-test-runner" +version = "0.1.0" +dependencies = [ + "cc", + "regex", + "target-lexicon 0.11.2", + "walkdir", +] + [[package]] name = "wasmer-cache" version = "3.0.0-beta" @@ -3050,6 +3061,16 @@ dependencies = [ "wasmer-compiler-singlepass", ] +[[package]] +name = "wasmer-capi-examples-runner" +version = "0.1.0" +dependencies = [ + "cc", + "regex", + "target-lexicon 0.11.2", + "walkdir", +] + [[package]] name = "wasmer-cli" version = "3.0.0-beta" @@ -3058,7 +3079,7 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 3.2.20", + "clap 3.2.21", "colored 2.0.0", "dirs", "distance", @@ -3119,7 +3140,7 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 3.2.20", + "clap 3.2.21", "colored 2.0.0", "distance", "fern", @@ -3166,7 +3187,7 @@ dependencies = [ "rayon", "regex", "rustc_version 0.4.0", - "semver 1.0.13", + "semver 1.0.14", "smallvec", "target-lexicon 0.12.4", "wasmer-compiler", @@ -3218,6 +3239,34 @@ dependencies = [ "wasmer-types", ] +[[package]] +name = "wasmer-inline-c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2405c99de49dc05338e5ed2eb397fe70b7128340d960507d0ba716f7d29a91a" +dependencies = [ + "assert_cmd", + "cc", + "lazy_static", + "predicates", + "regex", + "rustc_version 0.3.3", + "target-lexicon 0.11.2", + "tempfile", + "wasmer-inline-c-macro", +] + +[[package]] +name = "wasmer-inline-c-macro" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058581df4116836c51906e346d6f49ad1b1de0129243fba6b1e1d3c206cd36d1" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version 0.3.3", +] + [[package]] name = "wasmer-integration-tests-cli" version = "3.0.0-beta" @@ -3561,9 +3610,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 6ee42dd2c37..bed30b2181a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,8 @@ members = [ "lib/wasi-types", "lib/wasi-experimental-io-devices", "lib/wasi-local-networking", + "lib/c-api/tests/wasmer-c-api-test-runner", + "lib/c-api/examples/wasmer-capi-examples-runner", "lib/types", "tests/wasi-wast", "tests/lib/wast", diff --git a/Makefile b/Makefile index f735fe1632c..557ea873a19 100644 --- a/Makefile +++ b/Makefile @@ -602,12 +602,16 @@ package-capi: mkdir -p "package/lib" cp lib/c-api/wasmer.h* package/include cp lib/c-api/wasmer_wasm.h* package/include - cp lib/c-api/wasm.h* package/include + cp lib/c-api/tests/wasm-c-api/include/wasm.h* package/include cp lib/c-api/README.md package/include/README.md if [ -f $(TARGET_DIR)/wasmer.dll ]; then \ cp $(TARGET_DIR)/wasmer.dll package/lib/wasmer.dll ;\ fi + + if [ -f $(TARGET_DIR)/wasmer.dll.lib ]; then \ + cp $(TARGET_DIR)/wasmer.dll.lib package/lib/wasmer.dll.lib ;\ + fi if [ -f $(TARGET_DIR)/wasmer.lib ]; then \ cp $(TARGET_DIR)/wasmer.lib package/lib/wasmer.lib ;\ fi diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 072da4e3d9f..ac6b2728364 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -41,7 +41,12 @@ paste = "1.0" [dev-dependencies] field-offset = "0.3.3" -inline-c = "0.1.5" + +[target.'cfg(target_os = "windows")'.dev-dependencies] +wasmer-inline-c = "0.1.1" + +[target.'cfg(not(target_os = "windows"))'.dev-dependencies] +inline-c = "0.1.7" [features] default = [ diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 8fb05bc97ed..98400014c00 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -1,7 +1,7 @@ //! This build script aims at: //! //! * generating the C header files for the C API, -//! * setting `inline-c` up. +//! * setting `wasmer-inline-c` up. use cbindgen::{Builder, Language}; use std::{ @@ -83,7 +83,7 @@ fn main() { build_cdylib_link_arg(); } -/// Check whether we should build the C API headers or set `inline-c` up. +/// Check whether we should build the C API headers or set `wasmer-inline-c` up. fn running_self() -> bool { env::var("DOCS_RS").is_err() && env::var("_CBINDGEN_IS_RUNNING").is_err() diff --git a/lib/c-api/examples/.gitignore b/lib/c-api/examples/.gitignore index 259f7fb0864..be618742b91 100644 --- a/lib/c-api/examples/.gitignore +++ b/lib/c-api/examples/.gitignore @@ -1,6 +1,7 @@ * *.o +*.exe # Unignore files ending with `.c` (i.e. `wasm-c-api-wasi.c`) !*.c @@ -8,3 +9,5 @@ !Makefile !assets !assets/* +!wasmer-capi-examples-runner +!wasmer-capi-examples-runner/* diff --git a/lib/c-api/examples/Makefile b/lib/c-api/examples/Makefile index 884619acaf1..9bea95c12fc 100644 --- a/lib/c-api/examples/Makefile +++ b/lib/c-api/examples/Makefile @@ -3,15 +3,28 @@ WASMER_DIR:=$(realpath $(WASMER_DIR)) $(info Using provided WASMER_DIR=$(WASMER_DIR)) ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) +ROOT_DIR_PARENT:=$(shell dirname $(ROOT_DIR)) + +MSVC_CFLAGS:="" +MSVC_LDFLAGS:="" +MSVC_LDLIBS:="" ifeq (,$(wildcard $(WASMER_DIR)/bin/wasmer)) - CFLAGS = -g -I$(ROOT_DIR)/../tests -I$(WASMER_DIR)/include + CFLAGS = -g -I $(ROOT_DIR)/ -I $(WASMER_DIR)/include LDFLAGS = -Wl,-rpath,$(WASMER_DIR)/lib - LDLIBS = -L$(WASMER_DIR)/lib -lwasmer + LDLIBS = -L $(WASMER_DIR)/lib -lwasmer + + MSVC_CFLAGS:= /DEBUG /I $(ROOT_DIR)/ /I $(WASMER_DIR)/include + MSVC_LDFLAGS:= "" + MSVC_LDLIBS:= /LIBPATH:$(WASMER_DIR)/lib wasmer.dll.lib else - CFLAGS = -g -I$(ROOT_DIR)/../tests -I$(shell $(WASMER_DIR)/bin/wasmer config --includedir) + CFLAGS = -g -I $(ROOT_DIR)/ -I $(shell $(WASMER_DIR)/bin/wasmer config --includedir) LDFLAGS = -Wl,-rpath,$(shell $(WASMER_DIR)/bin/wasmer config --libdir) LDLIBS = $(shell $(WASMER_DIR)/bin/wasmer config --libs) + + MSVC_CFLAGS:= /DEBUG /I $(ROOT_DIR)/ /I $(shell $(WASMER_DIR)/bin/wasmer config --includedir) + MSVC_LDFLAGS:= "" + MSVC_LDLIBS:= /LIBPATH:$(shell $(WASMER_DIR)/bin/wasmer config --libs) wasmer.dll.lib endif $(info * CFLAGS: $(CFLAGS)) @@ -20,44 +33,10 @@ $(info * LDLIBS: $(LDLIBS)) ALL = deprecated-header early-exit instance imports-exports exports-function exports-global memory memory2 features wasi -.SILENT: deprecated-header deprecated-header.o -deprecated-header: deprecated-header.o - -.SILENT: early-exit early-exit.o -early-exit: early-exit.o - -.SILENT: instance instance.o -instance: instance.o - -.SILENT: imports-exports imports-exports.o -imports-exports: imports-exports.o - -.SILENT: exports-function exports-function.o -exports-function: exports-function.o - -.SILENT: exports-global exports-global.o -exports-global: exports-global.o - -.SILENT: memory memory.o -memory: memory.o - -.SILENT: memory2 memory2.o -memory2: memory2.o - -.SILENT: features features.o -features: features.o - -.SILENT: wasi wasi.o -wasi: wasi.o - -.PHONY: all -all: $(ALL) - .PHONY: run .SILENT: run -run: $(ALL) - set -o errexit; \ - $(foreach example,$?,echo Running \"$(example)\" example; ./$(example); echo;) +run: + WASMER_DIR="$(WASMER_DIR)" ROOT_DIR="$(ROOT_DIR)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" LDLIBS="$(LDLIBS)" cargo test --manifest-path="./wasmer-capi-examples-runner/Cargo.toml" -- --nocapture 2>&1 .SILENT: clean .PHONY: clean diff --git a/lib/c-api/examples/early-exit.c b/lib/c-api/examples/early-exit.c index d2410ca8baf..6c4bb08156e 100644 --- a/lib/c-api/examples/early-exit.c +++ b/lib/c-api/examples/early-exit.c @@ -45,7 +45,7 @@ int main(int argc, const char *argv[]) { // Load binary. printf("Loading binary...\n"); - FILE *file = fopen("assets/call_trap.wasm", "r"); + FILE *file = fopen("assets/call_trap.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; diff --git a/lib/c-api/examples/wasi.c b/lib/c-api/examples/wasi.c index 529268e8591..7771560aa05 100644 --- a/lib/c-api/examples/wasi.c +++ b/lib/c-api/examples/wasi.c @@ -38,7 +38,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("assets/qjs.wasm", "r"); + FILE* file = fopen("assets/qjs.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -49,7 +49,7 @@ int main(int argc, const char* argv[]) { wasm_byte_vec_t binary; wasm_byte_vec_new_uninitialized(&binary, file_size); if (fread(binary.data, file_size, 1, file) != 1) { - printf("> Error loading module!\n"); + printf("> Error initializing module!\n"); return 1; } fclose(file); @@ -137,12 +137,12 @@ int main(int argc, const char* argv[]) { } printf("Call completed\n"); - { - FILE *memory_stream; - char* stdout; - size_t stdout_size = 0; + if(true) { - memory_stream = open_memstream(&stdout, &stdout_size); + // NOTE: previously, this used open_memstream, + // which is not cross-platform + FILE *memory_stream = NULL; + memory_stream = tmpfile(); // stdio.h if (NULL == memory_stream) { printf("> Error creating a memory stream.\n"); @@ -161,15 +161,20 @@ int main(int argc, const char* argv[]) { } if (data_read_size > 0) { - stdout_size += data_read_size; fwrite(buffer, sizeof(char), data_read_size, memory_stream); } } while (BUF_SIZE == data_read_size); + // print memory_stream + rewind(memory_stream); + fputs("WASI Stdout: ", stdout); + char buffer2[256]; + while (!feof(memory_stream)) { + if (fgets(buffer2, 256, memory_stream) == NULL) break; + fputs(buffer2, stdout); + } + fputs("\n", stdout); fclose(memory_stream); - - printf("WASI Stdout: `%.*s`\n", (int) stdout_size, stdout); - free(stdout); } diff --git a/lib/c-api/examples/wasmer-capi-examples-runner/.gitignore b/lib/c-api/examples/wasmer-capi-examples-runner/.gitignore new file mode 100644 index 00000000000..1b04d33b6ab --- /dev/null +++ b/lib/c-api/examples/wasmer-capi-examples-runner/.gitignore @@ -0,0 +1,4 @@ +*.bat +*.ilk +*.pdb +*.exe \ No newline at end of file diff --git a/lib/c-api/examples/wasmer-capi-examples-runner/Cargo.toml b/lib/c-api/examples/wasmer-capi-examples-runner/Cargo.toml new file mode 100644 index 00000000000..67425ff2eff --- /dev/null +++ b/lib/c-api/examples/wasmer-capi-examples-runner/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "wasmer-capi-examples-runner" +version = "0.1.0" +edition = "2021" +license = "MIT" + +[dependencies] +cc = "1.0" +target-lexicon = "0.11" +regex = "1.6" +walkdir = "2.3.2" \ No newline at end of file diff --git a/lib/c-api/examples/wasmer-capi-examples-runner/src/lib.rs b/lib/c-api/examples/wasmer-capi-examples-runner/src/lib.rs new file mode 100644 index 00000000000..77030cc63b5 --- /dev/null +++ b/lib/c-api/examples/wasmer-capi-examples-runner/src/lib.rs @@ -0,0 +1,494 @@ +#[cfg(test)] +use std::error::Error; + +#[cfg(test)] +static INCLUDE_REGEX: &str = "#include \"(.*)\""; + +#[derive(Default)] +pub struct RemoveTestsOnDrop {} + +impl Drop for RemoveTestsOnDrop { + fn drop(&mut self) { + return; + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + for entry in std::fs::read_dir(&manifest_dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + let extension = path.extension().and_then(|s| s.to_str()); + if extension == Some("obj") || extension == Some("exe") || extension == Some("o") { + println!("removing {}", path.display()); + let _ = std::fs::remove_file(&path); + } + } + if let Some(parent) = std::path::Path::new(&manifest_dir).parent() { + for entry in std::fs::read_dir(&parent).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + let extension = path.extension().and_then(|s| s.to_str()); + if extension == Some("obj") || extension == Some("exe") || extension == Some("o") { + println!("removing {}", path.display()); + let _ = std::fs::remove_file(&path); + } + } + } + } +} + +fn make_package() { + let wasmer_root_dir = find_wasmer_base_dir(); + let _ = std::fs::create_dir_all(&format!("{wasmer_root_dir}/package/lib")); + let _ = std::fs::create_dir_all(&format!("{wasmer_root_dir}/package/include")); + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/lib/c-api/tests/wasm.h"), + &format!("{wasmer_root_dir}/package/include/wasm.h"), + ); + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/lib/c-api/tests/wasmer.h"), + &format!("{wasmer_root_dir}/package/include/wasmer.h"), + ); + #[cfg(target_os = "windows")] + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/target/release/wasmer.dll"), + &format!("{wasmer_root_dir}/package/lib"), + ); + #[cfg(target_os = "windows")] + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/target/release/wasmer.dll.lib"), + &format!("{wasmer_root_dir}/package/lib"), + ); + #[cfg(not(target_os = "windows"))] + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/target/release/libwasmer.so"), + &format!("{wasmer_root_dir}/package/lib"), + ); + #[cfg(not(target_os = "windows"))] + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/target/release/libwasmer.lib"), + &format!("{wasmer_root_dir}/package/lib"), + ); + println!("copying done (make package)"); +} + +#[derive(Debug)] +pub struct Config { + pub wasmer_dir: String, + pub root_dir: String, +} + +impl Config { + pub fn get() -> Config { + let mut config = Config { + wasmer_dir: std::env::var("WASMER_DIR").unwrap_or_default(), + root_dir: std::env::var("ROOT_DIR").unwrap_or_default(), + }; + + // resolve the path until the /wasmer root directory + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let wasmer_base_dir = find_wasmer_base_dir(); + + if config.wasmer_dir.is_empty() { + println!("manifest dir = {manifest_dir}, wasmer root dir = {wasmer_base_dir}"); + config.wasmer_dir = wasmer_base_dir.clone() + "/package"; + if !std::path::Path::new(&config.wasmer_dir).exists() { + println!("running make build-capi..."); + // run make build-capi + let mut cmd = std::process::Command::new("make"); + cmd.arg("build-capi"); + cmd.current_dir(wasmer_base_dir.clone()); + let result = cmd.output(); + println!("make build-capi: {result:#?}"); + + println!("running make package-capi..."); + // run make package + let mut cmd = std::process::Command::new("make"); + cmd.arg("package-capi"); + cmd.current_dir(wasmer_base_dir.clone()); + let result = cmd.output(); + make_package(); + println!("make package: {result:#?}"); + + println!("list {}", config.wasmer_dir); + match std::fs::read_dir(&config.wasmer_dir) { + Ok(o) => { + for entry in o { + let entry = entry.unwrap(); + let path = entry.path(); + println!(" {:?}", path.file_name()); + } + } + Err(e) => { + println!("error in reading config.wasmer_dir: {e}"); + } + }; + } + } + if config.root_dir.is_empty() { + config.root_dir = wasmer_base_dir + "/lib/c-api/examples"; + } + + config + } +} + +fn find_wasmer_base_dir() -> String { + let wasmer_base_dir = env!("CARGO_MANIFEST_DIR"); + let mut path2 = wasmer_base_dir.split("wasmer").collect::>(); + path2.pop(); + let mut wasmer_base_dir = path2.join("wasmer"); + + if wasmer_base_dir.contains("wasmer/lib/c-api") { + wasmer_base_dir = wasmer_base_dir + .split("wasmer/lib/c-api") + .next() + .unwrap() + .to_string() + + "wasmer"; + } else if wasmer_base_dir.contains("wasmer\\lib\\c-api") { + wasmer_base_dir = wasmer_base_dir + .split("wasmer\\lib\\c-api") + .next() + .unwrap() + .to_string() + + "wasmer"; + } + + wasmer_base_dir +} + +#[cfg(test)] +pub const TESTS: &[&str] = &[ + "deprecated-header", + "early-exit", + "instance", + "imports-exports", + "exports-function", + "exports-global", + "memory", + "memory2", + "features", + "wasi", +]; + +#[test] +fn test_run() { + let _drop = RemoveTestsOnDrop::default(); + let config = Config::get(); + println!("config: {:#?}", config); + + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let host = target_lexicon::HOST.to_string(); + let target = &host; + + let wasmer_dll_dir = format!("{}/lib", config.wasmer_dir); + let libwasmer_so_path = format!("{}/lib/libwasmer.so", config.wasmer_dir); + let path = std::env::var("PATH").unwrap_or_default(); + let newpath = format!("{wasmer_dll_dir};{path}"); + let exe_dir = match std::path::Path::new(&manifest_dir).parent() { + Some(parent) => format!("{}", parent.display()), + None => format!("{manifest_dir}"), + }; + + for test in TESTS.iter() { + let mut manifest_dir_parent = std::path::Path::new(&manifest_dir); + let mut manifest_dir_parent = manifest_dir_parent.parent().unwrap(); + let c_file_path = manifest_dir_parent.join(&format!("{test}.c")); + + if target.contains("msvc") { + let mut build = cc::Build::new(); + let mut build = build + .cargo_metadata(false) + .warnings(true) + .static_crt(true) + .extra_warnings(true) + .warnings_into_errors(false) + .debug(true) + .host(&host) + .target(target) + .opt_level(1); + + let compiler = build.try_get_compiler().unwrap(); + let mut command = compiler.to_command(); + + command.arg(&format!("{}", c_file_path.display())); + if !config.wasmer_dir.is_empty() { + command.arg("/I"); + command.arg(&format!("{}/include/", config.wasmer_dir)); + let mut log = String::new(); + fixup_symlinks( + &[ + format!("{}/include", config.wasmer_dir), + format!("{}", config.root_dir), + ], + &mut log, + &config.root_dir, + ) + .expect(&format!("failed to fix symlinks: {log}")); + println!("{log}"); + } + + let exe_outpath = manifest_dir_parent.join(&format!("{test}.exe")); + let exe_outpath = format!("{}", exe_outpath.display()); + println!("compiling exe to {exe_outpath}"); + + command.arg(&format!("/Fo:{}/", manifest_dir_parent.display())); + command.arg("/link"); + if !config.wasmer_dir.is_empty() { + command.arg(&format!("/LIBPATH:{}/lib", config.wasmer_dir)); + command.arg(&format!("{}/lib/wasmer.dll.lib", config.wasmer_dir)); + } + command.arg(&format!("/OUT:{exe_outpath}")); + + // read vcvars into file, append command, then execute the bat + + println!("compiling WINDOWS {test}: {command:?}"); + + let vcvars_bat_path = find_vcvarsall(&compiler).expect("no vcvarsall.bat"); + let vcvars_bat_path_parent = std::path::Path::new(&vcvars_bat_path).parent().unwrap(); + let vcvars_modified_output = vcvars_bat_path_parent.join("compile-windows.bat"); + let vcvars_bat_file = std::fs::read_to_string(&vcvars_bat_path).unwrap(); + let batch_formatted = format!("{}\\", vcvars_bat_path_parent.display()); + let vcvars_bat_file = vcvars_bat_file + .replace("%~dp0", &batch_formatted.replace("\\", "\\\\")) + .replace("\"%1\"", "\"x64\""); + let vcvars_modified = format!("{vcvars_bat_file}\r\n{command:?}"); + let path = std::path::Path::new(&manifest_dir).join("compile-windows.bat"); + println!("outputting batch to {}", path.display()); + std::fs::write(&path, vcvars_modified).unwrap(); + + print_wasmer_root_to_stdout(&config); + + let mut vcvars = std::process::Command::new("cmd"); + vcvars.arg("/C"); + vcvars.arg(&path); + vcvars.arg("x64"); + vcvars.current_dir(&vcvars_bat_path_parent); + + // compile + let output = vcvars + .output() + .map_err(|e| format!("failed to compile {command:#?}: {e}")) + .unwrap(); + if !output.status.success() { + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stdout: {}", String::from_utf8_lossy(&output.stderr)); + print_wasmer_root_to_stdout(&config); + panic!("failed to compile {test}"); + } + + if !std::path::Path::new(&exe_outpath).exists() { + panic!("error: {exe_outpath} does not exist"); + } + if !std::path::Path::new(&wasmer_dll_dir) + .join("wasmer.dll") + .exists() + { + panic!("error: {wasmer_dll_dir} has no wasmer.dll"); + } + // execute + let mut command = std::process::Command::new(&exe_outpath); + command.env("PATH", newpath.clone()); + command.current_dir(exe_dir.clone()); + println!("executing {test}: {command:?}"); + println!("setting current dir = {exe_dir}"); + let output = command + .output() + .expect(&format!("failed to run {command:#?}")); + if !output.status.success() { + println!("{output:#?}"); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + print_wasmer_root_to_stdout(&config); + panic!("failed to execute {test}"); + } + } else { + let compiler_cmd = match std::process::Command::new("cc").output() { + Ok(_) => "cc", + Err(_) => "gcc", + }; + + let mut command = std::process::Command::new(compiler_cmd); + + if !config.wasmer_dir.is_empty() { + command.arg("-I"); + command.arg(&format!("{}/include", config.wasmer_dir)); + let mut log = String::new(); + fixup_symlinks( + &[ + format!("{}/include", config.wasmer_dir), + format!("{}", config.root_dir), + ], + &mut log, + &config.root_dir, + ) + .expect(&format!("failed to fix symlinks: {log}")); + } + command.arg(&c_file_path); + if !config.wasmer_dir.is_empty() { + command.arg("-L"); + command.arg(&format!("{}/lib/", config.wasmer_dir)); + command.arg(&format!("-lwasmer")); + command.arg(&format!("-Wl,-rpath,{}/lib/", config.wasmer_dir)); + } + command.arg("-o"); + command.arg(&format!("{manifest_dir}/../{test}")); + + // cc -g -IC:/Users/felix/Development/wasmer/lib/c-api/examples/../tests + // -IC:/Users/felix/Development/wasmer/package/include + // -c -o deprecated-header.o deprecated-header.c + + /* + cc -I /home/runner/work/wasmer/wasmer/lib/c-api/tests + -I" "/home/runner/work/wasmer/wasmer/package/include" + "/home/runner/work/wasmer/wasmer/lib/c-api/tests/wasmer-c-api-test-runner/../wasm-c-api/example/callback.c" + "-L/home/runner/work/wasmer/wasmer/package/lib" + "-lwasmer" + "-o" "/home/runner/work/wasmer/wasmer/lib/c-api/tests/wasmer-c-api-test-runner/../wasm-c-api/example/callback" + */ + + println!("compiling LINUX {command:#?}"); + // compile + let output = command + .output() + .map_err(|e| format!("failed to compile {command:#?}: {e}")) + .unwrap(); + if !output.status.success() { + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + print_wasmer_root_to_stdout(&config); + panic!("failed to compile {test}: {command:#?}"); + } + + // execute + let mut command = std::process::Command::new(&format!("{manifest_dir}/../{test}")); + command.env("LD_PRELOAD", libwasmer_so_path.clone()); + command.current_dir(exe_dir.clone()); + println!("execute: {command:#?}"); + let output = command + .output() + .expect(&format!("failed to run {command:#?}")); + if !output.status.success() { + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stdout: {}", String::from_utf8_lossy(&output.stderr)); + print_wasmer_root_to_stdout(&config); + panic!("failed to execute {test} executable"); + } + } + } +} + +#[cfg(test)] +fn print_wasmer_root_to_stdout(config: &Config) { + println!("print_wasmer_root_to_stdout"); + + use walkdir::WalkDir; + + for entry in WalkDir::new(&config.wasmer_dir) + .into_iter() + .filter_map(Result::ok) + { + let f_name = String::from(entry.path().canonicalize().unwrap().to_string_lossy()); + println!("{f_name}"); + } + + for entry in WalkDir::new(&config.root_dir) + .into_iter() + .filter_map(Result::ok) + { + let f_name = String::from(entry.path().canonicalize().unwrap().to_string_lossy()); + println!("{f_name}"); + } + + println!("printed"); +} + +#[cfg(test)] +fn fixup_symlinks( + include_paths: &[String], + log: &mut String, + root_dir: &str, +) -> Result<(), Box> { + let source = std::path::Path::new(root_dir) + .join("lib") + .join("c-api") + .join("tests") + .join("wasm-c-api") + .join("include") + .join("wasm.h"); + let target = std::path::Path::new(root_dir) + .join("lib") + .join("c-api") + .join("tests") + .join("wasm.h"); + println!("copying {} -> {}", source.display(), target.display()); + let _ = std::fs::copy(source, target); + + log.push_str(&format!("include paths: {include_paths:?}")); + for i in include_paths { + let i = i.replacen("-I", "", 1); + let mut paths_headers = Vec::new(); + let readdir = match std::fs::read_dir(&i) { + Ok(o) => o, + Err(_) => continue, + }; + for entry in readdir { + let entry = entry?; + let path = entry.path(); + let path_display = format!("{}", path.display()); + if path_display.ends_with("h") { + paths_headers.push(path_display); + } + } + fixup_symlinks_inner(&paths_headers, log)?; + } + + Ok(()) +} + +#[cfg(test)] +fn fixup_symlinks_inner(include_paths: &[String], log: &mut String) -> Result<(), Box> { + log.push_str(&format!("fixup symlinks: {include_paths:#?}")); + let regex = regex::Regex::new(INCLUDE_REGEX).unwrap(); + for path in include_paths.iter() { + let file = match std::fs::read_to_string(&path) { + Ok(o) => o, + _ => continue, + }; + let lines_3 = file.lines().take(3).collect::>(); + log.push_str(&format!("first 3 lines of {path:?}: {:#?}\n", lines_3)); + + let parent = std::path::Path::new(&path).parent().unwrap(); + if let Ok(symlink) = std::fs::read_to_string(parent.clone().join(&file)) { + log.push_str(&format!("symlinking {path:?}\n")); + std::fs::write(&path, symlink)?; + } + + // follow #include directives and recurse + let filepaths = regex + .captures_iter(&file) + .map(|c| c[1].to_string()) + .collect::>(); + log.push_str(&format!("regex captures: ({path:?}): {:#?}\n", filepaths)); + let joined_filepaths = filepaths + .iter() + .filter_map(|s| { + let path = parent.clone().join(s); + Some(format!("{}", path.display())) + }) + .collect::>(); + fixup_symlinks_inner(&joined_filepaths, log)?; + } + Ok(()) +} + +#[cfg(test)] +fn find_vcvarsall(compiler: &cc::Tool) -> Option { + if !compiler.is_like_msvc() { + return None; + } + + let path = compiler.path(); + let path = format!("{}", path.display()); + let split = path.split("VC").nth(0)?; + + Some(format!("{split}VC\\Auxiliary\\Build\\vcvarsall.bat")) +} diff --git a/lib/c-api/src/error.rs b/lib/c-api/src/error.rs index f47caec1b92..adb988440ed 100644 --- a/lib/c-api/src/error.rs +++ b/lib/c-api/src/error.rs @@ -10,7 +10,7 @@ //! # Example //! //! ```rust -//! # use inline_c::assert_c; +//! # use wasmer_inline_c::assert_c; //! # fn main() { //! # (assert_c! { //! # #include "tests/wasmer.h" diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 505109f9bbc..67a3c730196 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -89,7 +89,7 @@ pub struct wasm_config_t { /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -128,7 +128,7 @@ pub extern "C" fn wasm_config_new() -> Box { /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -157,7 +157,7 @@ pub extern "C" fn wasm_config_delete(_config: Option>) {} /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -211,7 +211,7 @@ pub extern "C" fn wasm_config_set_compiler( /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -315,7 +315,7 @@ cfg_if! { /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -440,7 +440,10 @@ pub extern "C" fn wasm_engine_new_with_config( #[cfg(test)] mod tests { + #[cfg(not(target_os = "windows"))] use inline_c::assert_c; + #[cfg(target_os = "windows")] + use wasmer_inline_c::assert_c; #[test] fn test_engine_new() { diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index b6f8a4f74f5..0c911cf3943 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -97,7 +97,10 @@ pub unsafe extern "C" fn wasm_global_type( #[cfg(test)] mod tests { + #[cfg(not(target_os = "windows"))] use inline_c::assert_c; + #[cfg(target_os = "windows")] + use wasmer_inline_c::assert_c; #[test] fn test_set_host_global_immutable() { diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index 9fe5eca1d4a..fdd2a419569 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -132,7 +132,10 @@ pub extern "C" fn wasm_extern_as_table(r#extern: Option<&wasm_extern_t>) -> Opti #[cfg(test)] mod tests { + #[cfg(not(target_os = "windows"))] use inline_c::assert_c; + #[cfg(target_os = "windows")] + use wasmer_inline_c::assert_c; #[test] fn test_extern_copy() { diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index c32b44fbe93..863c736c0f6 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -106,7 +106,7 @@ pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -113,7 +113,7 @@ pub unsafe extern "C" fn wasm_module_validate( /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -236,7 +236,7 @@ pub unsafe extern "C" fn wasm_module_exports( /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -387,7 +387,7 @@ pub unsafe extern "C" fn wasm_module_imports( /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -480,7 +480,10 @@ pub unsafe extern "C" fn wasm_module_serialize(module: &wasm_module_t, out: &mut #[cfg(test)] mod tests { + #[cfg(not(target_os = "windows"))] use inline_c::assert_c; + #[cfg(target_os = "windows")] + use wasmer_inline_c::assert_c; #[test] fn test_module_validate() { diff --git a/lib/c-api/src/wasm_c_api/trap.rs b/lib/c-api/src/wasm_c_api/trap.rs index af21b00efb1..55ce4211ae1 100644 --- a/lib/c-api/src/wasm_c_api/trap.rs +++ b/lib/c-api/src/wasm_c_api/trap.rs @@ -70,7 +70,7 @@ pub unsafe extern "C" fn wasm_trap_delete(_trap: Option>) {} /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -144,7 +144,10 @@ pub unsafe extern "C" fn wasm_trap_trace( #[cfg(test)] mod tests { + #[cfg(not(target_os = "windows"))] use inline_c::assert_c; + #[cfg(target_os = "windows")] + use wasmer_inline_c::assert_c; #[test] fn test_trap_message_null_terminated() { diff --git a/lib/c-api/src/wasm_c_api/unstable/engine.rs b/lib/c-api/src/wasm_c_api/unstable/engine.rs index 43f12facbc0..fe3d53cb14e 100644 --- a/lib/c-api/src/wasm_c_api/unstable/engine.rs +++ b/lib/c-api/src/wasm_c_api/unstable/engine.rs @@ -14,7 +14,7 @@ use super::target_lexicon::wasmer_target_t; /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -58,7 +58,7 @@ pub extern "C" fn wasm_config_set_target(config: &mut wasm_config_t, target: Box /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -105,7 +105,7 @@ pub extern "C" fn wasm_config_set_features( /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -166,8 +166,11 @@ pub extern "C" fn wasmer_is_engine_available(engine: wasmer_engine_t) -> bool { #[cfg(test)] mod tests { + #[cfg(not(target_os = "windows"))] use inline_c::assert_c; use std::env::{remove_var, set_var}; + #[cfg(target_os = "windows")] + use wasmer_inline_c::assert_c; #[test] fn test_wasmer_is_headless() { diff --git a/lib/c-api/src/wasm_c_api/unstable/features.rs b/lib/c-api/src/wasm_c_api/unstable/features.rs index 51aee70c52a..349e69f704b 100644 --- a/lib/c-api/src/wasm_c_api/unstable/features.rs +++ b/lib/c-api/src/wasm_c_api/unstable/features.rs @@ -5,7 +5,7 @@ //! # Example //! //! ```rust -//! # use inline_c::assert_c; +//! # use wasmer_inline_c::assert_c; //! # fn main() { //! # (assert_c! { //! # #include "tests/wasmer.h" diff --git a/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs b/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs index f46301e672f..41958eafd5b 100644 --- a/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs +++ b/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs @@ -8,7 +8,7 @@ //! # Example //! //! ```rust -//! # use inline_c::assert_c; +//! # use wasmer_inline_c::assert_c; //! # fn main() { //! # (assert_c! { //! # #include "tests/wasmer.h" @@ -234,7 +234,7 @@ pub unsafe extern "C" fn wasmer_metering_points_are_exhausted( /// points aren't updated by the WebAssembly module execution /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" diff --git a/lib/c-api/src/wasm_c_api/unstable/module.rs b/lib/c-api/src/wasm_c_api/unstable/module.rs index b53e0b14608..ed2e9b9c984 100644 --- a/lib/c-api/src/wasm_c_api/unstable/module.rs +++ b/lib/c-api/src/wasm_c_api/unstable/module.rs @@ -12,7 +12,7 @@ use std::str; /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -79,7 +79,7 @@ pub unsafe extern "C" fn wasmer_module_name( /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" diff --git a/lib/c-api/src/wasm_c_api/unstable/target_lexicon.rs b/lib/c-api/src/wasm_c_api/unstable/target_lexicon.rs index 541b7a87498..cb875d5f477 100644 --- a/lib/c-api/src/wasm_c_api/unstable/target_lexicon.rs +++ b/lib/c-api/src/wasm_c_api/unstable/target_lexicon.rs @@ -6,7 +6,7 @@ //! # Example //! //! ```rust -//! # use inline_c::assert_c; +//! # use wasmer_inline_c::assert_c; //! # fn main() { //! # (assert_c! { //! # #include "tests/wasmer.h" @@ -108,7 +108,7 @@ pub extern "C" fn wasmer_target_delete(_target: Option>) {} /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -161,7 +161,7 @@ pub unsafe extern "C" fn wasmer_triple_new( /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -225,7 +225,7 @@ pub extern "C" fn wasmer_triple_delete(_triple: Option>) {} /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs index 130bb9782dd..737975fa881 100644 --- a/lib/c-api/src/wasm_c_api/value.rs +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -42,7 +42,7 @@ pub union wasm_val_inner { /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" diff --git a/lib/c-api/src/wasm_c_api/version.rs b/lib/c-api/src/wasm_c_api/version.rs index 3d2130e8eb6..337ad738b56 100644 --- a/lib/c-api/src/wasm_c_api/version.rs +++ b/lib/c-api/src/wasm_c_api/version.rs @@ -40,7 +40,7 @@ pub unsafe extern "C" fn wasmer_version() -> *const c_char { /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" @@ -98,7 +98,7 @@ pub unsafe extern "C" fn wasmer_version_patch() -> u8 { /// # Example /// /// ```rust -/// # use inline_c::assert_c; +/// # use wasmer_inline_c::assert_c; /// # fn main() { /// # (assert_c! { /// # #include "tests/wasmer.h" diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 4501b83f44f..6598ab2c608 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -403,7 +403,10 @@ pub unsafe extern "C" fn wasi_get_start_function( #[cfg(test)] mod tests { + #[cfg(not(target_os = "windows"))] use inline_c::assert_c; + #[cfg(target_os = "windows")] + use wasmer_inline_c::assert_c; #[test] fn test_wasi_get_wasi_version_snapshot0() { diff --git a/lib/c-api/src/wasm_c_api/wat.rs b/lib/c-api/src/wasm_c_api/wat.rs index fe985409882..4d0c3928c6e 100644 --- a/lib/c-api/src/wasm_c_api/wat.rs +++ b/lib/c-api/src/wasm_c_api/wat.rs @@ -26,7 +26,10 @@ pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t, out: &mut wasm_byte_vec #[cfg(test)] mod tests { + #[cfg(not(target_os = "windows"))] use inline_c::assert_c; + #[cfg(target_os = "windows")] + use wasmer_inline_c::assert_c; #[test] fn test_wat2wasm() { diff --git a/lib/c-api/tests/Makefile b/lib/c-api/tests/Makefile index ca17c83bd57..05c01037923 100644 --- a/lib/c-api/tests/Makefile +++ b/lib/c-api/tests/Makefile @@ -3,46 +3,28 @@ WASMER_DIR:=$(realpath $(WASMER_DIR)) $(info Using provided WASMER_DIR=$(WASMER_DIR)) ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) +ROOT_DIR_PARENT:=$(shell dirname $(ROOT_DIR)) ifeq (,$(wildcard $(WASMER_DIR)/bin/wasmer)) - CFLAGS = -g -I$(ROOT_DIR)/ -I$(WASMER_DIR)/include + CFLAGS = -g -I $(ROOT_DIR) -I $(WASMER_DIR)/include LDFLAGS = -Wl,-rpath,$(WASMER_DIR)/lib - LDLIBS = -L$(WASMER_DIR)/lib -lwasmer + LDLIBS = -L $(WASMER_DIR)/lib -lwasmer else - CFLAGS = -g -I$(ROOT_DIR)/ -I$(shell $(WASMER_DIR)/bin/wasmer config --includedir) + CFLAGS = -g -I $(ROOT_DIR)/wasm-c-api/include/ -I $(shell $(WASMER_DIR)/bin/wasmer config --includedir) LDFLAGS = -Wl,-rpath,$(shell $(WASMER_DIR)/bin/wasmer config --libdir) LDLIBS = $(shell $(WASMER_DIR)/bin/wasmer config --libs) endif + +$(info * ROOT_DIR: $(ROOT_DIR)) +$(info * WASMER_DIR: $(WASMER_DIR)) +$(info * "") $(info * CFLAGS: $(CFLAGS)) $(info * LDFLAGS: $(LDFLAGS)) $(info * LDLIBS: $(LDLIBS)) -CAPI_BASE_TESTS = \ - wasm-c-api/example/callback wasm-c-api/example/global wasm-c-api/example/hello \ - wasm-c-api/example/memory wasm-c-api/example/reflect wasm-c-api/example/serialize \ - wasm-c-api/example/start wasm-c-api/example/trap wasm-c-api/example/multi - -CAPI_BASE_TESTS_NOT_WORKING = \ - wasm-c-api/example/finalize wasm-c-api/example/hostref wasm-c-api/example/threads \ - wasm-c-api/example/table - -ALL = $(CAPI_BASE_TESTS) - -.PHONY: all -all: $(ALL) - -.PHONY: test-capi-base -.SILENT: test-capi-base -test-capi-base: $(CAPI_BASE_TESTS) - set -o errexit; \ - $(foreach example,$?,echo Running \"$(example)\" example; cd $(shell dirname $(realpath $(example))) && ./$(shell basename $(example)); echo;) - -.PHONY: test-capi-base -.SILENT: test-capi-base -test-capi: test-capi-base - -test: test-capi +test: + cargo test --manifest-path="./wasmer-c-api-test-runner/Cargo.toml" -- --nocapture 2>&1 .SILENT: clean .PHONY: clean diff --git a/lib/c-api/tests/wasm-c-api/include/wasm.h b/lib/c-api/tests/wasm-c-api/include/wasm.h index 78c9e727586..087319398da 100644 --- a/lib/c-api/tests/wasm-c-api/include/wasm.h +++ b/lib/c-api/tests/wasm-c-api/include/wasm.h @@ -133,7 +133,12 @@ WASM_API_EXTERN own wasm_config_t* wasm_config_new(); WASM_DECLARE_OWN(engine) +// During testing, we use a custom implementation of wasm_engine_new +#if defined(TEST_WASM) || defined(TEST_WASMER) +wasm_engine_t* wasm_engine_new(); +#else WASM_API_EXTERN own wasm_engine_t* wasm_engine_new(); +#endif WASM_API_EXTERN own wasm_engine_t* wasm_engine_new_with_config(own wasm_config_t*); diff --git a/lib/c-api/tests/wasm.h b/lib/c-api/tests/wasm.h index dcae9cf750b..1582dd0ec5c 100644 --- a/lib/c-api/tests/wasm.h +++ b/lib/c-api/tests/wasm.h @@ -9,6 +9,10 @@ #include #include +#if defined(_WIN32) || defined(_WIN64) +#define strtok_r strtok_s +#endif + wasm_engine_t *wasm_engine_new() { wasm_config_t *config = wasm_config_new(); diff --git a/lib/c-api/tests/wasmer-c-api-test-runner/Cargo.toml b/lib/c-api/tests/wasmer-c-api-test-runner/Cargo.toml new file mode 100644 index 00000000000..e5ab4eb22df --- /dev/null +++ b/lib/c-api/tests/wasmer-c-api-test-runner/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "wasmer-c-api-test-runner" +version = "0.1.0" +edition = "2021" + +[dependencies] +cc = "1.0" +target-lexicon = "0.11" +regex = "1.6" +walkdir = "2.3.2" \ No newline at end of file diff --git a/lib/c-api/tests/wasmer-c-api-test-runner/src/lib.rs b/lib/c-api/tests/wasmer-c-api-test-runner/src/lib.rs new file mode 100644 index 00000000000..60b2d300845 --- /dev/null +++ b/lib/c-api/tests/wasmer-c-api-test-runner/src/lib.rs @@ -0,0 +1,510 @@ +#[cfg(test)] +use std::error::Error; + +#[cfg(test)] +static INCLUDE_REGEX: &str = "#include \"(.*)\""; + +#[derive(Debug)] +pub struct Config { + pub wasmer_dir: String, + pub root_dir: String, +} + +impl Config { + pub fn get() -> Config { + let mut config = Config { + wasmer_dir: std::env::var("WASMER_DIR").unwrap_or_default(), + root_dir: std::env::var("ROOT_DIR").unwrap_or_default(), + }; + + let wasmer_base_dir = find_wasmer_base_dir(); + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + + if config.wasmer_dir.is_empty() { + println!("manifest dir = {manifest_dir}, wasmer root dir = {wasmer_base_dir}"); + config.wasmer_dir = wasmer_base_dir.clone() + "/package"; + if !std::path::Path::new(&config.wasmer_dir).exists() { + println!("running make build-capi..."); + // run make build-capi + let mut cmd = std::process::Command::new("make"); + cmd.arg("build-capi"); + cmd.current_dir(wasmer_base_dir.clone()); + let result = cmd.output(); + println!("make build-capi: {result:#?}"); + + println!("running make package..."); + // run make package-capi + let mut cmd = std::process::Command::new("make"); + cmd.arg("package-capi"); + cmd.current_dir(wasmer_base_dir.clone()); + let result = cmd.output(); + make_package(); + println!("make package: {result:#?}"); + + println!("list {}", config.wasmer_dir); + match std::fs::read_dir(&config.wasmer_dir) { + Ok(o) => { + for entry in o { + let entry = entry.unwrap(); + let path = entry.path(); + println!(" {:?}", path.file_name()); + } + } + Err(e) => { + println!("error in reading config.wasmer_dir: {e}"); + } + }; + + println!("list {}/include", config.wasmer_dir); + match std::fs::read_dir(&format!("{}/include", config.wasmer_dir)) { + Ok(o) => { + for entry in o { + let entry = entry.unwrap(); + let path = entry.path(); + println!(" {:?}", path.file_name()); + } + } + Err(e) => { + println!("error in reading config.wasmer_dir: {e}"); + } + }; + } + } + if config.root_dir.is_empty() { + config.root_dir = wasmer_base_dir + "/lib/c-api/tests"; + } + + config + } +} + +fn find_wasmer_base_dir() -> String { + let wasmer_base_dir = env!("CARGO_MANIFEST_DIR"); + let mut path2 = wasmer_base_dir.split("wasmer").collect::>(); + path2.pop(); + let mut wasmer_base_dir = path2.join("wasmer"); + + if wasmer_base_dir.contains("wasmer/lib/c-api") { + wasmer_base_dir = wasmer_base_dir + .split("wasmer/lib/c-api") + .next() + .unwrap() + .to_string() + + "wasmer"; + } else if wasmer_base_dir.contains("wasmer\\lib\\c-api") { + wasmer_base_dir = wasmer_base_dir + .split("wasmer\\lib\\c-api") + .next() + .unwrap() + .to_string() + + "wasmer"; + } + + wasmer_base_dir +} + +#[derive(Default)] +pub struct RemoveTestsOnDrop {} + +impl Drop for RemoveTestsOnDrop { + fn drop(&mut self) { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + for entry in std::fs::read_dir(&manifest_dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + let extension = path.extension().and_then(|s| s.to_str()); + if extension == Some("obj") || extension == Some("exe") || extension == Some("o") { + println!("removing {}", path.display()); + let _ = std::fs::remove_file(&path); + } + } + if let Some(parent) = std::path::Path::new(&manifest_dir).parent() { + for entry in std::fs::read_dir(&parent).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + let extension = path.extension().and_then(|s| s.to_str()); + if extension == Some("obj") || extension == Some("exe") || extension == Some("o") { + println!("removing {}", path.display()); + let _ = std::fs::remove_file(&path); + } + } + } + } +} + +fn make_package() { + let wasmer_root_dir = find_wasmer_base_dir(); + let _ = std::fs::create_dir_all(&format!("{wasmer_root_dir}/package/lib")); + let _ = std::fs::create_dir_all(&format!("{wasmer_root_dir}/package/include")); + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/lib/c-api/tests/wasm.h"), + &format!("{wasmer_root_dir}/package/include/wasm.h"), + ); + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/lib/c-api/tests/wasmer.h"), + &format!("{wasmer_root_dir}/package/include/wasmer.h"), + ); + #[cfg(target_os = "windows")] + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/target/release/wasmer.dll"), + &format!("{wasmer_root_dir}/package/lib"), + ); + #[cfg(target_os = "windows")] + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/target/release/wasmer.dll.lib"), + &format!("{wasmer_root_dir}/package/lib"), + ); + #[cfg(not(target_os = "windows"))] + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/target/release/libwasmer.so"), + &format!("{wasmer_root_dir}/package/lib"), + ); + #[cfg(not(target_os = "windows"))] + let _ = std::fs::copy( + &format!("{wasmer_root_dir}/target/release/libwasmer.lib"), + &format!("{wasmer_root_dir}/package/lib"), + ); + println!("copying done (make package)"); +} + +#[cfg(test)] +pub const CAPI_BASE_TESTS: &[&str] = &[ + "wasm-c-api/example/callback", + "wasm-c-api/example/memory", + "wasm-c-api/example/start", + "wasm-c-api/example/global", + "wasm-c-api/example/reflect", + "wasm-c-api/example/trap", + "wasm-c-api/example/hello", + "wasm-c-api/example/serialize", + "wasm-c-api/example/multi", +]; + +#[allow(unused_variables, dead_code)] +pub const CAPI_BASE_TESTS_NOT_WORKING: &[&str] = &[ + "wasm-c-api/example/finalize", + "wasm-c-api/example/hostref", + "wasm-c-api/example/threads", + "wasm-c-api/example/table", +]; + +// Runs all the tests that are working in the /c directory +#[test] +fn test_ok() { + let _drop = RemoveTestsOnDrop::default(); + let config = Config::get(); + println!("config: {:#?}", config); + + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let host = target_lexicon::HOST.to_string(); + let target = &host; + + let wasmer_dll_dir = format!("{}/lib", config.wasmer_dir); + let libwasmer_so_path = format!("{}/lib/libwasmer.so", config.wasmer_dir); + let exe_dir = format!("{manifest_dir}/../wasm-c-api/example"); + let path = std::env::var("PATH").unwrap_or_default(); + let newpath = format!("{};{path}", format!("{wasmer_dll_dir}").replace("/", "\\")); + + if target.contains("msvc") { + for test in CAPI_BASE_TESTS.iter() { + let mut build = cc::Build::new(); + let mut build = build + .cargo_metadata(false) + .warnings(true) + .static_crt(true) + .extra_warnings(true) + .warnings_into_errors(false) + .debug(true) + .host(&host) + .target(target) + .opt_level(1); + + let compiler = build.try_get_compiler().unwrap(); + + println!("compiler {:#?}", compiler); + + // run vcvars + let vcvars_bat_path = find_vcvars64(&compiler).expect("no vcvars64.bat"); + let mut vcvars = std::process::Command::new("cmd"); + vcvars.arg("/C"); + vcvars.arg(vcvars_bat_path); + println!("running {vcvars:?}"); + + // cmd /C vcvars64.bat + let output = vcvars + .output() + .expect("could not invoke vcvars64.bat at {vcvars_bat_path}"); + + if !output.status.success() { + println!(); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + print_wasmer_root_to_stdout(&config); + panic!("failed to invoke vcvars64.bat {test}"); + } + + let mut command = compiler.to_command(); + + command.arg(&format!("{manifest_dir}/../{test}.c")); + if !config.wasmer_dir.is_empty() { + command.arg("/I"); + command.arg(&format!("{}/wasm-c-api/include/", config.root_dir)); + command.arg("/I"); + command.arg(&format!("{}/include/", config.wasmer_dir)); + let mut log = String::new(); + fixup_symlinks( + &[ + format!("{}/include/", config.wasmer_dir), + format!("{}/wasm-c-api/include/", config.root_dir), + format!("{}", config.root_dir), + ], + &mut log, + &config.root_dir, + ) + .expect(&format!("failed to fix symlinks: {log}")); + println!("{log}"); + } + command.arg("/link"); + if !config.wasmer_dir.is_empty() { + command.arg(&format!("/LIBPATH:{}/lib", config.wasmer_dir)); + command.arg(&format!("{}/lib/wasmer.dll.lib", config.wasmer_dir)); + } + command.arg(&format!("/OUT:{manifest_dir}/../{test}.exe")); + + println!("compiling {test}: {command:?}"); + + // compile + let output = command + .output() + .expect(&format!("failed to compile {command:#?}")); + if !output.status.success() { + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + println!("output: {:#?}", output); + print_wasmer_root_to_stdout(&config); + panic!("failed to compile {test}"); + } + + if std::path::Path::new(&format!("{manifest_dir}/../{test}.exe")).exists() { + println!("exe does not exist"); + } + + // execute + let mut command = std::process::Command::new(&format!("{manifest_dir}/../{test}.exe")); + println!("newpath: {}", newpath.clone()); + command.env("PATH", newpath.clone()); + command.current_dir(exe_dir.clone()); + println!("executing {test}: {command:?}"); + println!("setting current dir = {exe_dir}"); + let output = command + .output() + .expect(&format!("failed to run {command:#?}")); + if !output.status.success() { + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + println!("output: {:#?}", output); + print_wasmer_root_to_stdout(&config); + panic!("failed to execute {test}"); + } + + // cc -g -IC:/Users/felix/Development/wasmer/lib/c-api/tests/ + // -IC:/Users/felix/Development/wasmer/package/include + // + // -Wl,-rpath,C:/Users/felix/Development/wasmer/package/lib + // + // wasm-c-api/example/callback.c + // + // -LC:/Users/felix/Development/wasmer/package/lib -lwasmer + // + // -o wasm-c-api/example/callback + } + } else { + for test in CAPI_BASE_TESTS.iter() { + let compiler_cmd = match std::process::Command::new("cc").output() { + Ok(_) => "cc", + Err(_) => "gcc", + }; + let mut command = std::process::Command::new(compiler_cmd); + + if !config.wasmer_dir.is_empty() { + command.arg("-I"); + command.arg(&format!("{}/wasm-c-api/include/", config.root_dir)); + command.arg("-I"); + command.arg(&format!("{}/include/", config.wasmer_dir)); + let mut log = String::new(); + fixup_symlinks( + &[ + format!("{}/include/", config.wasmer_dir), + format!("{}/wasm-c-api/include/", config.root_dir), + format!("{}", config.root_dir), + ], + &mut log, + &config.root_dir, + ) + .expect(&format!("failed to fix symlinks: {log}")); + } + command.arg(&format!("{manifest_dir}/../{test}.c")); + if !config.wasmer_dir.is_empty() { + command.arg("-L"); + command.arg(&format!("{}/lib/", config.wasmer_dir)); + command.arg(&format!("-lwasmer")); + command.arg(&format!("-Wl,-rpath,{}/lib/", config.wasmer_dir)); + } + command.arg("-o"); + command.arg(&format!("{manifest_dir}/../{test}")); + + print_wasmer_root_to_stdout(&config); + + println!("compile: {command:#?}"); + // compile + let output = command + .output() + .expect(&format!("failed to compile {command:#?}")); + if !output.status.success() { + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + print_wasmer_root_to_stdout(&config); + panic!("failed to compile {test}: {command:#?}"); + } + + // execute + let mut command = std::process::Command::new(&format!("{manifest_dir}/../{test}")); + command.env("LD_PRELOAD", libwasmer_so_path.clone()); + command.current_dir(exe_dir.clone()); + println!("execute: {command:#?}"); + let output = command + .output() + .expect(&format!("failed to run {command:#?}")); + if !output.status.success() { + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + print_wasmer_root_to_stdout(&config); + panic!("failed to execute {test}: {command:#?}"); + } + } + } + + for test in CAPI_BASE_TESTS.iter() { + let _ = std::fs::remove_file(&format!("{manifest_dir}/{test}.obj")); + let _ = std::fs::remove_file(&format!("{manifest_dir}/../{test}.exe")); + let _ = std::fs::remove_file(&format!("{manifest_dir}/../{test}")); + } +} + +#[cfg(test)] +fn print_wasmer_root_to_stdout(config: &Config) { + println!("print_wasmer_root_to_stdout"); + + use walkdir::WalkDir; + + for entry in WalkDir::new(&config.wasmer_dir) + .into_iter() + .filter_map(Result::ok) + { + let f_name = String::from(entry.path().canonicalize().unwrap().to_string_lossy()); + println!("{f_name}"); + } + + for entry in WalkDir::new(&config.root_dir) + .into_iter() + .filter_map(Result::ok) + { + let f_name = String::from(entry.path().canonicalize().unwrap().to_string_lossy()); + println!("{f_name}"); + } + + println!("printed"); +} + +#[cfg(test)] +fn fixup_symlinks( + include_paths: &[String], + log: &mut String, + root_dir: &str, +) -> Result<(), Box> { + let source = std::path::Path::new(root_dir) + .join("lib") + .join("c-api") + .join("tests") + .join("wasm-c-api") + .join("include") + .join("wasm.h"); + let target = std::path::Path::new(root_dir) + .join("lib") + .join("c-api") + .join("tests") + .join("wasm.h"); + println!("copying {} -> {}", source.display(), target.display()); + let _ = std::fs::copy(source, target); + + log.push_str(&format!("include paths: {include_paths:?}")); + for i in include_paths { + let i = i.replacen("-I", "", 1); + let i = i.replacen("/I", "", 1); + let mut paths_headers = Vec::new(); + let readdir = match std::fs::read_dir(&i) { + Ok(o) => o, + Err(_) => continue, + }; + for entry in readdir { + let entry = entry?; + let path = entry.path(); + let path_display = format!("{}", path.display()); + if path_display.ends_with("h") { + paths_headers.push(path_display); + } + } + fixup_symlinks_inner(&paths_headers, log)?; + } + + Ok(()) +} + +#[cfg(test)] +fn fixup_symlinks_inner(include_paths: &[String], log: &mut String) -> Result<(), Box> { + log.push_str(&format!("fixup symlinks: {include_paths:#?}")); + let regex = regex::Regex::new(INCLUDE_REGEX).unwrap(); + for path in include_paths.iter() { + let file = match std::fs::read_to_string(&path) { + Ok(o) => o, + _ => continue, + }; + let lines_3 = file.lines().take(3).collect::>(); + log.push_str(&format!("first 3 lines of {path:?}: {:#?}\n", lines_3)); + + let parent = std::path::Path::new(&path).parent().unwrap(); + if let Ok(symlink) = std::fs::read_to_string(parent.clone().join(&file)) { + log.push_str(&format!("symlinking {path:?}\n")); + std::fs::write(&path, symlink)?; + } + + // follow #include directives and recurse + let filepaths = regex + .captures_iter(&file) + .map(|c| c[1].to_string()) + .collect::>(); + log.push_str(&format!("regex captures: ({path:?}): {:#?}\n", filepaths)); + let joined_filepaths = filepaths + .iter() + .filter_map(|s| { + let path = parent.clone().join(s); + Some(format!("{}", path.display())) + }) + .collect::>(); + fixup_symlinks_inner(&joined_filepaths, log)?; + } + Ok(()) +} + +#[cfg(test)] +fn find_vcvars64(compiler: &cc::Tool) -> Option { + if !compiler.is_like_msvc() { + return None; + } + + let path = compiler.path(); + let path = format!("{}", path.display()); + let split = path.split("VC").nth(0)?; + + Some(format!("{split}VC\\Auxiliary\\Build\\vcvars64.bat")) +} diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index 9756b9102fd..a3b51f0836a 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -480,9 +480,14 @@ impl CreateExe { include_dir.pop(); include_dir.push("include"); + let compiler_cmd = match std::process::Command::new("cc").output() { + Ok(_) => "cc", + Err(_) => "gcc", + }; + let mut cmd = Command::new(zig_binary_path); let mut cmd_mut: &mut Command = cmd - .arg("cc") + .arg(compiler_cmd) .arg("-w") .arg("-fgnu-inline-asm") .arg("-fsanitize=undefined") @@ -549,7 +554,12 @@ impl CreateExe { /* Compile main function */ let compilation = { - Command::new("cc") + let compiler_cmd = match Command::new("cc").output() { + Ok(_) => "cc", + Err(_) => "gcc", + }; + + Command::new(compiler_cmd) .arg("-c") .arg(&c_src_path) .arg(if linkcode.optimization_flag.is_empty() { diff --git a/lib/wasi-types-generated/wit-bindgen b/lib/wasi-types-generated/wit-bindgen new file mode 160000 index 00000000000..095d295be63 --- /dev/null +++ b/lib/wasi-types-generated/wit-bindgen @@ -0,0 +1 @@ +Subproject commit 095d295be6392259924e48488af188d3ed3e4102 diff --git a/tests/integration/cli/src/assets.rs b/tests/integration/cli/src/assets.rs index 6f7b9a24b14..8fe5dbc79c3 100644 --- a/tests/integration/cli/src/assets.rs +++ b/tests/integration/cli/src/assets.rs @@ -36,7 +36,7 @@ pub const WASMER_TARGET_PATH2: &str = concat!( pub const LIBWASMER_FILENAME: &str = "libwasmer.a"; #[cfg(windows)] -pub const LIBWASMER_PATH: &str = "wasmer.lib"; +pub const LIBWASMER_FILENAME: &str = "wasmer.lib"; /// Get the path to the `libwasmer.a` static library. pub fn get_libwasmer_path() -> PathBuf { @@ -63,6 +63,18 @@ pub fn get_wasmer_path() -> PathBuf { ret = PathBuf::from(format!("{}wasmer", WASMER_TARGET_PATH2)); } if !ret.exists() { + if let Some(s) = env!("CARGO_MANIFEST_DIR").split("wasmer").next() { + #[cfg(target_os = "windows")] + { + return std::path::Path::new(&format!("{s}wasmer/target/release/wasmer.exe")) + .to_path_buf(); + } + #[cfg(not(target_os = "windows"))] + { + return std::path::Path::new(&format!("{s}wasmer/target/release/wasmer")) + .to_path_buf(); + } + } panic!("Could not find wasmer executable path! {:?}", ret); } ret