mirror of
https://github.com/mii443/wasmer.git
synced 2025-08-31 04:39:28 +00:00
Merge branch 'master' into wasix-core-changes
This commit is contained in:
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -334,7 +334,7 @@ jobs:
|
||||
env:
|
||||
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/aarch64 cross
|
||||
CROSS_DOCKER_IN_DOCKER: true
|
||||
CARGO_TARGET: --target aarch64-unknown-linux-gnu
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
|
||||
PKG_CONFIG_ALLOW_CROSS: true
|
||||
ENABLE_LLVM: 0
|
||||
@ -345,7 +345,7 @@ jobs:
|
||||
env:
|
||||
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/aarch64 cross
|
||||
CROSS_DOCKER_IN_DOCKER: true
|
||||
CARGO_TARGET: --target aarch64-unknown-linux-gnu
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
|
||||
PKG_CONFIG_ALLOW_CROSS: true
|
||||
ENABLE_LLVM: 0
|
||||
@ -357,7 +357,7 @@ jobs:
|
||||
env:
|
||||
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/aarch64 cross
|
||||
CROSS_DOCKER_IN_DOCKER: true
|
||||
CARGO_TARGET: --target aarch64-unknown-linux-gnu
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
|
||||
PKG_CONFIG_ALLOW_CROSS: true
|
||||
ENABLE_LLVM: 0
|
||||
@ -367,7 +367,7 @@ jobs:
|
||||
env:
|
||||
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/aarch64 cross
|
||||
CROSS_DOCKER_IN_DOCKER: true
|
||||
CARGO_TARGET: --target aarch64-unknown-linux-gnu
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
|
||||
PKG_CONFIG_ALLOW_CROSS: true
|
||||
TARGET: aarch64-unknown-linux-gnu
|
||||
|
48
.github/workflows/test.yaml
vendored
48
.github/workflows/test.yaml
vendored
@ -155,7 +155,7 @@ jobs:
|
||||
env:
|
||||
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/aarch64 cross
|
||||
CROSS_DOCKER_IN_DOCKER: true
|
||||
CARGO_TARGET: --target aarch64-unknown-linux-gnu
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
|
||||
PKG_CONFIG_ALLOW_CROSS: true
|
||||
ENABLE_LLVM: 0
|
||||
@ -207,7 +207,7 @@ jobs:
|
||||
build: windows-x64,
|
||||
os: windows-2019,
|
||||
target: x86_64-pc-windows-msvc,
|
||||
llvm_choco_version: 13.0.0
|
||||
llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/13.x/llvm-windows-amd64.tar.xz'
|
||||
},
|
||||
{
|
||||
build: windows-gnu,
|
||||
@ -225,7 +225,7 @@ jobs:
|
||||
if: matrix.metadata.build == 'linux-x64'
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y --allow-downgrades libstdc++6
|
||||
sudo apt-get install -y --allow-downgrades libstdc++6 libtinfo5
|
||||
sudo apt-get install --reinstall g++
|
||||
- name: Set up base deps on musl
|
||||
if: matrix.metadata.build == 'linux-musl'
|
||||
@ -275,18 +275,6 @@ jobs:
|
||||
mkdir -p package
|
||||
mkdir -p package/winsdk
|
||||
cp -r /tmp/winsdk/* package/winsdk
|
||||
- name: Choco install LLVM
|
||||
uses: crazy-max/ghaction-chocolatey@v2
|
||||
if: matrix.metadata.llvm_choco_version
|
||||
with:
|
||||
args: install llvm --version ${{ matrix.metadata.llvm_choco_version }} --allow-downgrade
|
||||
- name: Install LLVM (Choco - Windows)
|
||||
if: matrix.metadata.llvm_choco_version
|
||||
shell: bash
|
||||
run: |
|
||||
cd 'C:\Program Files\LLVM\'
|
||||
LLVM_DIR=$(pwd)
|
||||
echo "LLVM_SYS_120_PREFIX=${LLVM_DIR}" >> $GITHUB_ENV
|
||||
- name: Install LLVM (macOS Apple Silicon)
|
||||
if: matrix.metadata.os == 'macos-11.0' && !matrix.metadata.llvm_url
|
||||
run: |
|
||||
@ -299,6 +287,7 @@ jobs:
|
||||
LLVM_DIR=$(pwd)/${{ env.LLVM_DIR }}
|
||||
mkdir ${LLVM_DIR}
|
||||
tar xf llvm.tar.xz --strip-components=1 -C ${LLVM_DIR}
|
||||
echo "ENABLE_LLVM=1" >> $GITHUB_ENV
|
||||
echo "${LLVM_DIR}/bin" >> $GITHUB_PATH
|
||||
echo "LLVM_SYS_120_PREFIX=${LLVM_DIR}" >> $GITHUB_ENV
|
||||
env:
|
||||
@ -343,7 +332,7 @@ jobs:
|
||||
env:
|
||||
TARGET: ${{ matrix.metadata.target }}
|
||||
TARGET_DIR: target/${{ matrix.metadata.target }}/release
|
||||
CARGO_TARGET: --target ${{ matrix.metadata.target }}
|
||||
CARGO_TARGET: ${{ matrix.metadata.target }}
|
||||
- name: Build Wasmer
|
||||
shell: bash
|
||||
if: ${{ matrix.build-what.key == 'wasmer' && matrix.metadata.build != 'windows-gnu' }}
|
||||
@ -351,7 +340,7 @@ jobs:
|
||||
env:
|
||||
TARGET: ${{ matrix.metadata.target }}
|
||||
TARGET_DIR: target/${{ matrix.metadata.target }}/release
|
||||
CARGO_TARGET: --target ${{ matrix.metadata.target }}
|
||||
CARGO_TARGET: ${{ matrix.metadata.target }}
|
||||
- name: Test C-API
|
||||
shell: bash
|
||||
if: ${{ matrix.build-what.key == 'capi' && !(matrix.metadata.build == 'linux-musl' || matrix.metadata.build == 'macos-arm' || matrix.metadata.build == 'windows-gnu') }}
|
||||
@ -359,7 +348,7 @@ jobs:
|
||||
env:
|
||||
TARGET: ${{ matrix.metadata.target }}
|
||||
TARGET_DIR: target/${{ matrix.metadata.target }}/release
|
||||
CARGO_TARGET: --target ${{ matrix.metadata.target }}
|
||||
CARGO_TARGET: ${{ matrix.metadata.target }}
|
||||
# C-API tests were disabled for linux-musl and macos-arm (we can't run them)
|
||||
- name: Test C-API integration
|
||||
shell: bash
|
||||
@ -368,7 +357,7 @@ jobs:
|
||||
env:
|
||||
TARGET: ${{ matrix.metadata.target }}
|
||||
TARGET_DIR: target/${{ matrix.metadata.target }}/release
|
||||
CARGO_TARGET: --target ${{ matrix.metadata.target }}
|
||||
CARGO_TARGET: ${{ matrix.metadata.target }}
|
||||
- name: Archive production artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@ -435,7 +424,7 @@ jobs:
|
||||
build: windows-x64,
|
||||
os: windows-2019,
|
||||
target: x86_64-pc-windows-msvc,
|
||||
llvm_choco_version: 13.0.0
|
||||
llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/13.x/llvm-windows-amd64.tar.xz'
|
||||
},
|
||||
{
|
||||
build: linux-musl,
|
||||
@ -472,18 +461,6 @@ jobs:
|
||||
with:
|
||||
toolchain: 1.64
|
||||
target: ${{ matrix.metadata.target }}
|
||||
- name: Choco install LLVM
|
||||
uses: crazy-max/ghaction-chocolatey@v2
|
||||
if: matrix.metadata.llvm_choco_version
|
||||
with:
|
||||
args: install llvm --version ${{ matrix.metadata.llvm_choco_version }} --allow-downgrade
|
||||
- name: Install LLVM (Choco - Windows)
|
||||
if: matrix.metadata.llvm_choco_version
|
||||
shell: bash
|
||||
run: |
|
||||
cd 'C:\Program Files\LLVM\'
|
||||
LLVM_DIR=$(pwd)
|
||||
echo "LLVM_SYS_120_PREFIX=${LLVM_DIR}" >> $GITHUB_ENV
|
||||
- name: Install LLVM (macOS Apple Silicon)
|
||||
if: matrix.metadata.os == 'macos-11.0' && !matrix.metadata.llvm_url
|
||||
run: |
|
||||
@ -528,7 +505,7 @@ jobs:
|
||||
env:
|
||||
TARGET: ${{ matrix.metadata.target }}
|
||||
TARGET_DIR: target/${{ matrix.metadata.target }}/release
|
||||
CARGO_TARGET: --target ${{ matrix.metadata.target }}
|
||||
CARGO_TARGET: ${{ matrix.metadata.target }}
|
||||
|
||||
test_integration_cli:
|
||||
name: CLI integration tests on ${{ matrix.build }}
|
||||
@ -554,6 +531,9 @@ jobs:
|
||||
target: x86_64-unknown-linux-musl
|
||||
os: ubuntu-22.04
|
||||
container: alpine:latest
|
||||
- build: windows-x64
|
||||
os: windows-2019
|
||||
target: x86_64-pc-windows-msvc
|
||||
container: ${{ matrix.container }}
|
||||
env:
|
||||
SCCACHE_AZURE_BLOB_CONTAINER: wasmerstoragesccacheblob
|
||||
@ -610,6 +590,6 @@ jobs:
|
||||
env:
|
||||
TARGET: ${{ matrix.target }}
|
||||
TARGET_DIR: target/${{ matrix.target }}/release
|
||||
CARGO_TARGET: --target ${{ matrix.target }}
|
||||
CARGO_TARGET: ${{ matrix.target }}
|
||||
WAPM_DEV_TOKEN: ${{ secrets.WAPM_DEV_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -2253,6 +2253,16 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
@ -2333,6 +2343,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd"
|
||||
|
||||
[[package]]
|
||||
name = "pathdiff"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.11.0"
|
||||
@ -4313,6 +4329,8 @@ dependencies = [
|
||||
"log",
|
||||
"minisign",
|
||||
"nuke-dir",
|
||||
"object 0.30.0",
|
||||
"pathdiff",
|
||||
"prettytable-rs",
|
||||
"regex",
|
||||
"reqwest",
|
||||
@ -4321,6 +4339,7 @@ dependencies = [
|
||||
"semver 1.0.14",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"spinoff",
|
||||
"tar",
|
||||
"target-lexicon 0.12.5",
|
||||
@ -4522,6 +4541,7 @@ version = "3.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"flate2",
|
||||
"object 0.30.0",
|
||||
"pretty_assertions",
|
||||
"rand 0.8.5",
|
||||
"tar",
|
||||
|
107
Makefile
107
Makefile
@ -95,6 +95,11 @@ endif
|
||||
|
||||
CARGO_BINARY ?= cargo
|
||||
CARGO_TARGET ?=
|
||||
CARGO_TARGET_FLAG ?=
|
||||
|
||||
ifneq ($(CARGO_TARGET),)
|
||||
CARGO_TARGET_FLAG := --target $(CARGO_TARGET)
|
||||
endif
|
||||
|
||||
# Variables that can be overridden by the users to force to enable or
|
||||
# to disable a specific compiler.
|
||||
@ -358,24 +363,24 @@ all: build-wasmer build-capi
|
||||
check: check-wasmer check-wasmer-wasm check-capi
|
||||
|
||||
check-wasmer:
|
||||
$(CARGO_BINARY) check $(CARGO_TARGET) --manifest-path lib/cli/Cargo.toml $(compiler_features) --bin wasmer
|
||||
$(CARGO_BINARY) check $(CARGO_TARGET_FLAG) --manifest-path lib/cli/Cargo.toml $(compiler_features) --bin wasmer
|
||||
|
||||
check-wasmer-wasm:
|
||||
$(CARGO_BINARY) check --manifest-path lib/cli-compiler/Cargo.toml --target wasm32-wasi --features singlepass,cranelift --bin wasmer-compiler
|
||||
|
||||
check-capi:
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) check $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml \
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) check $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml \
|
||||
--no-default-features --features wat,compiler,wasi,middlewares $(capi_compiler_features)
|
||||
|
||||
|
||||
build-wasmer:
|
||||
$(CARGO_BINARY) build $(CARGO_TARGET) --release --manifest-path lib/cli/Cargo.toml $(compiler_features) --features="webc_runner" --bin wasmer
|
||||
$(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --release --manifest-path lib/cli/Cargo.toml $(compiler_features) --features="webc_runner" --bin wasmer
|
||||
|
||||
build-wasmer-debug:
|
||||
$(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/cli/Cargo.toml $(compiler_features) --features "webc_runner,debug" --bin wasmer
|
||||
$(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/cli/Cargo.toml $(compiler_features) --features "webc_runner,debug" --bin wasmer
|
||||
|
||||
bench:
|
||||
$(CARGO_BINARY) bench $(CARGO_TARGET) $(compiler_features)
|
||||
$(CARGO_BINARY) bench $(CARGO_TARGET_FLAG) $(compiler_features)
|
||||
|
||||
build-wasmer-wasm:
|
||||
$(CARGO_BINARY) build --release --manifest-path lib/cli-compiler/Cargo.toml --target wasm32-wasi --features singlepass,cranelift --bin wasmer-compiler
|
||||
@ -404,58 +409,58 @@ else
|
||||
endif
|
||||
|
||||
build-docs:
|
||||
$(CARGO_BINARY) doc $(CARGO_TARGET) --release $(compiler_features) --document-private-items --no-deps --workspace --exclude wasmer-c-api
|
||||
$(CARGO_BINARY) doc $(CARGO_TARGET_FLAG) --release $(compiler_features) --document-private-items --no-deps --workspace --exclude wasmer-c-api
|
||||
|
||||
build-docs-capi:
|
||||
# `wasmer-c-api` lib's name is `wasmer`. To avoid a conflict
|
||||
# when generating the documentation, we rename it to its
|
||||
# crate's name. Then we restore the lib's name.
|
||||
sed "$(SEDI)" -e 's/name = "wasmer" # ##lib.name##/name = "wasmer_c_api" # ##lib.name##/' lib/c-api/Cargo.toml
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) doc $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --no-deps --features wat,compiler,cranelift,wasi
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) doc $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --no-deps --features wat,compiler,cranelift,wasi
|
||||
sed "$(SEDI)" -e 's/name = "wasmer_c_api" # ##lib.name##/name = "wasmer" # ##lib.name##/' lib/c-api/Cargo.toml
|
||||
|
||||
build-capi:
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features wat,compiler,wasi,middlewares,webc_runner $(capi_compiler_features)
|
||||
|
||||
build-capi-singlepass:
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features wat,compiler,singlepass,wasi,middlewares,webc_runner
|
||||
|
||||
build-capi-singlepass-universal:
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features wat,compiler,singlepass,wasi,middlewares,webc_runner
|
||||
|
||||
build-capi-cranelift:
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features wat,compiler,cranelift,wasi,middlewares,webc_runner
|
||||
|
||||
build-capi-cranelift-universal:
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features wat,compiler,cranelift,wasi,middlewares,webc_runner
|
||||
|
||||
build-capi-llvm:
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features wat,compiler,llvm,wasi,middlewares,webc_runner
|
||||
|
||||
build-capi-llvm-universal:
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features wat,compiler,llvm,wasi,middlewares,webc_runner
|
||||
|
||||
# Headless (we include the minimal to be able to run)
|
||||
|
||||
build-capi-headless:
|
||||
ifeq ($(CARGO_TARGET),)
|
||||
ifeq ($(CARGO_TARGET_FLAG),)
|
||||
RUSTFLAGS="${RUSTFLAGS} -C panic=abort -C link-dead-code -C lto -O -C embed-bitcode=yes" $(CARGO_BINARY) build --target $(HOST_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features compiler-headless,wasi
|
||||
--no-default-features --features compiler-headless,wasi,webc_runner --target-dir target/$(CARGO_TARGET_FLAG)/headless
|
||||
else
|
||||
RUSTFLAGS="${RUSTFLAGS} -C panic=abort -C link-dead-code -C lto -O -C embed-bitcode=yes" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features compiler-headless,wasi
|
||||
RUSTFLAGS="${RUSTFLAGS} -C panic=abort -C link-dead-code -C lto -O -C embed-bitcode=yes" $(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features compiler-headless,wasi,webc_runner --target-dir target/$(CARGO_TARGET_FLAG)/headless
|
||||
endif
|
||||
|
||||
build-capi-headless-ios:
|
||||
RUSTFLAGS="${RUSTFLAGS} -C panic=abort" cargo lipo --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features compiler-headless,wasi
|
||||
--no-default-features --features compiler-headless,wasi,webc_runner --target-dir target/$(CARGO_TARGET_FLAG)/headless
|
||||
|
||||
#####
|
||||
#
|
||||
@ -465,27 +470,27 @@ build-capi-headless-ios:
|
||||
|
||||
# test compilers
|
||||
test-stage-0-wast:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features)
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --tests $(compiler_features)
|
||||
|
||||
# test packages
|
||||
test-stage-1-test-all:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --all --release $(exclude_tests) --exclude wasmer-c-api-test-runner --exclude wasmer-capi-examples-runner
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --all --release $(exclude_tests) --exclude wasmer-c-api-test-runner --exclude wasmer-capi-examples-runner
|
||||
test-stage-2-test-compiler-cranelift-nostd:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --manifest-path lib/compiler-cranelift/Cargo.toml --release --no-default-features --features=std
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --manifest-path lib/compiler-cranelift/Cargo.toml --release --no-default-features --features=std
|
||||
test-stage-3-test-compiler-singlepass-nostd:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --manifest-path lib/compiler-singlepass/Cargo.toml --release --no-default-features --features=std
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --manifest-path lib/compiler-singlepass/Cargo.toml --release --no-default-features --features=std
|
||||
test-stage-4-wasmer-cli:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --manifest-path lib/cli/Cargo.toml $(compiler_features) --release
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --manifest-path lib/cli/Cargo.toml $(compiler_features) --release
|
||||
|
||||
# test examples
|
||||
test-stage-5-test-examples:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) $(compiler_features) --features wasi --examples
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) $(compiler_features) --features wasi --examples
|
||||
test-stage-6-test-examples-release:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release $(compiler_features) --features wasi --examples
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release $(compiler_features) --features wasi --examples
|
||||
|
||||
test-stage-7-capi-integration-tests:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --package wasmer-c-api-test-runner
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --package wasmer-capi-examples-runner
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --package wasmer-c-api-test-runner
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --package wasmer-capi-examples-runner
|
||||
|
||||
test: test-compilers test-packages test-examples
|
||||
|
||||
@ -517,13 +522,13 @@ test-js-wasi:
|
||||
test-compilers-compat: $(foreach compiler,$(compilers),test-$(compiler))
|
||||
|
||||
test-singlepass-universal:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- singlepass::universal
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --tests $(compiler_features) -- singlepass::universal
|
||||
|
||||
test-cranelift-universal:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- cranelift::universal
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --tests $(compiler_features) -- cranelift::universal
|
||||
|
||||
test-llvm-universal:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- llvm::universal
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --tests $(compiler_features) -- llvm::universal
|
||||
|
||||
test-singlepass: $(foreach singlepass_engine,$(filter singlepass-%,$(compilers_engines)),test-$(singlepass_engine))
|
||||
|
||||
@ -540,7 +545,7 @@ test-capi: build-capi package-capi test-capi-ci
|
||||
|
||||
|
||||
test-capi-crate-%:
|
||||
WASMER_CAPI_CONFIG=$(shell echo $@ | sed -e s/test-capi-crate-//) $(CARGO_BINARY) test $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
WASMER_CAPI_CONFIG=$(shell echo $@ | sed -e s/test-capi-crate-//) $(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --manifest-path lib/c-api/Cargo.toml --release \
|
||||
--no-default-features --features wat,compiler,wasi,middlewares,webc_runner $(capi_compiler_features) -- --nocapture
|
||||
|
||||
test-capi-integration-%:
|
||||
@ -551,26 +556,26 @@ test-capi-integration-%:
|
||||
cd lib/c-api/examples; WASMER_CAPI_CONFIG=$(shell echo $@ | sed -e s/test-capi-integration-//) WASMER_DIR=`pwd`/../../../package make run
|
||||
|
||||
test-wasi-unit:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --manifest-path lib/wasi/Cargo.toml --release
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --manifest-path lib/wasi/Cargo.toml --release
|
||||
|
||||
test-wasi:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- wasi::wasitests
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --tests $(compiler_features) -- wasi::wasitests
|
||||
|
||||
test-integration-cli:
|
||||
rustup target add wasm32-wasi
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture --test-threads=1
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture --test-threads=1
|
||||
|
||||
test-integration-cli-ci:
|
||||
rustup target add wasm32-wasi
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner -p wasmer-integration-tests-cli -- --nocapture || $(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture --test-threads=1
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --features webc_runner -p wasmer-integration-tests-cli -- --nocapture --test-threads=1 || $(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture --test-threads=1
|
||||
|
||||
test-integration-ios:
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner -p wasmer-integration-tests-ios
|
||||
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --features webc_runner -p wasmer-integration-tests-ios
|
||||
|
||||
generate-wasi-tests:
|
||||
# Uncomment the following for installing the toolchain
|
||||
# cargo run -p wasi-test-generator -- -s
|
||||
$(CARGO_BINARY) run $(CARGO_TARGET) -p wasi-test-generator -- -g
|
||||
$(CARGO_BINARY) run $(CARGO_TARGET_FLAG) -p wasi-test-generator -- -g
|
||||
#####
|
||||
#
|
||||
# Packaging.
|
||||
@ -621,24 +626,50 @@ package-capi:
|
||||
cp $(TARGET_DIR)/wasmer.dll package/lib/wasmer.dll ;\
|
||||
fi
|
||||
|
||||
if [ -f target/headless/$(CARGO_TARGET)/release/wasmer.dll ]; then \
|
||||
cp target/headless/$(CARGO_TARGET)/release/wasmer.dll package/lib/wasmer-headless.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/headless/$(CARGO_TARGET)/release/wasmer.dll.lib ]; then \
|
||||
cp target/headless/$(CARGO_TARGET)/release/wasmer.dll.lib package/lib/wasmer-headless.dll.lib ;\
|
||||
fi
|
||||
|
||||
if [ -f $(TARGET_DIR)/wasmer.lib ]; then \
|
||||
cp $(TARGET_DIR)/wasmer.lib package/lib/wasmer.lib ;\
|
||||
fi
|
||||
|
||||
if [ -f target/headless/$(CARGO_TARGET)/release/wasmer.lib ]; then \
|
||||
cp target/headless/$(CARGO_TARGET)/release/wasmer.lib package/lib/wasmer-headless.lib ;\
|
||||
fi
|
||||
|
||||
if [ -f $(TARGET_DIR)/libwasmer.dylib ]; then \
|
||||
cp $(TARGET_DIR)/libwasmer.dylib package/lib/libwasmer.dylib ;\
|
||||
fi
|
||||
|
||||
if [ -f target/headless/$(CARGO_TARGET)/release/libwasmer.dylib ]; then \
|
||||
cp target/headless/$(CARGO_TARGET)/release/libwasmer.dylib package/lib/libwasmer-headless.dylib ;\
|
||||
fi
|
||||
|
||||
if [ -f $(TARGET_DIR)/libwasmer.so ]; then \
|
||||
cp $(TARGET_DIR)/libwasmer.so package/lib/libwasmer.so ;\
|
||||
fi
|
||||
|
||||
if [ -f target/headless/$(CARGO_TARGET)/release/libwasmer.so ]; then \
|
||||
cp target/headless/$(CARGO_TARGET)/release/libwasmer.so package/lib/libwasmer-headless.so ;\
|
||||
fi
|
||||
|
||||
if [ -f $(TARGET_DIR)/libwasmer.a ]; then \
|
||||
cp $(TARGET_DIR)/libwasmer.a package/lib/libwasmer.a ;\
|
||||
fi
|
||||
|
||||
if [ -f target/headless/$(CARGO_TARGET)/release/libwasmer.a ]; then \
|
||||
cp target/headless/$(CARGO_TARGET)/release/libwasmer.a package/lib/libwasmer-headless.a ;\
|
||||
fi
|
||||
|
||||
if [ -f target/$(HOST_TARGET)/release/wasmer.dll ]; then \
|
||||
cp target/$(HOST_TARGET)/release/wasmer.dll package/lib/wasmer.dll ;\
|
||||
fi
|
||||
|
@ -29,10 +29,10 @@ fn main() -> anyhow::Result<()> {
|
||||
let module = Module::new(&store, &module_wat)?;
|
||||
// The module doesn't import anything, so we create an empty import object.
|
||||
let import_object = imports! {};
|
||||
let instance = Instance::new(&module, &import_object)?;
|
||||
let instance = Instance::new(&mut store, &module, &import_object)?;
|
||||
|
||||
let add_one = instance.exports.get_function("add_one")?;
|
||||
let result = add_one.call(&[Value::I32(42)])?;
|
||||
let result = add_one.call(&mut store, &[Value::I32(42)])?;
|
||||
assert_eq!(result[0], Value::I32(43));
|
||||
|
||||
Ok(())
|
||||
|
@ -69,7 +69,7 @@ mod tests {
|
||||
let sz = 18 * WASM_PAGE_SIZE;
|
||||
let mut memory = Vec::new();
|
||||
memory.resize(sz, 0);
|
||||
let mut ret = VMTinyMemory {
|
||||
let mut ret = Self {
|
||||
mem: memory,
|
||||
memory_definition: None,
|
||||
};
|
||||
|
BIN
lib/c-api/examples/assets/wabt-1.0.37.wasmer
Normal file
BIN
lib/c-api/examples/assets/wabt-1.0.37.wasmer
Normal file
Binary file not shown.
@ -184,17 +184,17 @@ fn test_run() {
|
||||
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}"),
|
||||
None => manifest_dir.to_string(),
|
||||
};
|
||||
|
||||
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 manifest_dir_parent = std::path::Path::new(&manifest_dir);
|
||||
let 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
|
||||
let build = build
|
||||
.cargo_metadata(false)
|
||||
.warnings(true)
|
||||
.static_crt(true)
|
||||
@ -216,12 +216,12 @@ fn test_run() {
|
||||
fixup_symlinks(
|
||||
&[
|
||||
format!("{}/include", config.wasmer_dir),
|
||||
format!("{}", config.root_dir),
|
||||
config.root_dir.to_string(),
|
||||
],
|
||||
&mut log,
|
||||
&config.root_dir,
|
||||
)
|
||||
.expect(&format!("failed to fix symlinks: {log}"));
|
||||
.unwrap_or_else(|_| panic!("failed to fix symlinks: {log}"));
|
||||
println!("{log}");
|
||||
}
|
||||
|
||||
@ -243,11 +243,11 @@ fn test_run() {
|
||||
|
||||
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_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("%~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");
|
||||
@ -291,7 +291,7 @@ fn test_run() {
|
||||
println!("setting current dir = {exe_dir}");
|
||||
let output = command
|
||||
.output()
|
||||
.expect(&format!("failed to run {command:#?}"));
|
||||
.unwrap_or_else(|_| panic!("failed to run {command:#?}"));
|
||||
if !output.status.success() {
|
||||
println!("{output:#?}");
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
@ -314,18 +314,18 @@ fn test_run() {
|
||||
fixup_symlinks(
|
||||
&[
|
||||
format!("{}/include", config.wasmer_dir),
|
||||
format!("{}", config.root_dir),
|
||||
config.root_dir.to_string(),
|
||||
],
|
||||
&mut log,
|
||||
&config.root_dir,
|
||||
)
|
||||
.expect(&format!("failed to fix symlinks: {log}"));
|
||||
.unwrap_or_else(|_| panic!("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("-lwasmer");
|
||||
command.arg(&format!("-Wl,-rpath,{}/lib/", config.wasmer_dir));
|
||||
}
|
||||
command.arg("-o");
|
||||
@ -364,7 +364,7 @@ fn test_run() {
|
||||
println!("execute: {command:#?}");
|
||||
let output = command
|
||||
.output()
|
||||
.expect(&format!("failed to run {command:#?}"));
|
||||
.unwrap_or_else(|_| panic!("failed to run {command:#?}"));
|
||||
if !output.status.success() {
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stderr));
|
||||
@ -433,7 +433,7 @@ fn fixup_symlinks(
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
let path_display = format!("{}", path.display());
|
||||
if path_display.ends_with("h") {
|
||||
if path_display.ends_with('h') {
|
||||
paths_headers.push(path_display);
|
||||
}
|
||||
}
|
||||
@ -487,7 +487,7 @@ fn find_vcvarsall(compiler: &cc::Tool) -> Option<String> {
|
||||
|
||||
let path = compiler.path();
|
||||
let path = format!("{}", path.display());
|
||||
let split = path.split("VC").nth(0)?;
|
||||
let split = path.split("VC").next()?;
|
||||
|
||||
Some(format!("{split}VC\\Auxiliary\\Build\\vcvarsall.bat"))
|
||||
}
|
||||
|
@ -125,12 +125,12 @@ fn test_ok() {
|
||||
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("/", "\\"));
|
||||
let newpath = format!("{};{path}", 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
|
||||
let build = build
|
||||
.cargo_metadata(false)
|
||||
.warnings(true)
|
||||
.static_crt(true)
|
||||
@ -178,12 +178,12 @@ fn test_ok() {
|
||||
&[
|
||||
format!("{}/include/", config.wasmer_dir),
|
||||
format!("{}/wasm-c-api/include/", config.root_dir),
|
||||
format!("{}", config.root_dir),
|
||||
config.root_dir.to_string(),
|
||||
],
|
||||
&mut log,
|
||||
&config.root_dir,
|
||||
)
|
||||
.expect(&format!("failed to fix symlinks: {log}"));
|
||||
.unwrap_or_else(|_| panic!("failed to fix symlinks: {log}"));
|
||||
println!("{log}");
|
||||
}
|
||||
command.arg("/link");
|
||||
@ -198,7 +198,7 @@ fn test_ok() {
|
||||
// compile
|
||||
let output = command
|
||||
.output()
|
||||
.expect(&format!("failed to compile {command:#?}"));
|
||||
.unwrap_or_else(|_| panic!("failed to compile {command:#?}"));
|
||||
if !output.status.success() {
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
@ -220,7 +220,7 @@ fn test_ok() {
|
||||
println!("setting current dir = {exe_dir}");
|
||||
let output = command
|
||||
.output()
|
||||
.expect(&format!("failed to run {command:#?}"));
|
||||
.unwrap_or_else(|_| panic!("failed to run {command:#?}"));
|
||||
if !output.status.success() {
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
@ -258,18 +258,18 @@ fn test_ok() {
|
||||
&[
|
||||
format!("{}/include/", config.wasmer_dir),
|
||||
format!("{}/wasm-c-api/include/", config.root_dir),
|
||||
format!("{}", config.root_dir),
|
||||
config.root_dir.to_string(),
|
||||
],
|
||||
&mut log,
|
||||
&config.root_dir,
|
||||
)
|
||||
.expect(&format!("failed to fix symlinks: {log}"));
|
||||
.unwrap_or_else(|_| panic!("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("-lwasmer");
|
||||
command.arg(&format!("-Wl,-rpath,{}/lib/", config.wasmer_dir));
|
||||
}
|
||||
command.arg("-o");
|
||||
@ -284,7 +284,7 @@ fn test_ok() {
|
||||
.stderr(Stdio::inherit())
|
||||
.current_dir(find_wasmer_base_dir())
|
||||
.output()
|
||||
.expect(&format!("failed to compile {command:#?}"));
|
||||
.unwrap_or_else(|_| panic!("failed to compile {command:#?}"));
|
||||
if !output.status.success() {
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
@ -299,7 +299,7 @@ fn test_ok() {
|
||||
println!("execute: {command:#?}");
|
||||
let output = command
|
||||
.output()
|
||||
.expect(&format!("failed to run {command:#?}"));
|
||||
.unwrap_or_else(|_| panic!("failed to run {command:#?}"));
|
||||
if !output.status.success() {
|
||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
@ -391,7 +391,7 @@ fn fixup_symlinks(
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
let path_display = format!("{}", path.display());
|
||||
if path_display.ends_with("h") {
|
||||
if path_display.ends_with('h') {
|
||||
paths_headers.push(path_display);
|
||||
}
|
||||
}
|
||||
@ -445,7 +445,7 @@ fn find_vcvars64(compiler: &cc::Tool) -> Option<String> {
|
||||
|
||||
let path = compiler.path();
|
||||
let path = format!("{}", path.display());
|
||||
let split = path.split("VC").nth(0)?;
|
||||
let split = path.split("VC").next()?;
|
||||
|
||||
Some(format!("{split}VC\\Auxiliary\\Build\\vcvars64.bat"))
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ wasmer-wasi = { version = "=3.1.0", path = "../wasi", optional = true }
|
||||
wasmer-wasi-experimental-io-devices = { version = "=3.1.0", path = "../wasi-experimental-io-devices", optional = true, features = ["link_external_libs"] }
|
||||
wasmer-wast = { version = "=3.1.0", path = "../../tests/lib/wast", optional = true }
|
||||
wasmer-cache = { version = "=3.1.0", path = "../cache", optional = true }
|
||||
wasmer-types = { version = "=3.1.0", path = "../types" }
|
||||
wasmer-types = { version = "=3.1.0", path = "../types", features = ["enable-serde"] }
|
||||
wasmer-registry = { version = "=4.0.0", path = "../registry" }
|
||||
wasmer-object = { version = "=3.1.0", path = "../object", optional = true }
|
||||
wasmer-vfs = { version = "=3.1.0", path = "../vfs", default-features = false, features = ["host-fs"] }
|
||||
@ -85,6 +85,9 @@ log = "0.4.17"
|
||||
minisign = "0.7.2"
|
||||
semver = "1.0.14"
|
||||
rpassword = "7.2.0"
|
||||
pathdiff = "0.2.1"
|
||||
sha2 = "0.10.6"
|
||||
object = "0.30.0"
|
||||
|
||||
[build-dependencies]
|
||||
chrono = { version = "^0.4", default-features = false, features = [ "std", "clock" ] }
|
||||
@ -104,6 +107,7 @@ default = [
|
||||
"compiler",
|
||||
"wasmer-artifact-create",
|
||||
"static-artifact-create",
|
||||
"webc_runner",
|
||||
]
|
||||
cache = ["wasmer-cache"]
|
||||
cache-blake3-pure = ["wasmer-cache/blake3-pure"]
|
||||
@ -165,7 +169,6 @@ enable-serde = [
|
||||
"wasmer/enable-serde",
|
||||
"wasmer-vm/enable-serde",
|
||||
"wasmer-compiler/enable-serde",
|
||||
"wasmer-types/enable-serde",
|
||||
"wasmer-wasi/enable-serde",
|
||||
]
|
||||
|
||||
|
@ -5,71 +5,74 @@ use wasmer_types::ModuleInfo;
|
||||
use wasmer_types::{Symbol, SymbolRegistry};
|
||||
|
||||
/// Helper functions to simplify the usage of the static artifact.
|
||||
const HELPER_FUNCTIONS: &str = r#"
|
||||
wasm_byte_vec_t generate_serialized_data() {
|
||||
fn gen_helper_functions(atom_name: &str, module_name: &str) -> String {
|
||||
format!("
|
||||
wasm_byte_vec_t generate_serialized_data_{atom_name}() {{
|
||||
// We need to pass all the bytes as one big buffer so we have to do all this logic to memcpy
|
||||
// the various pieces together from the generated header file.
|
||||
//
|
||||
// We should provide a `deseralize_vectored` function to avoid requiring this extra work.
|
||||
|
||||
char* byte_ptr = (char*)&WASMER_METADATA[0];
|
||||
char* byte_ptr = (char*)&{module_name}[0];
|
||||
|
||||
size_t num_function_pointers
|
||||
= sizeof(function_pointers) / sizeof(void*);
|
||||
= sizeof(function_pointers_{atom_name}) / sizeof(void*);
|
||||
size_t num_function_trampolines
|
||||
= sizeof(function_trampolines) / sizeof(void*);
|
||||
= sizeof(function_trampolines_{atom_name}) / sizeof(void*);
|
||||
size_t num_dynamic_function_trampoline_pointers
|
||||
= sizeof(dynamic_function_trampoline_pointers) / sizeof(void*);
|
||||
= sizeof(dynamic_function_trampoline_pointers_{atom_name}) / sizeof(void*);
|
||||
|
||||
|
||||
size_t buffer_size = module_bytes_len
|
||||
+ sizeof(size_t) + sizeof(function_pointers)
|
||||
+ sizeof(size_t) + sizeof(function_trampolines)
|
||||
+ sizeof(size_t) + sizeof(dynamic_function_trampoline_pointers);
|
||||
size_t buffer_size = module_bytes_len_{atom_name}
|
||||
+ sizeof(size_t) + sizeof(function_pointers_{atom_name})
|
||||
+ sizeof(size_t) + sizeof(function_trampolines_{atom_name})
|
||||
+ sizeof(size_t) + sizeof(dynamic_function_trampoline_pointers_{atom_name});
|
||||
|
||||
char* memory_buffer = (char*) malloc(buffer_size);
|
||||
size_t current_offset = 0;
|
||||
|
||||
memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len);
|
||||
current_offset += module_bytes_len;
|
||||
memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len_{atom_name});
|
||||
current_offset += module_bytes_len_{atom_name};
|
||||
|
||||
memcpy(memory_buffer + current_offset, (void*)&num_function_pointers, sizeof(size_t));
|
||||
current_offset += sizeof(size_t);
|
||||
|
||||
memcpy(memory_buffer + current_offset, (void*)&function_pointers[0], sizeof(function_pointers));
|
||||
current_offset += sizeof(function_pointers);
|
||||
memcpy(memory_buffer + current_offset, (void*)&function_pointers_{atom_name}[0], sizeof(function_pointers_{atom_name}));
|
||||
current_offset += sizeof(function_pointers_{atom_name});
|
||||
|
||||
memcpy(memory_buffer + current_offset, (void*)&num_function_trampolines, sizeof(size_t));
|
||||
current_offset += sizeof(size_t);
|
||||
|
||||
memcpy(memory_buffer + current_offset, (void*)&function_trampolines[0], sizeof(function_trampolines));
|
||||
current_offset += sizeof(function_trampolines);
|
||||
memcpy(memory_buffer + current_offset, (void*)&function_trampolines_{atom_name}[0], sizeof(function_trampolines_{atom_name}));
|
||||
current_offset += sizeof(function_trampolines_{atom_name});
|
||||
|
||||
memcpy(memory_buffer + current_offset, (void*)&num_dynamic_function_trampoline_pointers, sizeof(size_t));
|
||||
current_offset += sizeof(size_t);
|
||||
|
||||
memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers[0], sizeof(dynamic_function_trampoline_pointers));
|
||||
current_offset += sizeof(dynamic_function_trampoline_pointers);
|
||||
memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers_{atom_name}[0], sizeof(dynamic_function_trampoline_pointers_{atom_name}));
|
||||
current_offset += sizeof(dynamic_function_trampoline_pointers_{atom_name});
|
||||
|
||||
wasm_byte_vec_t module_byte_vec = {
|
||||
wasm_byte_vec_t module_byte_vec = {{
|
||||
.size = buffer_size,
|
||||
.data = memory_buffer,
|
||||
};
|
||||
}};
|
||||
return module_byte_vec;
|
||||
}
|
||||
}}
|
||||
|
||||
wasm_module_t* wasmer_object_module_new(wasm_store_t* store, const char* wasm_name) {
|
||||
wasm_module_t* wasmer_object_module_new_{atom_name}(wasm_store_t* store, const char* wasm_name) {{
|
||||
// wasm_name intentionally unused for now: will be used in the future.
|
||||
wasm_byte_vec_t module_byte_vec = generate_serialized_data();
|
||||
wasm_byte_vec_t module_byte_vec = generate_serialized_data_{atom_name}();
|
||||
wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec);
|
||||
free(module_byte_vec.data);
|
||||
|
||||
return module;
|
||||
}}
|
||||
")
|
||||
}
|
||||
"#;
|
||||
|
||||
/// Generate the header file that goes with the generated object file.
|
||||
pub fn generate_header_file(
|
||||
atom_name: &str,
|
||||
module_info: &ModuleInfo,
|
||||
symbol_registry: &dyn SymbolRegistry,
|
||||
metadata_length: usize,
|
||||
@ -83,7 +86,7 @@ pub fn generate_header_file(
|
||||
value: "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n".to_string(),
|
||||
},
|
||||
CStatement::Declaration {
|
||||
name: "module_bytes_len".to_string(),
|
||||
name: format!("module_bytes_len_{atom_name}"),
|
||||
is_extern: false,
|
||||
is_const: true,
|
||||
ctype: CType::U32,
|
||||
@ -92,7 +95,7 @@ pub fn generate_header_file(
|
||||
})),
|
||||
},
|
||||
CStatement::Declaration {
|
||||
name: "WASMER_METADATA".to_string(),
|
||||
name: symbol_registry.symbol_to_name(Symbol::Metadata),
|
||||
is_extern: true,
|
||||
is_const: true,
|
||||
ctype: CType::Array {
|
||||
@ -154,7 +157,7 @@ pub fn generate_header_file(
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
c_statements.push(CStatement::Declaration {
|
||||
name: "function_pointers".to_string(),
|
||||
name: format!("function_pointers_{atom_name}"),
|
||||
is_extern: false,
|
||||
is_const: true,
|
||||
ctype: CType::Array {
|
||||
@ -210,7 +213,7 @@ pub fn generate_header_file(
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
c_statements.push(CStatement::Declaration {
|
||||
name: "function_trampolines".to_string(),
|
||||
name: format!("function_trampolines_{atom_name}"),
|
||||
is_extern: false,
|
||||
is_const: true,
|
||||
ctype: CType::Array {
|
||||
@ -274,7 +277,7 @@ pub fn generate_header_file(
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
c_statements.push(CStatement::Declaration {
|
||||
name: "dynamic_function_trampoline_pointers".to_string(),
|
||||
name: format!("dynamic_function_trampoline_pointers_{atom_name}"),
|
||||
is_extern: false,
|
||||
is_const: true,
|
||||
ctype: CType::Array {
|
||||
@ -287,7 +290,7 @@ pub fn generate_header_file(
|
||||
}
|
||||
|
||||
c_statements.push(CStatement::LiteralConstant {
|
||||
value: HELPER_FUNCTIONS.to_string(),
|
||||
value: gen_helper_functions(atom_name, &symbol_registry.symbol_to_name(Symbol::Metadata)),
|
||||
});
|
||||
|
||||
c_statements.push(CStatement::LiteralConstant {
|
||||
|
@ -11,7 +11,8 @@ use crate::commands::CreateObj;
|
||||
#[cfg(feature = "wast")]
|
||||
use crate::commands::Wast;
|
||||
use crate::commands::{
|
||||
Add, Cache, Config, Init, Inspect, List, Login, Publish, Run, SelfUpdate, Validate, Whoami,
|
||||
Add, Cache, Config, GenCHeader, Init, Inspect, List, Login, Publish, Run, SelfUpdate, Validate,
|
||||
Whoami,
|
||||
};
|
||||
use crate::error::PrettyError;
|
||||
use clap::{CommandFactory, ErrorKind, Parser};
|
||||
@ -128,6 +129,9 @@ enum WasmerCLIOptions {
|
||||
#[structopt(name = "create-obj", verbatim_doc_comment)]
|
||||
CreateObj(CreateObj),
|
||||
|
||||
/// Generate the C static_defs.h header file for the input .wasm module
|
||||
GenCHeader(GenCHeader),
|
||||
|
||||
/// Get various configuration information needed
|
||||
/// to compile programs which use Wasmer
|
||||
Config(Config),
|
||||
@ -177,6 +181,7 @@ impl WasmerCLIOptions {
|
||||
Self::List(list) => list.execute(),
|
||||
Self::Login(login) => login.execute(),
|
||||
Self::Publish(publish) => publish.execute(),
|
||||
Self::GenCHeader(gen_heder) => gen_heder.execute(),
|
||||
#[cfg(feature = "wast")]
|
||||
Self::Wast(wast) => wast.execute(),
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -234,9 +239,9 @@ fn wasmer_main_inner() -> Result<(), anyhow::Error> {
|
||||
WasmerCLIOptions::Run(Run::from_binfmt_args())
|
||||
} else {
|
||||
match command.unwrap_or(&"".to_string()).as_ref() {
|
||||
"add" | "cache" | "compile" | "config" | "create-exe" | "help" | "inspect" | "init"
|
||||
| "run" | "self-update" | "validate" | "wast" | "binfmt" | "list" | "login"
|
||||
| "publish" => WasmerCLIOptions::parse(),
|
||||
"add" | "cache" | "compile" | "config" | "create-obj" | "create-exe" | "help"
|
||||
| "gen-c-header" | "inspect" | "init" | "run" | "self-update" | "validate" | "wast"
|
||||
| "binfmt" | "list" | "login" | "publish" => WasmerCLIOptions::parse(),
|
||||
_ => {
|
||||
WasmerCLIOptions::try_parse_from(args.iter()).unwrap_or_else(|e| {
|
||||
match e.kind() {
|
||||
|
@ -10,6 +10,7 @@ mod config;
|
||||
mod create_exe;
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
mod create_obj;
|
||||
mod gen_c_header;
|
||||
mod init;
|
||||
mod inspect;
|
||||
mod list;
|
||||
@ -30,15 +31,16 @@ pub use compile::*;
|
||||
pub use create_exe::*;
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
pub use create_obj::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "wast")]
|
||||
pub use wast::*;
|
||||
pub use {
|
||||
add::*, cache::*, config::*, init::*, inspect::*, list::*, login::*, publish::*, run::*,
|
||||
self_update::*, validate::*, whoami::*,
|
||||
add::*, cache::*, config::*, gen_c_header::*, init::*, inspect::*, list::*, login::*,
|
||||
publish::*, run::*, self_update::*, validate::*, whoami::*,
|
||||
};
|
||||
|
||||
/// The kind of object format to emit.
|
||||
#[derive(Debug, Copy, Clone, clap::Parser)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, clap::Parser, Serialize, Deserialize)]
|
||||
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
|
||||
pub enum ObjectFormat {
|
||||
/// Serialize the entire module into an object file.
|
||||
@ -47,6 +49,12 @@ pub enum ObjectFormat {
|
||||
Symbols,
|
||||
}
|
||||
|
||||
impl Default for ObjectFormat {
|
||||
fn default() -> Self {
|
||||
ObjectFormat::Symbols
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
|
||||
impl std::str::FromStr for ObjectFormat {
|
||||
type Err = &'static str;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,23 +2,18 @@
|
||||
//! Create a standalone native executable for a given Wasm file.
|
||||
|
||||
use super::ObjectFormat;
|
||||
use crate::{commands::PrefixerFn, store::CompilerOptions};
|
||||
use crate::store::CompilerOptions;
|
||||
use anyhow::{Context, Result};
|
||||
use clap::Parser;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufWriter;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use wasmer::*;
|
||||
use wasmer_object::{emit_serialized, get_object_for_target};
|
||||
|
||||
#[cfg(feature = "webc_runner")]
|
||||
use webc::{ParseOptions, WebCMmap};
|
||||
|
||||
const WASMER_SERIALIZED_HEADER: &[u8] = include_bytes!("wasmer_create_exe.h");
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
/// The options for the `wasmer create-exe` subcommand
|
||||
pub struct CreateObj {
|
||||
@ -26,17 +21,24 @@ pub struct CreateObj {
|
||||
#[clap(name = "FILE", parse(from_os_str))]
|
||||
path: PathBuf,
|
||||
|
||||
/// Output file
|
||||
/// Output file or directory if the input is a pirita file
|
||||
#[clap(name = "OUTPUT_PATH", short = 'o', parse(from_os_str))]
|
||||
output: PathBuf,
|
||||
|
||||
/// Header output file
|
||||
#[clap(
|
||||
name = "OUTPUT_HEADER_PATH",
|
||||
long = "output-header-path",
|
||||
parse(from_os_str)
|
||||
)]
|
||||
header_output: Option<PathBuf>,
|
||||
/// Optional directorey used for debugging: if present, will
|
||||
/// output the files to a debug instead of a temp directory
|
||||
#[clap(long, name = "DEBUG PATH", parse(from_os_str))]
|
||||
debug_dir: Option<PathBuf>,
|
||||
|
||||
/// Prefix for the function names in the input file in the compiled object file.
|
||||
///
|
||||
/// Default value = sha256 of the input file
|
||||
#[clap(long, name = "PREFIX")]
|
||||
prefix: Option<String>,
|
||||
|
||||
/// Atom name to compile when compiling multi-atom pirita files
|
||||
#[clap(long, name = "ATOM")]
|
||||
atom: Option<String>,
|
||||
|
||||
/// Compilation Target triple
|
||||
///
|
||||
@ -49,6 +51,7 @@ pub struct CreateObj {
|
||||
/// - "aarch64-linux-gnu"
|
||||
/// - "x86_64-apple-darwin"
|
||||
/// - "arm64-apple-darwin"
|
||||
/// - "x86_64-windows-gnu"
|
||||
#[clap(long = "target")]
|
||||
target_triple: Option<Triple>,
|
||||
|
||||
@ -57,10 +60,10 @@ pub struct CreateObj {
|
||||
/// This flag accepts two options: `symbols` or `serialized`.
|
||||
/// - (default) `symbols` creates an object where all functions and metadata of the module are regular object symbols
|
||||
/// - `serialized` creates an object where the module is zero-copy serialized as raw data
|
||||
#[clap(name = "OBJECT_FORMAT", long = "object-format", verbatim_doc_comment)]
|
||||
#[clap(long = "object-format", name = "OBJECT_FORMAT", verbatim_doc_comment)]
|
||||
object_format: Option<ObjectFormat>,
|
||||
|
||||
#[clap(short = 'm', multiple = true, number_of_values = 1)]
|
||||
#[clap(long, short = 'm', multiple = true, number_of_values = 1)]
|
||||
cpu_features: Vec<CpuFeature>,
|
||||
|
||||
#[clap(flatten)]
|
||||
@ -70,191 +73,116 @@ pub struct CreateObj {
|
||||
impl CreateObj {
|
||||
/// Runs logic for the `create-obj` subcommand
|
||||
pub fn execute(&self) -> Result<()> {
|
||||
let target = self
|
||||
.target_triple
|
||||
.as_ref()
|
||||
.map(|target_triple| {
|
||||
let mut features = self
|
||||
.cpu_features
|
||||
.clone()
|
||||
.into_iter()
|
||||
.fold(CpuFeature::set(), |a, b| a | b);
|
||||
// Cranelift requires SSE2, so we have this "hack" for now to facilitate
|
||||
// usage
|
||||
if target_triple.architecture == Architecture::X86_64 {
|
||||
features |= CpuFeature::SSE2;
|
||||
}
|
||||
Target::new(target_triple.clone(), features)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let path = crate::commands::create_exe::normalize_path(&format!("{}", self.path.display()));
|
||||
let target_triple = self.target_triple.clone().unwrap_or_else(Triple::host);
|
||||
let starting_cd = env::current_dir()?;
|
||||
let wasm_module_path = starting_cd.join(&self.path);
|
||||
let output_path = starting_cd.join(&self.output);
|
||||
let object_format = self.object_format.unwrap_or(ObjectFormat::Symbols);
|
||||
|
||||
#[cfg(feature = "webc_runner")]
|
||||
{
|
||||
if let Ok(pirita) = WebCMmap::parse(wasm_module_path.clone(), &ParseOptions::default())
|
||||
{
|
||||
return self.execute_pirita(&pirita, target, output_path, object_format);
|
||||
}
|
||||
}
|
||||
|
||||
let (store, compiler_type) = self.compiler.get_store_for_target(target.clone())?;
|
||||
let input_path = starting_cd.join(&path);
|
||||
let temp_dir = tempfile::tempdir();
|
||||
let output_directory_path = match self.debug_dir.as_ref() {
|
||||
Some(s) => s.clone(),
|
||||
None => temp_dir?.path().to_path_buf(),
|
||||
};
|
||||
std::fs::create_dir_all(&output_directory_path)?;
|
||||
let object_format = self.object_format.unwrap_or_default();
|
||||
let prefix = match self.prefix.as_ref() {
|
||||
Some(s) => vec![s.clone()],
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
let target = crate::commands::create_exe::utils::target_triple_to_target(
|
||||
&target_triple,
|
||||
&self.cpu_features,
|
||||
);
|
||||
let (_, compiler_type) = self.compiler.get_store_for_target(target.clone())?;
|
||||
println!("Compiler: {}", compiler_type.to_string());
|
||||
println!("Target: {}", target.triple());
|
||||
println!("Format: {:?}", object_format);
|
||||
|
||||
let header_output = self.header_output.clone().unwrap_or_else(|| {
|
||||
let mut retval = self.output.clone();
|
||||
retval.set_extension("h");
|
||||
retval
|
||||
});
|
||||
|
||||
let header_output_path = starting_cd.join(&header_output);
|
||||
|
||||
match object_format {
|
||||
ObjectFormat::Serialized => {
|
||||
let module = Module::from_file(&store, &wasm_module_path)
|
||||
.context("failed to compile Wasm")?;
|
||||
let bytes = module.serialize()?;
|
||||
let mut obj = get_object_for_target(target.triple())?;
|
||||
emit_serialized(&mut obj, &bytes, target.triple(), "WASMER_MODULE")?;
|
||||
let mut writer = BufWriter::new(File::create(&output_path)?);
|
||||
obj.write_stream(&mut writer)
|
||||
.map_err(|err| anyhow::anyhow!(err.to_string()))?;
|
||||
writer.flush()?;
|
||||
let mut writer = BufWriter::new(File::create(&header_output_path)?);
|
||||
writer.write_all(WASMER_SERIALIZED_HEADER)?;
|
||||
writer.flush()?;
|
||||
}
|
||||
ObjectFormat::Symbols => {
|
||||
let engine = store.engine();
|
||||
let engine_inner = engine.inner();
|
||||
let compiler = engine_inner.compiler()?;
|
||||
let features = engine_inner.features();
|
||||
let tunables = store.tunables();
|
||||
let data: Vec<u8> = fs::read(wasm_module_path)?;
|
||||
let prefixer: Option<PrefixerFn> = None;
|
||||
let (module_info, obj, metadata_length, symbol_registry) =
|
||||
Artifact::generate_object(
|
||||
compiler, &data, prefixer, &target, tunables, features,
|
||||
)?;
|
||||
|
||||
let header_file_src = crate::c_gen::staticlib_header::generate_header_file(
|
||||
&module_info,
|
||||
&*symbol_registry,
|
||||
metadata_length,
|
||||
);
|
||||
let mut writer = BufWriter::new(File::create(&output_path)?);
|
||||
obj.write_stream(&mut writer)
|
||||
.map_err(|err| anyhow::anyhow!(err.to_string()))?;
|
||||
writer.flush()?;
|
||||
let mut writer = BufWriter::new(File::create(&header_output_path)?);
|
||||
writer.write_all(header_file_src.as_bytes())?;
|
||||
writer.flush()?;
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
"✔ Object compiled successfully to `{}` and the header file was generated at `{}`.",
|
||||
self.output.display(),
|
||||
header_output.display(),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "webc_runner")]
|
||||
fn execute_pirita(
|
||||
&self,
|
||||
file: &WebCMmap,
|
||||
target: Target,
|
||||
output_path: PathBuf,
|
||||
object_format: ObjectFormat,
|
||||
) -> Result<()> {
|
||||
if output_path.exists() {
|
||||
if output_path.is_dir() {
|
||||
nuke_dir::nuke_dir(&output_path)
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||
}
|
||||
} else {
|
||||
let _ = std::fs::create_dir_all(&output_path)?;
|
||||
}
|
||||
println!(
|
||||
"outputting create-obj to directory {}",
|
||||
output_path.display()
|
||||
);
|
||||
let (store, _) = self.compiler.get_store_for_target(target.clone())?;
|
||||
crate::commands::create_exe::CreateExe::create_objs_pirita(
|
||||
&store,
|
||||
file,
|
||||
&target,
|
||||
&output_path,
|
||||
let atoms =
|
||||
if let Ok(pirita) = WebCMmap::parse(input_path.clone(), &ParseOptions::default()) {
|
||||
crate::commands::create_exe::compile_pirita_into_directory(
|
||||
&pirita,
|
||||
&output_directory_path,
|
||||
&self.compiler,
|
||||
&self.cpu_features,
|
||||
&target_triple,
|
||||
object_format,
|
||||
)?;
|
||||
&prefix,
|
||||
crate::commands::AllowMultiWasm::Reject(self.atom.clone()),
|
||||
self.debug_dir.is_some(),
|
||||
)
|
||||
} else {
|
||||
crate::commands::create_exe::prepare_directory_from_single_wasm_file(
|
||||
&input_path,
|
||||
&output_directory_path,
|
||||
&self.compiler,
|
||||
&target_triple,
|
||||
&self.cpu_features,
|
||||
object_format,
|
||||
&prefix,
|
||||
self.debug_dir.is_some(),
|
||||
)
|
||||
}?;
|
||||
|
||||
// Copy output files into target path, depending on whether
|
||||
// there are one or many files being compiled
|
||||
let file_paths = std::fs::read_dir(output_directory_path.join("atoms"))
|
||||
.map_err(|e| {
|
||||
anyhow::anyhow!(
|
||||
"could not read {}: {e}",
|
||||
output_directory_path.join("atoms").display()
|
||||
)
|
||||
})?
|
||||
.filter_map(|path| path.ok()?.path().canonicalize().ok())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if file_paths.is_empty() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"could not compile object file: no output objects in {}",
|
||||
output_directory_path.join("atoms").display()
|
||||
));
|
||||
}
|
||||
|
||||
if file_paths.len() == 1 {
|
||||
if let Some(parent) = self.output.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
std::fs::copy(
|
||||
std::env::current_dir().unwrap().join(&file_paths[0]),
|
||||
std::env::current_dir().unwrap().join(&self.output),
|
||||
)
|
||||
.map_err(|e| {
|
||||
anyhow::anyhow!(
|
||||
"{} -> {}: {e}",
|
||||
&file_paths[0].display(),
|
||||
self.output.display()
|
||||
)
|
||||
})?;
|
||||
} else {
|
||||
let keys = atoms
|
||||
.iter()
|
||||
.map(|(name, _)| name.clone())
|
||||
.collect::<Vec<_>>();
|
||||
return Err(anyhow::anyhow!(
|
||||
"where <ATOM> is one of: {}",
|
||||
keys.join(", ")
|
||||
))
|
||||
.context(anyhow::anyhow!(
|
||||
"note: use --atom <ATOM> to specify which atom to compile"
|
||||
))
|
||||
.context(anyhow::anyhow!(
|
||||
"cannot compile more than one atom at a time"
|
||||
));
|
||||
}
|
||||
|
||||
let output_file = self.output.canonicalize().unwrap().display().to_string();
|
||||
let output_file = output_file
|
||||
.strip_prefix(r"\\?\")
|
||||
.unwrap_or(&output_file)
|
||||
.to_string();
|
||||
|
||||
eprintln!("✔ Object compiled successfully to `{output_file}`");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn link(
|
||||
output_path: PathBuf,
|
||||
object_path: PathBuf,
|
||||
header_code_path: PathBuf,
|
||||
) -> anyhow::Result<()> {
|
||||
let libwasmer_path = get_libwasmer_path()?
|
||||
.canonicalize()
|
||||
.context("Failed to find libwasmer")?;
|
||||
println!(
|
||||
"link output {:?}",
|
||||
Command::new("cc")
|
||||
.arg(&header_code_path)
|
||||
.arg(&format!("-L{}", libwasmer_path.display()))
|
||||
//.arg(&format!("-I{}", header_code_path.display()))
|
||||
.arg("-pie")
|
||||
.arg("-o")
|
||||
.arg("header_obj.o")
|
||||
.output()?
|
||||
);
|
||||
//ld -relocatable a.o b.o -o c.o
|
||||
|
||||
println!(
|
||||
"link output {:?}",
|
||||
Command::new("ld")
|
||||
.arg("-relocatable")
|
||||
.arg(&object_path)
|
||||
.arg("header_obj.o")
|
||||
.arg("-o")
|
||||
.arg(&output_path)
|
||||
.output()?
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// path to the static libwasmer
|
||||
fn get_libwasmer_path() -> anyhow::Result<PathBuf> {
|
||||
let mut path = get_wasmer_dir()?;
|
||||
path.push("lib");
|
||||
|
||||
// TODO: prefer headless Wasmer if/when it's a separate library.
|
||||
#[cfg(not(windows))]
|
||||
path.push("libwasmer.a");
|
||||
#[cfg(windows)]
|
||||
path.push("wasmer.lib");
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
fn get_wasmer_dir() -> anyhow::Result<PathBuf> {
|
||||
Ok(PathBuf::from(
|
||||
env::var("WASMER_DIR")
|
||||
.or_else(|e| {
|
||||
option_env!("WASMER_INSTALL_PREFIX")
|
||||
.map(str::to_string)
|
||||
.ok_or(e)
|
||||
})
|
||||
.context("Trying to read env var `WASMER_DIR`")?,
|
||||
))
|
||||
}
|
||||
|
137
lib/cli/src/commands/gen_c_header.rs
Normal file
137
lib/cli/src/commands/gen_c_header.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use crate::store::CompilerOptions;
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use std::path::PathBuf;
|
||||
use wasmer_compiler::Artifact;
|
||||
use wasmer_types::compilation::symbols::ModuleMetadataSymbolRegistry;
|
||||
use wasmer_types::{CpuFeature, MetadataHeader, Triple};
|
||||
use webc::WebC;
|
||||
|
||||
use super::normalize_path;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
/// The options for the `wasmer gen-c-header` subcommand
|
||||
pub struct GenCHeader {
|
||||
/// Input file
|
||||
#[clap(name = "FILE", parse(from_os_str))]
|
||||
path: PathBuf,
|
||||
|
||||
/// Prefix hash (default: SHA256 of input .wasm file)
|
||||
#[clap(long)]
|
||||
prefix: Option<String>,
|
||||
|
||||
/// For pirita files: optional atom name to compile
|
||||
#[clap(long)]
|
||||
atom: Option<String>,
|
||||
|
||||
/// Output file
|
||||
#[clap(name = "OUTPUT PATH", short = 'o', parse(from_os_str))]
|
||||
output: PathBuf,
|
||||
|
||||
/// Compilation Target triple
|
||||
///
|
||||
/// Accepted target triple values must follow the
|
||||
/// ['target_lexicon'](https://crates.io/crates/target-lexicon) crate format.
|
||||
///
|
||||
/// The recommended targets we try to support are:
|
||||
///
|
||||
/// - "x86_64-linux-gnu"
|
||||
/// - "aarch64-linux-gnu"
|
||||
/// - "x86_64-apple-darwin"
|
||||
/// - "arm64-apple-darwin"
|
||||
/// - "x86_64-windows-gnu"
|
||||
#[clap(long = "target")]
|
||||
target_triple: Option<Triple>,
|
||||
|
||||
#[clap(long, short = 'm', multiple = true, number_of_values = 1)]
|
||||
cpu_features: Vec<CpuFeature>,
|
||||
}
|
||||
|
||||
impl GenCHeader {
|
||||
/// Runs logic for the `gen-c-header` subcommand
|
||||
pub fn execute(&self) -> Result<(), anyhow::Error> {
|
||||
let path = crate::commands::normalize_path(&format!("{}", self.path.display()));
|
||||
let mut file = std::fs::read(&path)
|
||||
.map_err(|e| anyhow::anyhow!("{e}"))
|
||||
.with_context(|| anyhow::anyhow!("{path}"))?;
|
||||
let prefix = match self.prefix.as_deref() {
|
||||
Some(s) => s.to_string(),
|
||||
None => crate::commands::PrefixMapCompilation::hash_for_bytes(&file),
|
||||
};
|
||||
|
||||
if let Ok(pirita) = WebC::parse(&file, &webc::ParseOptions::default()) {
|
||||
let atoms = pirita
|
||||
.manifest
|
||||
.atoms
|
||||
.iter()
|
||||
.map(|a| a.0.clone())
|
||||
.collect::<Vec<_>>();
|
||||
if atoms.len() == 1 {
|
||||
file = pirita
|
||||
.get_atom(&pirita.get_package_name(), &atoms[0])
|
||||
.unwrap()
|
||||
.to_vec();
|
||||
} else if self.atom.is_none() {
|
||||
return Err(anyhow::anyhow!("-> note: available atoms are: {}", atoms.join(", ")))
|
||||
.context(anyhow::anyhow!("file has multiple atoms, please specify which atom to generate the header file for"))?;
|
||||
} else {
|
||||
file = pirita
|
||||
.get_atom(&pirita.get_package_name(), &atoms[0])
|
||||
.map_err(|_| {
|
||||
anyhow::anyhow!("-> note: available atoms are: {}", atoms.join(", "))
|
||||
})
|
||||
.context(anyhow::anyhow!(
|
||||
"could not get atom {} from file (invalid atom name)",
|
||||
&atoms[0]
|
||||
))?
|
||||
.to_vec();
|
||||
}
|
||||
}
|
||||
|
||||
let target_triple = self.target_triple.clone().unwrap_or_else(Triple::host);
|
||||
let target = crate::commands::create_exe::utils::target_triple_to_target(
|
||||
&target_triple,
|
||||
&self.cpu_features,
|
||||
);
|
||||
let (store, _) = CompilerOptions::default().get_store_for_target(target.clone())?;
|
||||
let engine = store.engine();
|
||||
let engine_inner = engine.inner();
|
||||
let compiler = engine_inner.compiler()?;
|
||||
let features = engine_inner.features();
|
||||
let tunables = store.tunables();
|
||||
let (metadata, _, _) = Artifact::metadata(
|
||||
compiler,
|
||||
&file,
|
||||
Some(prefix.as_str()),
|
||||
&target,
|
||||
tunables,
|
||||
features,
|
||||
)
|
||||
.map_err(|e| anyhow::anyhow!("could not generate metadata: {e}"))?;
|
||||
|
||||
let serialized_data = metadata
|
||||
.serialize()
|
||||
.map_err(|e| anyhow::anyhow!("failed to serialize: {e}"))?;
|
||||
let mut metadata_binary = vec![];
|
||||
metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
|
||||
metadata_binary.extend(serialized_data);
|
||||
let metadata_length = metadata_binary.len();
|
||||
|
||||
let header_file_src = crate::c_gen::staticlib_header::generate_header_file(
|
||||
&prefix,
|
||||
&metadata.compile_info.module,
|
||||
&ModuleMetadataSymbolRegistry {
|
||||
prefix: prefix.clone(),
|
||||
},
|
||||
metadata_length,
|
||||
);
|
||||
|
||||
let output = normalize_path(&self.output.display().to_string());
|
||||
|
||||
std::fs::write(&output, &header_file_src)
|
||||
.map_err(|e| anyhow::anyhow!("{e}"))
|
||||
.with_context(|| anyhow::anyhow!("{output}"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -418,9 +418,7 @@ fn construct_manifest(
|
||||
log::warn!("{msg}");
|
||||
}
|
||||
|
||||
let modules = vec![wasmer_toml::Module {
|
||||
name: package_name.to_string(),
|
||||
source: cargo_toml
|
||||
let module_source = cargo_toml
|
||||
.as_ref()
|
||||
.map(|p| {
|
||||
// Normalize the path to /target/release to be relative to the parent of the Cargo.toml
|
||||
@ -429,16 +427,29 @@ fn construct_manifest(
|
||||
.join("release")
|
||||
.join(&format!("{package_name}.wasm"));
|
||||
let canonicalized_outpath = outpath.canonicalize().unwrap_or(outpath);
|
||||
let outpath_str = format!("{}", canonicalized_outpath.display());
|
||||
let manifest_canonicalized = manifest_path
|
||||
let outpath_str =
|
||||
crate::commands::normalize_path(&canonicalized_outpath.display().to_string());
|
||||
let manifest_canonicalized = crate::commands::normalize_path(
|
||||
&manifest_path
|
||||
.parent()
|
||||
.and_then(|p| p.canonicalize().ok())
|
||||
.unwrap_or_else(|| manifest_path.to_path_buf());
|
||||
let manifest_str = format!("{}/", manifest_canonicalized.display());
|
||||
let relative_str = outpath_str.replacen(&manifest_str, "", 1);
|
||||
.unwrap_or_else(|| manifest_path.to_path_buf())
|
||||
.display()
|
||||
.to_string(),
|
||||
);
|
||||
let diff = outpath_str
|
||||
.strip_prefix(&manifest_canonicalized)
|
||||
.unwrap_or(&outpath_str)
|
||||
.replace('\\', "/");
|
||||
// Format in UNIX fashion (forward slashes)
|
||||
let relative_str = diff.strip_prefix('/').unwrap_or(&diff);
|
||||
Path::new(&relative_str).to_path_buf()
|
||||
})
|
||||
.unwrap_or_else(|| Path::new(&format!("{package_name}.wasm")).to_path_buf()),
|
||||
.unwrap_or_else(|| Path::new(&format!("{package_name}.wasm")).to_path_buf());
|
||||
|
||||
let modules = vec![wasmer_toml::Module {
|
||||
name: package_name.to_string(),
|
||||
source: module_source,
|
||||
kind: None,
|
||||
abi: default_abi,
|
||||
bindings: bindings.as_ref().and_then(|b| b.first_binding()),
|
||||
|
@ -1,25 +0,0 @@
|
||||
#include "wasmer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern size_t WASMER_MODULE_LENGTH asm("WASMER_MODULE_LENGTH");
|
||||
extern char WASMER_MODULE_DATA asm("WASMER_MODULE_DATA");
|
||||
|
||||
wasm_module_t* wasmer_object_module_new(wasm_store_t* store, const char* wasm_name) {
|
||||
wasm_byte_vec_t module_byte_vec = {
|
||||
.size = WASMER_MODULE_LENGTH,
|
||||
.data = (const char*)&WASMER_MODULE_DATA,
|
||||
};
|
||||
wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,24 +1,16 @@
|
||||
|
||||
#include "wasmer.h"
|
||||
//#include "my_wasm.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
// EXTRA_HEADERS
|
||||
|
||||
#define own
|
||||
|
||||
|
||||
#define WASI
|
||||
|
||||
#ifdef WASI_PIRITA
|
||||
extern size_t VOLUMES_LENGTH asm("VOLUMES_LENGTH");
|
||||
extern char VOLUMES_DATA asm("VOLUMES_DATA");
|
||||
// DECLARE_VOLUMES
|
||||
// DECLARE_MODULES
|
||||
#else
|
||||
extern size_t WASMER_MODULE_LENGTH asm("WASMER_MODULE_LENGTH");
|
||||
extern char WASMER_MODULE_DATA asm("WASMER_MODULE_DATA");
|
||||
#endif
|
||||
|
||||
static void print_wasmer_error() {
|
||||
int error_len = wasmer_last_error_length();
|
||||
@ -54,8 +46,13 @@ static void pass_mapdir_arg(wasi_config_t *wasi_config, char *mapdir) {
|
||||
|
||||
// We try to parse out `--dir` and `--mapdir` ahead of time and process those
|
||||
// specially. All other arguments are passed to the guest program.
|
||||
static void handle_arguments(wasi_config_t *wasi_config, int argc,
|
||||
char *argv[]) {
|
||||
static void handle_arguments(
|
||||
wasi_config_t *wasi_config,
|
||||
int argc,
|
||||
char *argv[],
|
||||
bool command_was_invoked,
|
||||
int dash_dash_position
|
||||
) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
// We probably want special args like `--dir` and `--mapdir` to not be
|
||||
// passed directly
|
||||
@ -88,6 +85,16 @@ static void handle_arguments(wasi_config_t *wasi_config, int argc,
|
||||
// this arg is a mapdir
|
||||
char *mapdir = argv[i] + strlen("--mapdir=");
|
||||
pass_mapdir_arg(wasi_config, mapdir);
|
||||
} else if (command_was_invoked && i == dash_dash_position && strcmp(argv[i], "--") == 0) {
|
||||
continue;
|
||||
} else if (command_was_invoked && dash_dash_position > i && (strcmp(argv[i], "--command") == 0 || strcmp(argv[i], "-c") == 0)) {
|
||||
// next arg is a command
|
||||
if ((i + 1) < argc) {
|
||||
i++;
|
||||
} else {
|
||||
fprintf(stderr, "--command expects a commmand name\n");
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
// guest argument
|
||||
wasi_config_arg(wasi_config, argv[i]);
|
||||
@ -100,29 +107,47 @@ int main(int argc, char *argv[]) {
|
||||
wasm_config_t *config = wasm_config_new();
|
||||
wasm_engine_t *engine = wasm_engine_new_with_config(config);
|
||||
wasm_store_t *store = wasm_store_new(engine);
|
||||
wasm_module_t *module = NULL;
|
||||
|
||||
#ifdef WASI_PIRITA
|
||||
// INSTANTIATE_MODULES
|
||||
#else
|
||||
wasm_byte_vec_t module_byte_vec = {
|
||||
.size = WASMER_MODULE_LENGTH,
|
||||
.data = &WASMER_MODULE_DATA,
|
||||
};
|
||||
wasm_module_t *module = wasm_module_deserialize(store, &module_byte_vec);
|
||||
const char* selected_atom = "main";
|
||||
bool command_was_invoked = false;
|
||||
int dash_dash_position = argc + 1;
|
||||
int number_of_commands = 1;
|
||||
// SET_NUMBER_OF_COMMANDS
|
||||
|
||||
if (!module) {
|
||||
fprintf(stderr, "Failed to create module\n");
|
||||
print_wasmer_error();
|
||||
return -1;
|
||||
if (number_of_commands > 1) {
|
||||
// check if arguments contain "--" earlier than "--command" or "-c"
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--") == 0) {
|
||||
dash_dash_position = i;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// select the --command only if if was given before a "--", such
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if ((strcmp(argv[i], "--command") == 0 || strcmp(argv[i], "-c") == 0) && dash_dash_position > i) {
|
||||
// next arg is a command
|
||||
if ((i + 1) < argc) {
|
||||
selected_atom = argv[i + 1];
|
||||
command_was_invoked = true;
|
||||
break;
|
||||
} else {
|
||||
fprintf(stderr, "--command expects a commmand name\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// INSTANTIATE_MODULES
|
||||
|
||||
// We have now finished the memory buffer book keeping and we have a valid
|
||||
// Module.
|
||||
|
||||
#ifdef WASI_PIRITA
|
||||
wasi_config_t *wasi_config = wasi_config_new(argv[0]);
|
||||
handle_arguments(wasi_config, argc, argv);
|
||||
handle_arguments(wasi_config, argc, argv, command_was_invoked,dash_dash_position);
|
||||
|
||||
wasm_byte_vec_t volume_bytes = {
|
||||
.size = VOLUMES_LENGTH,
|
||||
@ -142,7 +167,7 @@ int main(int argc, char *argv[]) {
|
||||
module,
|
||||
filesystem,
|
||||
&imports,
|
||||
"##atom-name##"
|
||||
selected_atom
|
||||
);
|
||||
if (!wasi_env) {
|
||||
printf("Error setting filesystem\n");
|
||||
@ -150,7 +175,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
#else
|
||||
wasi_config_t *wasi_config = wasi_config_new(argv[0]);
|
||||
handle_arguments(wasi_config, argc, argv);
|
||||
handle_arguments(wasi_config, argc, argv, command_was_invoked, dash_dash_position);
|
||||
|
||||
wasi_env_t *wasi_env = wasi_env_new(store, wasi_config);
|
||||
if (!wasi_env) {
|
||||
@ -216,9 +241,16 @@ int main(int argc, char *argv[]) {
|
||||
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||
own wasm_trap_t *trap = wasm_func_call(start_function, &args, &results);
|
||||
if (trap) {
|
||||
fprintf(stderr, "Trap is not NULL: TODO:\n");
|
||||
wasm_message_t retrieved_message;
|
||||
// TODO: this is a shitty solution, but it's good enough for now
|
||||
wasm_trap_message(trap, &retrieved_message);
|
||||
if (strcmp(retrieved_message.data, "WASI exited with code: 0") == 0) {
|
||||
wasm_trap_delete(trap);
|
||||
} else {
|
||||
fprintf(stderr, "%s", retrieved_message.data);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: handle non-WASI start (maybe with invoke?)
|
||||
|
@ -1,25 +0,0 @@
|
||||
#include "wasmer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern size_t WASMER_MODULE_LENGTH asm("WASMER_MODULE_LENGTH");
|
||||
extern char WASMER_MODULE_DATA asm("WASMER_MODULE_DATA");
|
||||
|
||||
wasm_module_t* wasmer_object_module_new(wasm_store_t* store, const char* wasm_name) {
|
||||
wasm_byte_vec_t module_byte_vec = {
|
||||
.size = WASMER_MODULE_LENGTH,
|
||||
.data = (const char*)&WASMER_MODULE_DATA,
|
||||
};
|
||||
wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,230 +0,0 @@
|
||||
#include "wasmer.h"
|
||||
#include "static_defs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define own
|
||||
|
||||
// TODO: make this define templated so that the Rust code can toggle it on/off
|
||||
#define WASI
|
||||
|
||||
#ifdef WASI_PIRITA
|
||||
extern size_t VOLUMES_LENGTH asm("VOLUMES_LENGTH");
|
||||
extern char VOLUMES_DATA asm("VOLUMES_DATA");
|
||||
#endif
|
||||
|
||||
extern wasm_module_t* wasmer_object_module_new(wasm_store_t* store,const char* wasm_name) asm("wasmer_object_module_new");
|
||||
|
||||
static void print_wasmer_error() {
|
||||
int error_len = wasmer_last_error_length();
|
||||
printf("Error len: `%d`\n", error_len);
|
||||
char *error_str = (char *)malloc(error_len);
|
||||
wasmer_last_error_message(error_str, error_len);
|
||||
printf("%s\n", error_str);
|
||||
free(error_str);
|
||||
}
|
||||
|
||||
#ifdef WASI
|
||||
static void pass_mapdir_arg(wasi_config_t *wasi_config, char *mapdir) {
|
||||
int colon_location = strchr(mapdir, ':') - mapdir;
|
||||
if (colon_location == 0) {
|
||||
// error malformed argument
|
||||
fprintf(stderr, "Expected mapdir argument of the form alias:directory\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char *alias = (char *)malloc(colon_location + 1);
|
||||
memcpy(alias, mapdir, colon_location);
|
||||
alias[colon_location] = '\0';
|
||||
|
||||
int dir_len = strlen(mapdir) - colon_location;
|
||||
char *dir = (char *)malloc(dir_len + 1);
|
||||
memcpy(dir, &mapdir[colon_location + 1], dir_len);
|
||||
dir[dir_len] = '\0';
|
||||
|
||||
wasi_config_mapdir(wasi_config, alias, dir);
|
||||
free(alias);
|
||||
free(dir);
|
||||
}
|
||||
|
||||
// We try to parse out `--dir` and `--mapdir` ahead of time and process those
|
||||
// specially. All other arguments are passed to the guest program.
|
||||
static void handle_arguments(wasi_config_t *wasi_config, int argc,
|
||||
char *argv[]) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
// We probably want special args like `--dir` and `--mapdir` to not be
|
||||
// passed directly
|
||||
if (strcmp(argv[i], "--dir") == 0) {
|
||||
// next arg is a preopen directory
|
||||
if ((i + 1) < argc) {
|
||||
i++;
|
||||
wasi_config_preopen_dir(wasi_config, argv[i]);
|
||||
} else {
|
||||
fprintf(stderr, "--dir expects a following argument specifying which "
|
||||
"directory to preopen\n");
|
||||
exit(-1);
|
||||
}
|
||||
} else if (strcmp(argv[i], "--mapdir") == 0) {
|
||||
// next arg is a mapdir
|
||||
if ((i + 1) < argc) {
|
||||
i++;
|
||||
pass_mapdir_arg(wasi_config, argv[i]);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"--mapdir expects a following argument specifying which "
|
||||
"directory to preopen in the form alias:directory\n");
|
||||
exit(-1);
|
||||
}
|
||||
} else if (strncmp(argv[i], "--dir=", strlen("--dir=")) == 0) {
|
||||
// this arg is a preopen dir
|
||||
char *dir = argv[i] + strlen("--dir=");
|
||||
wasi_config_preopen_dir(wasi_config, dir);
|
||||
} else if (strncmp(argv[i], "--mapdir=", strlen("--mapdir=")) == 0) {
|
||||
// this arg is a mapdir
|
||||
char *mapdir = argv[i] + strlen("--mapdir=");
|
||||
pass_mapdir_arg(wasi_config, mapdir);
|
||||
} else {
|
||||
// guest argument
|
||||
wasi_config_arg(wasi_config, argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
wasm_config_t *config = wasm_config_new();
|
||||
wasm_engine_t *engine = wasm_engine_new_with_config(config);
|
||||
wasm_store_t *store = wasm_store_new(engine);
|
||||
|
||||
#ifdef WASI_PIRITA
|
||||
// INSTANTIATE_MODULES
|
||||
#else
|
||||
wasm_module_t *module = wasmer_object_module_new(store, "module");
|
||||
#endif
|
||||
|
||||
if (!module) {
|
||||
fprintf(stderr, "Failed to create module\n");
|
||||
print_wasmer_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// We have now finished the memory buffer book keeping and we have a valid
|
||||
// Module.
|
||||
|
||||
#ifdef WASI_PIRITA
|
||||
wasi_config_t *wasi_config = wasi_config_new(argv[0]);
|
||||
handle_arguments(wasi_config, argc, argv);
|
||||
|
||||
wasm_byte_vec_t volume_bytes = {
|
||||
.size = VOLUMES_LENGTH,
|
||||
.data = &VOLUMES_DATA,
|
||||
};
|
||||
|
||||
wasi_filesystem_t* filesystem = wasi_filesystem_init_static_memory(&volume_bytes);
|
||||
if (!filesystem) {
|
||||
printf("Error parsing filesystem from bytes\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_extern_vec_t imports;
|
||||
wasi_env_t* wasi_env = wasi_env_with_filesystem(
|
||||
wasi_config,
|
||||
store,
|
||||
module,
|
||||
filesystem,
|
||||
&imports,
|
||||
"##atom-name##"
|
||||
);
|
||||
if (!wasi_env) {
|
||||
printf("Error setting filesystem\n");
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
wasi_config_t *wasi_config = wasi_config_new(argv[0]);
|
||||
handle_arguments(wasi_config, argc, argv);
|
||||
|
||||
wasi_env_t *wasi_env = wasi_env_new(store, wasi_config);
|
||||
if (!wasi_env) {
|
||||
fprintf(stderr, "Error building WASI env!\n");
|
||||
print_wasmer_error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_importtype_vec_t import_types;
|
||||
wasm_module_imports(module, &import_types);
|
||||
|
||||
wasm_extern_vec_t imports;
|
||||
wasm_extern_vec_new_uninitialized(&imports, import_types.size);
|
||||
wasm_importtype_vec_delete(&import_types);
|
||||
|
||||
#ifdef WASI
|
||||
bool get_imports_result = wasi_get_imports(store, wasi_env, module, &imports);
|
||||
|
||||
if (!get_imports_result) {
|
||||
fprintf(stderr, "Error getting WASI imports!\n");
|
||||
print_wasmer_error();
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
wasm_instance_t *instance = wasm_instance_new(store, module, &imports, NULL);
|
||||
|
||||
if (!instance) {
|
||||
fprintf(stderr, "Failed to create instance\n");
|
||||
print_wasmer_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WASI
|
||||
// Read the exports.
|
||||
wasm_extern_vec_t exports;
|
||||
wasm_instance_exports(instance, &exports);
|
||||
wasm_memory_t* mem = NULL;
|
||||
for (size_t i = 0; i < exports.size; i++) {
|
||||
mem = wasm_extern_as_memory(exports.data[i]);
|
||||
if (mem) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mem) {
|
||||
fprintf(stderr, "Failed to create instance: Could not find memory in exports\n");
|
||||
print_wasmer_error();
|
||||
return -1;
|
||||
}
|
||||
wasi_env_set_memory(wasi_env, mem);
|
||||
|
||||
own wasm_func_t *start_function = wasi_get_start_function(instance);
|
||||
if (!start_function) {
|
||||
fprintf(stderr, "`_start` function not found\n");
|
||||
print_wasmer_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
wasm_val_vec_t args = WASM_EMPTY_VEC;
|
||||
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||
own wasm_trap_t *trap = wasm_func_call(start_function, &args, &results);
|
||||
if (trap) {
|
||||
fprintf(stderr, "Trap is not NULL: TODO:\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: handle non-WASI start (maybe with invoke?)
|
||||
|
||||
#ifdef WASI_PIRITA
|
||||
wasi_filesystem_delete(filesystem);
|
||||
#endif
|
||||
#ifdef WASI
|
||||
wasi_env_delete(wasi_env);
|
||||
wasm_extern_vec_delete(&exports);
|
||||
#endif
|
||||
wasm_instance_delete(instance);
|
||||
wasm_module_delete(module);
|
||||
wasm_store_delete(store);
|
||||
wasm_engine_delete(engine);
|
||||
return 0;
|
||||
}
|
@ -30,7 +30,7 @@ pub fn parse_mapdir(entry: &str) -> Result<(String, PathBuf)> {
|
||||
retrieve_alias_pathbuf(alias, real_dir)
|
||||
}
|
||||
// And then we try splitting by `:` (for compatibility with previous API)
|
||||
else if let [alias, real_dir] = entry.split(':').collect::<Vec<&str>>()[..] {
|
||||
else if let [alias, real_dir] = entry.splitn(2, ':').collect::<Vec<&str>>()[..] {
|
||||
retrieve_alias_pathbuf(alias, real_dir)
|
||||
} else {
|
||||
bail!(
|
||||
|
@ -43,6 +43,7 @@ struct ShortNames {}
|
||||
impl SymbolRegistry for ShortNames {
|
||||
fn symbol_to_name(&self, symbol: Symbol) -> String {
|
||||
match symbol {
|
||||
Symbol::Metadata => "M".to_string(),
|
||||
Symbol::LocalFunction(index) => format!("f{}", index.index()),
|
||||
Symbol::Section(index) => format!("s{}", index.index()),
|
||||
Symbol::FunctionCallTrampoline(index) => format!("t{}", index.index()),
|
||||
@ -55,6 +56,10 @@ impl SymbolRegistry for ShortNames {
|
||||
return None;
|
||||
}
|
||||
let (ty, idx) = name.split_at(1);
|
||||
if ty.starts_with('M') {
|
||||
return Some(Symbol::Metadata);
|
||||
}
|
||||
|
||||
let idx = idx.parse::<u32>().ok()?;
|
||||
match ty.chars().next().unwrap() {
|
||||
'f' => Some(Symbol::LocalFunction(LocalFunctionIndex::from_u32(idx))),
|
||||
@ -164,8 +169,11 @@ impl LLVMCompiler {
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
);
|
||||
let metadata_gv =
|
||||
merged_module.add_global(metadata_init.get_type(), None, "WASMER_METADATA");
|
||||
let metadata_gv = merged_module.add_global(
|
||||
metadata_init.get_type(),
|
||||
None,
|
||||
&symbol_registry.symbol_to_name(wasmer_types::Symbol::Metadata),
|
||||
);
|
||||
metadata_gv.set_initializer(&metadata_init);
|
||||
metadata_gv.set_linkage(Linkage::DLLExport);
|
||||
metadata_gv.set_dll_storage_class(DLLStorageClass::Export);
|
||||
@ -310,17 +318,9 @@ impl Compiler for LLVMCompiler {
|
||||
let dwarf = Some(Dwarf::new(SectionIndex::from_u32(
|
||||
module_custom_sections.len() as u32,
|
||||
)));
|
||||
// Terminating zero-length CIE.
|
||||
frame_section_bytes.extend(vec![
|
||||
0x00, 0x00, 0x00, 0x00, // Length
|
||||
0x00, 0x00, 0x00, 0x00, // CIE ID
|
||||
0x10, // Version (must be 1)
|
||||
0x00, // Augmentation data
|
||||
0x00, // Code alignment factor
|
||||
0x00, // Data alignment factor
|
||||
0x00, // Return address register
|
||||
0x00, 0x00, 0x00, // Padding to a multiple of 4 bytes
|
||||
]);
|
||||
// Do not terminate dwarf info with a zero-length CIE.
|
||||
// Because more info will be added later
|
||||
// in lib/object/src/module.rs emit_compilation
|
||||
module_custom_sections.push(CustomSection {
|
||||
protection: CustomSectionProtection::Read,
|
||||
bytes: SectionBody::new_with_vec(frame_section_bytes),
|
||||
|
@ -739,10 +739,13 @@ macro_rules! sse_fn {
|
||||
|emitter: &mut AssemblerX64, precision: Precision, src1: XMM, src2: XMMOrMemory, dst: XMM| {
|
||||
match src2 {
|
||||
XMMOrMemory::XMM(x) => {
|
||||
assert_ne!(x, dst);
|
||||
if x == dst {
|
||||
dynasm!(emitter ; $ins Rx((dst as u8)), Rx((src1 as u8)))
|
||||
} else {
|
||||
move_src_to_dst(emitter, precision, src1, dst);
|
||||
dynasm!(emitter ; $ins Rx((dst as u8)), Rx((x as u8)))
|
||||
}
|
||||
}
|
||||
XMMOrMemory::Memory(base, disp) => {
|
||||
move_src_to_dst(emitter, precision, src1, dst);
|
||||
dynasm!(emitter ; $ins Rx((dst as u8)), [Rq((base as u8)) + disp])
|
||||
|
@ -48,12 +48,6 @@ pub struct Artifact {
|
||||
finished_function_lengths: BoxedSlice<LocalFunctionIndex, usize>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
pub type PrefixerFn = Box<dyn Fn(&[u8]) -> String + Send>;
|
||||
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
const WASMER_METADATA_SYMBOL: &[u8] = b"WASMER_METADATA";
|
||||
|
||||
impl Artifact {
|
||||
/// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
|
||||
#[cfg(feature = "compiler")]
|
||||
@ -416,7 +410,7 @@ impl Artifact {
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
/// Generate a compilation
|
||||
fn generate_metadata<'data>(
|
||||
pub fn generate_metadata<'data>(
|
||||
data: &'data [u8],
|
||||
compiler: &dyn Compiler,
|
||||
tunables: &dyn Tunables,
|
||||
@ -464,16 +458,65 @@ impl Artifact {
|
||||
))
|
||||
}
|
||||
|
||||
/// Generate the metadata object for the module
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn metadata<'data, 'a>(
|
||||
compiler: &dyn Compiler,
|
||||
data: &'a [u8],
|
||||
metadata_prefix: Option<&str>,
|
||||
target: &'data Target,
|
||||
tunables: &dyn Tunables,
|
||||
features: &Features,
|
||||
) -> Result<
|
||||
(
|
||||
ModuleMetadata,
|
||||
Option<ModuleTranslationState>,
|
||||
PrimaryMap<LocalFunctionIndex, FunctionBodyData<'a>>,
|
||||
),
|
||||
CompileError,
|
||||
> {
|
||||
#[allow(dead_code)]
|
||||
let (compile_info, function_body_inputs, data_initializers, module_translation) =
|
||||
Self::generate_metadata(data, compiler, tunables, features)?;
|
||||
|
||||
let data_initializers = data_initializers
|
||||
.iter()
|
||||
.map(OwnedDataInitializer::new)
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice();
|
||||
|
||||
// TODO: we currently supply all-zero function body lengths.
|
||||
// We don't know the lengths until they're compiled, yet we have to
|
||||
// supply the metadata as an input to the compile.
|
||||
let function_body_lengths = function_body_inputs
|
||||
.keys()
|
||||
.map(|_function_body| 0u64)
|
||||
.collect::<PrimaryMap<LocalFunctionIndex, u64>>();
|
||||
|
||||
let metadata = ModuleMetadata {
|
||||
compile_info,
|
||||
prefix: metadata_prefix.map(|s| s.to_string()).unwrap_or_default(),
|
||||
data_initializers,
|
||||
function_body_lengths,
|
||||
cpu_features: target.cpu_features().as_u64(),
|
||||
};
|
||||
|
||||
Ok((metadata, module_translation, function_body_inputs))
|
||||
}
|
||||
|
||||
/// Compile a module into an object file, which can be statically linked against.
|
||||
///
|
||||
/// The `prefixer` returns the a String to prefix each of the
|
||||
/// functions in the static object generated by the
|
||||
/// so we can assure no collisions.
|
||||
/// The `metadata_prefix` is an optional prefix for the object name to make the
|
||||
/// function names in the object file unique. When set, the function names will
|
||||
/// be `wasmer_function_{prefix}_{id}` and the object metadata will be addressable
|
||||
/// using `WASMER_METADATA_{prefix}_LENGTH` and `WASMER_METADATA_{prefix}_DATA`.
|
||||
///
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
pub fn generate_object<'data>(
|
||||
compiler: &dyn Compiler,
|
||||
data: &[u8],
|
||||
prefixer: Option<PrefixerFn>,
|
||||
metadata_prefix: Option<&str>,
|
||||
target: &'data Target,
|
||||
tunables: &dyn Tunables,
|
||||
features: &Features,
|
||||
@ -486,37 +529,16 @@ impl Artifact {
|
||||
),
|
||||
CompileError,
|
||||
> {
|
||||
use wasmer_types::{compilation::symbols::ModuleMetadataSymbolRegistry, SymbolRegistry};
|
||||
|
||||
fn to_compile_error(err: impl std::error::Error) -> CompileError {
|
||||
CompileError::Codegen(format!("{}", err))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
let (compile_info, function_body_inputs, data_initializers, module_translation) =
|
||||
Self::generate_metadata(data, compiler, tunables, features)?;
|
||||
|
||||
let data_initializers = data_initializers
|
||||
.iter()
|
||||
.map(OwnedDataInitializer::new)
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice();
|
||||
|
||||
let target_triple = target.triple();
|
||||
|
||||
// TODO: we currently supply all-zero function body lengths.
|
||||
// We don't know the lengths until they're compiled, yet we have to
|
||||
// supply the metadata as an input to the compile.
|
||||
let function_body_lengths = function_body_inputs
|
||||
.keys()
|
||||
.map(|_function_body| 0u64)
|
||||
.collect::<PrimaryMap<LocalFunctionIndex, u64>>();
|
||||
|
||||
let mut metadata = ModuleMetadata {
|
||||
compile_info,
|
||||
prefix: prefixer.as_ref().map(|p| p(data)).unwrap_or_default(),
|
||||
data_initializers,
|
||||
function_body_lengths,
|
||||
cpu_features: target.cpu_features().as_u64(),
|
||||
};
|
||||
let (mut metadata, module_translation, function_body_inputs) =
|
||||
Self::metadata(compiler, data, metadata_prefix, target, tunables, features)
|
||||
.map_err(to_compile_error)?;
|
||||
|
||||
/*
|
||||
In the C file we need:
|
||||
@ -551,7 +573,12 @@ impl Artifact {
|
||||
)?;
|
||||
let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
|
||||
|
||||
emit_data(&mut obj, WASMER_METADATA_SYMBOL, &metadata_binary, 1)
|
||||
let object_name = ModuleMetadataSymbolRegistry {
|
||||
prefix: metadata_prefix.unwrap_or_default().to_string(),
|
||||
}
|
||||
.symbol_to_name(wasmer_types::Symbol::Metadata);
|
||||
|
||||
emit_data(&mut obj, object_name.as_bytes(), &metadata_binary, 1)
|
||||
.map_err(to_compile_error)?;
|
||||
|
||||
emit_compilation(&mut obj, compilation, &symbol_registry, target_triple)
|
||||
|
@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
|
||||
/// possible after translation (such as the features used for compiling,
|
||||
/// or the `MemoryStyle` and `TableStyle`).
|
||||
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
||||
#[derive(Debug, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||
pub struct CompileModuleInfo {
|
||||
/// The features used for compiling the module
|
||||
pub features: Features,
|
||||
|
@ -14,21 +14,15 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The kinds of wasmer_types objects that might be found in a native object file.
|
||||
#[derive(
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
Archive,
|
||||
Copy,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Debug,
|
||||
RkyvSerialize, RkyvDeserialize, Archive, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
|
||||
)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
#[archive(as = "Self")]
|
||||
pub enum Symbol {
|
||||
/// A metadata section, indexed by a unique prefix
|
||||
/// (usually the wasm file SHA256 hash)
|
||||
Metadata,
|
||||
|
||||
/// A function defined in the wasm.
|
||||
LocalFunction(LocalFunctionIndex),
|
||||
|
||||
@ -154,6 +148,9 @@ impl ModuleMetadata {
|
||||
impl SymbolRegistry for ModuleMetadataSymbolRegistry {
|
||||
fn symbol_to_name(&self, symbol: Symbol) -> String {
|
||||
match symbol {
|
||||
Symbol::Metadata => {
|
||||
format!("WASMER_METADATA_{}", self.prefix.to_uppercase())
|
||||
}
|
||||
Symbol::LocalFunction(index) => {
|
||||
format!("wasmer_function_{}_{}", self.prefix, index.index())
|
||||
}
|
||||
@ -176,7 +173,10 @@ impl SymbolRegistry for ModuleMetadataSymbolRegistry {
|
||||
}
|
||||
|
||||
fn name_to_symbol(&self, name: &str) -> Option<Symbol> {
|
||||
if let Some(index) = name.strip_prefix(&format!("wasmer_function_{}_", self.prefix)) {
|
||||
if name == self.symbol_to_name(Symbol::Metadata) {
|
||||
Some(Symbol::Metadata)
|
||||
} else if let Some(index) = name.strip_prefix(&format!("wasmer_function_{}_", self.prefix))
|
||||
{
|
||||
index
|
||||
.parse::<u32>()
|
||||
.ok()
|
||||
|
@ -67,6 +67,34 @@ impl From<(String, String, u32)> for ImportKey {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable-serde")]
|
||||
mod serde_imports {
|
||||
|
||||
use crate::ImportIndex;
|
||||
use crate::ImportKey;
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
type InitialType = IndexMap<ImportKey, ImportIndex>;
|
||||
type SerializedType = Vec<(ImportKey, ImportIndex)>;
|
||||
// IndexMap<ImportKey, ImportIndex>
|
||||
// Vec<
|
||||
pub fn serialize<S: Serializer>(s: &InitialType, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let vec: SerializedType = s
|
||||
.iter()
|
||||
.map(|(a, b)| (a.clone(), b.clone()))
|
||||
.collect::<Vec<_>>();
|
||||
vec.serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D: Deserializer<'de>>(
|
||||
deserializer: D,
|
||||
) -> Result<InitialType, D::Error> {
|
||||
let serialized = <SerializedType as Deserialize>::deserialize(deserializer)?;
|
||||
Ok(serialized.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// A translated WebAssembly module, excluding the function bodies and
|
||||
/// memory initializers.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
@ -89,6 +117,7 @@ pub struct ModuleInfo {
|
||||
/// Keeping the `index_of_the_import` is important, as there can be
|
||||
/// two same references to the same import, and we don't want to confuse
|
||||
/// them.
|
||||
#[cfg_attr(feature = "enable-serde", serde(with = "serde_imports"))]
|
||||
pub imports: IndexMap<ImportKey, ImportIndex>,
|
||||
|
||||
/// Exported entities.
|
||||
|
@ -13,7 +13,7 @@ use wasmer_emscripten::{
|
||||
};
|
||||
use webc::{Command, WebCMmap};
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
pub struct EmscriptenRunner {
|
||||
args: Vec<String>,
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use wasmer::{Cranelift, Instance, Module, Store};
|
||||
use wasmer_vfs::webc_fs::WebcFileSystem;
|
||||
use webc::{Command, WebCMmap};
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
pub struct WasiRunner {
|
||||
args: Vec<String>,
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ tar = "0.4.38"
|
||||
flate2 = "1.0.24"
|
||||
target-lexicon = "0.12.4"
|
||||
pretty_assertions = "1.3.0"
|
||||
object = "0.30.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
|
@ -23,13 +23,14 @@ pub fn run_code(
|
||||
operating_dir: &Path,
|
||||
executable_path: &Path,
|
||||
args: &[String],
|
||||
stderr: bool,
|
||||
) -> anyhow::Result<String> {
|
||||
let output = Command::new(executable_path.canonicalize()?)
|
||||
.current_dir(operating_dir)
|
||||
.args(args)
|
||||
.output()?;
|
||||
|
||||
if !output.status.success() {
|
||||
if !output.status.success() && !stderr {
|
||||
bail!(
|
||||
"running executable failed: stdout: {}\n\nstderr: {}",
|
||||
std::str::from_utf8(&output.stdout)
|
||||
@ -38,8 +39,12 @@ pub fn run_code(
|
||||
.expect("stderr is not utf8! need to handle arbitrary bytes")
|
||||
);
|
||||
}
|
||||
let output =
|
||||
std::str::from_utf8(&output.stdout).expect("output from running executable is not utf-8");
|
||||
let output = std::str::from_utf8(if stderr {
|
||||
&output.stderr
|
||||
} else {
|
||||
&output.stdout
|
||||
})
|
||||
.expect("output from running executable is not utf-8");
|
||||
|
||||
Ok(output.to_owned())
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use anyhow::bail;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use wasmer_integration_tests_cli::get_wasmer_path;
|
||||
|
||||
@ -42,11 +41,16 @@ fn wasmer_config_error() -> anyhow::Result<()> {
|
||||
.lines()
|
||||
.map(|s| s.trim().to_string())
|
||||
.collect::<Vec<_>>();
|
||||
#[cfg(not(windows))]
|
||||
let expected_1 = "wasmer config --bindir --cflags";
|
||||
#[cfg(windows)]
|
||||
let expected_1 = "wasmer.exe config --bindir --cflags";
|
||||
|
||||
let expected = vec![
|
||||
"error: The argument '--bindir' cannot be used with '--pkg-config'",
|
||||
"",
|
||||
"USAGE:",
|
||||
"wasmer config --bindir --cflags",
|
||||
expected_1,
|
||||
"",
|
||||
"For more information try --help",
|
||||
];
|
||||
@ -212,7 +216,7 @@ fn config_works() -> anyhow::Result<()> {
|
||||
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
format!("{}\n", original_token.to_string().trim().to_string())
|
||||
format!("{}\n", original_token.to_string().trim())
|
||||
);
|
||||
|
||||
let output = Command::new(get_wasmer_path())
|
||||
|
@ -5,8 +5,17 @@ use std::fs;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use tempfile::TempDir;
|
||||
use wasmer_integration_tests_cli::*;
|
||||
|
||||
fn create_exe_wabt_path() -> String {
|
||||
format!("{}/{}", C_ASSET_PATH, "wabt-1.0.37.wasmer")
|
||||
}
|
||||
|
||||
fn create_exe_python_wasmer() -> String {
|
||||
format!("{}/{}", C_ASSET_PATH, "python-0.1.0.wasmer")
|
||||
}
|
||||
|
||||
fn create_exe_test_wasm_path() -> String {
|
||||
format!("{}/{}", C_ASSET_PATH, "qjs.wasm")
|
||||
}
|
||||
@ -27,7 +36,7 @@ struct WasmerCreateExe {
|
||||
/// Compiler with which to compile the Wasm.
|
||||
compiler: Compiler,
|
||||
/// Extra CLI flags
|
||||
extra_cli_flags: Vec<&'static str>,
|
||||
extra_cli_flags: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for WasmerCreateExe {
|
||||
@ -49,19 +58,23 @@ impl Default for WasmerCreateExe {
|
||||
|
||||
impl WasmerCreateExe {
|
||||
fn run(&self) -> anyhow::Result<Vec<u8>> {
|
||||
let output = Command::new(&self.wasmer_path)
|
||||
.current_dir(&self.current_dir)
|
||||
.arg("create-exe")
|
||||
.arg(&self.wasm_path.canonicalize()?)
|
||||
.arg(&self.compiler.to_flag())
|
||||
.args(self.extra_cli_flags.iter())
|
||||
.arg("-o")
|
||||
.arg(&self.native_executable_path)
|
||||
.output()?;
|
||||
let mut output = Command::new(&self.wasmer_path);
|
||||
output.current_dir(&self.current_dir);
|
||||
output.arg("create-exe");
|
||||
output.arg(&self.wasm_path.canonicalize()?);
|
||||
output.arg(&self.compiler.to_flag());
|
||||
output.args(self.extra_cli_flags.iter());
|
||||
output.arg("-o");
|
||||
output.arg(&self.native_executable_path);
|
||||
let cmd = format!("{:?}", output);
|
||||
|
||||
println!("(integration-test) running create-exe: {cmd}");
|
||||
|
||||
let output = output.output()?;
|
||||
|
||||
if !output.status.success() {
|
||||
bail!(
|
||||
"wasmer create-exe failed with: stdout: {}\n\nstderr: {}",
|
||||
"{cmd}\r\n failed with: stdout: {}\n\nstderr: {}",
|
||||
std::str::from_utf8(&output.stdout)
|
||||
.expect("stdout is not utf8! need to handle arbitrary bytes"),
|
||||
std::str::from_utf8(&output.stderr)
|
||||
@ -86,7 +99,7 @@ struct WasmerCreateObj {
|
||||
/// Compiler with which to compile the Wasm.
|
||||
compiler: Compiler,
|
||||
/// Extra CLI flags
|
||||
extra_cli_flags: Vec<&'static str>,
|
||||
extra_cli_flags: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for WasmerCreateObj {
|
||||
@ -108,19 +121,24 @@ impl Default for WasmerCreateObj {
|
||||
|
||||
impl WasmerCreateObj {
|
||||
fn run(&self) -> anyhow::Result<Vec<u8>> {
|
||||
let output = Command::new(&self.wasmer_path)
|
||||
.current_dir(&self.current_dir)
|
||||
.arg("create-obj")
|
||||
.arg(&self.wasm_path.canonicalize()?)
|
||||
.arg(&self.compiler.to_flag())
|
||||
.args(self.extra_cli_flags.iter())
|
||||
.arg("-o")
|
||||
.arg(&self.output_object_path)
|
||||
.output()?;
|
||||
let mut output = Command::new(&self.wasmer_path);
|
||||
output.current_dir(&self.current_dir);
|
||||
output.arg("create-obj");
|
||||
output.arg(&self.wasm_path.canonicalize()?);
|
||||
output.arg(&self.compiler.to_flag());
|
||||
output.args(self.extra_cli_flags.iter());
|
||||
output.arg("-o");
|
||||
output.arg(&self.output_object_path);
|
||||
|
||||
let cmd = format!("{:?}", output);
|
||||
|
||||
println!("(integration-test) running create-obj: {cmd}");
|
||||
|
||||
let output = output.output()?;
|
||||
|
||||
if !output.status.success() {
|
||||
bail!(
|
||||
"wasmer create-obj failed with: stdout: {}\n\nstderr: {}",
|
||||
"{cmd}\r\n failed with: stdout: {}\n\nstderr: {}",
|
||||
std::str::from_utf8(&output.stdout)
|
||||
.expect("stdout is not utf8! need to handle arbitrary bytes"),
|
||||
std::str::from_utf8(&output.stderr)
|
||||
@ -131,6 +149,115 @@ impl WasmerCreateObj {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_exe_with_pirita_works_1() {
|
||||
let tempdir = TempDir::new().unwrap();
|
||||
let path = tempdir.path();
|
||||
let wasm_out = path.join("out.obj");
|
||||
let cmd = Command::new(get_wasmer_path())
|
||||
.arg("create-obj")
|
||||
.arg(create_exe_wabt_path())
|
||||
.arg("-o")
|
||||
.arg(&wasm_out)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
let stderr = String::from_utf8_lossy(&cmd.stderr);
|
||||
|
||||
assert_eq!(stderr.lines().map(|s| s.trim().to_string()).collect::<Vec<_>>(), vec![
|
||||
format!("error: cannot compile more than one atom at a time"),
|
||||
format!("│ 1: note: use --atom <ATOM> to specify which atom to compile"),
|
||||
format!("╰─▶ 2: where <ATOM> is one of: wabt, wasm-interp, wasm-strip, wasm-validate, wasm2wat, wast2json, wat2wasm"),
|
||||
]);
|
||||
|
||||
assert!(!cmd.status.success());
|
||||
|
||||
let cmd = Command::new(get_wasmer_path())
|
||||
.arg("create-obj")
|
||||
.arg(create_exe_wabt_path())
|
||||
.arg("--atom")
|
||||
.arg("wasm2wat")
|
||||
.arg("-o")
|
||||
.arg(&wasm_out)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
let stderr = String::from_utf8_lossy(&cmd.stderr);
|
||||
|
||||
let real_out = wasm_out.canonicalize().unwrap().display().to_string();
|
||||
let real_out = real_out
|
||||
.strip_prefix(r"\\?\")
|
||||
.unwrap_or(&real_out)
|
||||
.to_string();
|
||||
assert_eq!(
|
||||
stderr
|
||||
.lines()
|
||||
.map(|s| s.trim().to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
vec![format!("✔ Object compiled successfully to `{real_out}`"),]
|
||||
);
|
||||
|
||||
assert!(cmd.status.success());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_exe_with_precompiled_works_1() {
|
||||
use object::{Object, ObjectSymbol};
|
||||
|
||||
let tempdir = TempDir::new().unwrap();
|
||||
let path = tempdir.path();
|
||||
let wasm_out = path.join("out.obj");
|
||||
let _ = Command::new(get_wasmer_path())
|
||||
.arg("create-obj")
|
||||
.arg(create_exe_test_wasm_path())
|
||||
.arg("--prefix")
|
||||
.arg("sha123123")
|
||||
.arg("-o")
|
||||
.arg(&wasm_out)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
let file = std::fs::read(&wasm_out).unwrap();
|
||||
let obj_file = object::File::parse(&*file).unwrap();
|
||||
let names = obj_file
|
||||
.symbols()
|
||||
.filter_map(|s| Some(s.name().ok()?.to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert!(
|
||||
names.contains(&"_wasmer_function_sha123123_1".to_string())
|
||||
|| names.contains(&"wasmer_function_sha123123_1".to_string())
|
||||
);
|
||||
|
||||
let _ = Command::new(get_wasmer_path())
|
||||
.arg("create-obj")
|
||||
.arg(create_exe_test_wasm_path())
|
||||
.arg("-o")
|
||||
.arg(&wasm_out)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
let file = std::fs::read(&wasm_out).unwrap();
|
||||
let obj_file = object::File::parse(&*file).unwrap();
|
||||
let names = obj_file
|
||||
.symbols()
|
||||
.filter_map(|s| Some(s.name().ok()?.to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert!(
|
||||
names.contains(
|
||||
&"_wasmer_function_6f62a6bc5c8f8e3e12a54e2ecbc5674ccfe1c75f91d8e4dd6ebb3fec422a4d6c_1"
|
||||
.to_string()
|
||||
) || names.contains(
|
||||
&"wasmer_function_6f62a6bc5c8f8e3e12a54e2ecbc5674ccfe1c75f91d8e4dd6ebb3fec422a4d6c_1"
|
||||
.to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Ignored because of -lunwind linker issue on Windows
|
||||
// see https://github.com/wasmerio/wasmer/issues/3459
|
||||
#[cfg_attr(target_os = "windows", ignore)]
|
||||
#[test]
|
||||
fn create_exe_works() -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
@ -156,6 +283,7 @@ fn create_exe_works() -> anyhow::Result<()> {
|
||||
&operating_dir,
|
||||
&executable_path,
|
||||
&["--eval".to_string(), "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));".to_string()],
|
||||
false,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
@ -164,6 +292,133 @@ fn create_exe_works() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that "-c" and "-- -c" are treated differently
|
||||
// Ignored because of -lunwind linker issue on Windows
|
||||
// see https://github.com/wasmerio/wasmer/issues/3459
|
||||
#[cfg_attr(target_os = "windows", ignore)]
|
||||
#[test]
|
||||
fn create_exe_works_multi_command_args_handling() -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
let operating_dir: PathBuf = temp_dir.path().to_owned();
|
||||
|
||||
let wasm_path = operating_dir.join(create_exe_wabt_path());
|
||||
#[cfg(not(windows))]
|
||||
let executable_path = operating_dir.join("multicommand.out");
|
||||
#[cfg(windows)]
|
||||
let executable_path = operating_dir.join("multicommand.exe");
|
||||
|
||||
WasmerCreateExe {
|
||||
current_dir: operating_dir.clone(),
|
||||
wasm_path,
|
||||
native_executable_path: executable_path.clone(),
|
||||
compiler: Compiler::Cranelift,
|
||||
..Default::default()
|
||||
}
|
||||
.run()
|
||||
.context("Failed to create-exe wasm with Wasmer")?;
|
||||
|
||||
let result = run_code(
|
||||
&operating_dir,
|
||||
&executable_path,
|
||||
&[
|
||||
"--command".to_string(),
|
||||
"wasm-strip".to_string(),
|
||||
"--".to_string(),
|
||||
"-c".to_string(),
|
||||
],
|
||||
true,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
assert_eq!(
|
||||
result_lines,
|
||||
vec![
|
||||
"wasm-strip: unknown option '-c'",
|
||||
"Try '--help' for more information.",
|
||||
"WASI exited with code: 1"
|
||||
]
|
||||
);
|
||||
|
||||
let result = run_code(
|
||||
&operating_dir,
|
||||
&executable_path,
|
||||
&["-c".to_string(), "wasm-strip".to_string()],
|
||||
true,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
assert_eq!(
|
||||
result_lines,
|
||||
vec![
|
||||
"wasm-strip: expected filename argument.",
|
||||
"Try '--help' for more information.",
|
||||
"WASI exited with code: 1"
|
||||
]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Ignored because of -lunwind linker issue on Windows
|
||||
// see https://github.com/wasmerio/wasmer/issues/3459
|
||||
#[cfg_attr(target_os = "windows", ignore)]
|
||||
#[test]
|
||||
fn create_exe_works_multi_command() -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
let operating_dir: PathBuf = temp_dir.path().to_owned();
|
||||
|
||||
let wasm_path = operating_dir.join(create_exe_wabt_path());
|
||||
#[cfg(not(windows))]
|
||||
let executable_path = operating_dir.join("multicommand.out");
|
||||
#[cfg(windows)]
|
||||
let executable_path = operating_dir.join("multicommand.exe");
|
||||
|
||||
WasmerCreateExe {
|
||||
current_dir: operating_dir.clone(),
|
||||
wasm_path,
|
||||
native_executable_path: executable_path.clone(),
|
||||
compiler: Compiler::Cranelift,
|
||||
..Default::default()
|
||||
}
|
||||
.run()
|
||||
.context("Failed to create-exe wasm with Wasmer")?;
|
||||
|
||||
let result = run_code(
|
||||
&operating_dir,
|
||||
&executable_path,
|
||||
&[
|
||||
"--command".to_string(),
|
||||
"wasm2wat".to_string(),
|
||||
"--version".to_string(),
|
||||
],
|
||||
false,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
assert_eq!(result_lines, vec!["1.0.37 (git~v1.0.37)"]);
|
||||
|
||||
let result = run_code(
|
||||
&operating_dir,
|
||||
&executable_path,
|
||||
&[
|
||||
"-c".to_string(),
|
||||
"wasm-validate".to_string(),
|
||||
"--version".to_string(),
|
||||
],
|
||||
false,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
assert_eq!(result_lines, vec!["1.0.37 (git~v1.0.37)"]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Ignored because of -lunwind linker issue on Windows
|
||||
// see https://github.com/wasmerio/wasmer/issues/3459
|
||||
#[cfg_attr(target_os = "windows", ignore)]
|
||||
#[test]
|
||||
fn create_exe_works_with_file() -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
@ -202,6 +457,7 @@ fn create_exe_works_with_file() -> anyhow::Result<()> {
|
||||
"--script".to_string(),
|
||||
"test.js".to_string(),
|
||||
],
|
||||
false,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
@ -216,6 +472,7 @@ fn create_exe_works_with_file() -> anyhow::Result<()> {
|
||||
"--script".to_string(),
|
||||
"abc/test.js".to_string(),
|
||||
],
|
||||
false,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
@ -224,6 +481,9 @@ fn create_exe_works_with_file() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Ignored because of -lunwind linker issue on Windows
|
||||
// see https://github.com/wasmerio/wasmer/issues/3459
|
||||
#[cfg_attr(target_os = "windows", ignore)]
|
||||
#[test]
|
||||
fn create_exe_serialized_works() -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
@ -236,11 +496,11 @@ fn create_exe_serialized_works() -> anyhow::Result<()> {
|
||||
let executable_path = operating_dir.join("wasm.exe");
|
||||
|
||||
let output: Vec<u8> = WasmerCreateExe {
|
||||
current_dir: operating_dir.clone(),
|
||||
current_dir: std::env::current_dir().unwrap(),
|
||||
wasm_path,
|
||||
native_executable_path: executable_path.clone(),
|
||||
compiler: Compiler::Cranelift,
|
||||
extra_cli_flags: vec!["--object-format", "serialized"],
|
||||
extra_cli_flags: vec!["--object-format".to_string(), "serialized".to_string()],
|
||||
..Default::default()
|
||||
}
|
||||
.run()
|
||||
@ -250,6 +510,7 @@ fn create_exe_serialized_works() -> anyhow::Result<()> {
|
||||
&operating_dir,
|
||||
&executable_path,
|
||||
&["--eval".to_string(), "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));".to_string()],
|
||||
false,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
@ -265,17 +526,13 @@ fn create_exe_serialized_works() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_obj(args: Vec<&'static str>, keyword_needle: &str, keyword: &str) -> anyhow::Result<()> {
|
||||
fn create_obj(args: Vec<String>, keyword_needle: &str, keyword: &str) -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
let operating_dir: PathBuf = temp_dir.path().to_owned();
|
||||
|
||||
let wasm_path = operating_dir.join(create_exe_test_wasm_path());
|
||||
|
||||
#[cfg(not(windows))]
|
||||
let object_path = operating_dir.join("wasm.o");
|
||||
#[cfg(windows)]
|
||||
let object_path = operating_dir.join("wasm.obj");
|
||||
let wasm_path = operating_dir.as_path().join(create_exe_test_wasm_path());
|
||||
|
||||
let object_path = operating_dir.as_path().join("wasm");
|
||||
let output: Vec<u8> = WasmerCreateObj {
|
||||
current_dir: operating_dir,
|
||||
wasm_path,
|
||||
@ -292,13 +549,6 @@ fn create_obj(args: Vec<&'static str>, keyword_needle: &str, keyword: &str) -> a
|
||||
"create-obj successfully completed but object output file `{}` missing",
|
||||
object_path.display()
|
||||
);
|
||||
let mut object_header_path = object_path;
|
||||
object_header_path.set_extension("h");
|
||||
assert!(
|
||||
object_header_path.exists(),
|
||||
"create-obj successfully completed but object output header file `{}` missing",
|
||||
object_header_path.display()
|
||||
);
|
||||
|
||||
let output_str = String::from_utf8_lossy(&output);
|
||||
assert!(
|
||||
@ -318,19 +568,23 @@ fn create_obj_default() -> anyhow::Result<()> {
|
||||
|
||||
#[test]
|
||||
fn create_obj_symbols() -> anyhow::Result<()> {
|
||||
create_obj(vec!["--object-format", "symbols"], "Symbols", "symbols")
|
||||
create_obj(
|
||||
vec!["--object-format".to_string(), "symbols".to_string()],
|
||||
"Symbols",
|
||||
"symbols",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_obj_serialized() -> anyhow::Result<()> {
|
||||
create_obj(
|
||||
vec!["--object-format", "serialized"],
|
||||
vec!["--object-format".to_string(), "serialized".to_string()],
|
||||
"Serialized",
|
||||
"serialized",
|
||||
)
|
||||
}
|
||||
|
||||
fn create_exe_with_object_input(args: Vec<&'static str>) -> anyhow::Result<()> {
|
||||
fn create_exe_with_object_input(args: Vec<String>) -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
let operating_dir: PathBuf = temp_dir.path().to_owned();
|
||||
|
||||
@ -341,12 +595,21 @@ fn create_exe_with_object_input(args: Vec<&'static str>) -> anyhow::Result<()> {
|
||||
#[cfg(windows)]
|
||||
let object_path = operating_dir.join("wasm.obj");
|
||||
|
||||
let mut create_obj_args = args.clone();
|
||||
create_obj_args.push("--prefix".to_string());
|
||||
create_obj_args.push("abc123".to_string());
|
||||
create_obj_args.push("--debug-dir".to_string());
|
||||
create_obj_args.push(format!(
|
||||
"{}",
|
||||
operating_dir.join("compile-create-obj").display()
|
||||
));
|
||||
|
||||
WasmerCreateObj {
|
||||
current_dir: operating_dir.clone(),
|
||||
wasm_path,
|
||||
wasm_path: wasm_path.clone(),
|
||||
output_object_path: object_path.clone(),
|
||||
compiler: Compiler::Cranelift,
|
||||
extra_cli_flags: args,
|
||||
extra_cli_flags: create_obj_args,
|
||||
..Default::default()
|
||||
}
|
||||
.run()
|
||||
@ -357,34 +620,43 @@ fn create_exe_with_object_input(args: Vec<&'static str>) -> anyhow::Result<()> {
|
||||
"create-obj successfully completed but object output file `{}` missing",
|
||||
object_path.display()
|
||||
);
|
||||
let mut object_header_path = object_path.clone();
|
||||
object_header_path.set_extension("h");
|
||||
assert!(
|
||||
object_header_path.exists(),
|
||||
"create-obj successfully completed but object output header file `{}` missing",
|
||||
object_header_path.display()
|
||||
);
|
||||
|
||||
#[cfg(not(windows))]
|
||||
let executable_path = operating_dir.join("wasm.out");
|
||||
#[cfg(windows)]
|
||||
let executable_path = operating_dir.join("wasm.exe");
|
||||
|
||||
WasmerCreateExe {
|
||||
current_dir: operating_dir.clone(),
|
||||
wasm_path: object_path,
|
||||
let mut create_exe_args = args.clone();
|
||||
create_exe_args.push("--precompiled-atom".to_string());
|
||||
create_exe_args.push(format!("qjs:abc123:{}", object_path.display()));
|
||||
create_exe_args.push("--debug-dir".to_string());
|
||||
create_exe_args.push(format!(
|
||||
"{}",
|
||||
operating_dir.join("compile-create-exe").display()
|
||||
));
|
||||
|
||||
let create_exe_stdout = WasmerCreateExe {
|
||||
current_dir: std::env::current_dir().unwrap(),
|
||||
wasm_path,
|
||||
native_executable_path: executable_path.clone(),
|
||||
compiler: Compiler::Cranelift,
|
||||
extra_cli_flags: vec!["--header", "wasm.h"],
|
||||
extra_cli_flags: create_exe_args,
|
||||
..Default::default()
|
||||
}
|
||||
.run()
|
||||
.context("Failed to create-exe wasm with Wasmer")?;
|
||||
|
||||
let create_exe_stdout = std::str::from_utf8(&create_exe_stdout).unwrap();
|
||||
assert!(
|
||||
create_exe_stdout.contains("Using cached object file for atom \"qjs\"."),
|
||||
"missed cache hit"
|
||||
);
|
||||
|
||||
let result = run_code(
|
||||
&operating_dir,
|
||||
&executable_path,
|
||||
&["--eval".to_string(), "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));".to_string()],
|
||||
false,
|
||||
)
|
||||
.context("Failed to run generated executable")?;
|
||||
let result_lines = result.lines().collect::<Vec<&str>>();
|
||||
@ -393,17 +665,29 @@ fn create_exe_with_object_input(args: Vec<&'static str>) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Ignored because of -lunwind linker issue on Windows
|
||||
// see https://github.com/wasmerio/wasmer/issues/3459
|
||||
#[cfg_attr(target_os = "windows", ignore)]
|
||||
#[test]
|
||||
fn create_exe_with_object_input_default() -> anyhow::Result<()> {
|
||||
create_exe_with_object_input(vec![])
|
||||
}
|
||||
|
||||
// Ignored because of -lunwind linker issue on Windows
|
||||
// see https://github.com/wasmerio/wasmer/issues/3459
|
||||
#[cfg_attr(target_os = "windows", ignore)]
|
||||
#[test]
|
||||
fn create_exe_with_object_input_symbols() -> anyhow::Result<()> {
|
||||
create_exe_with_object_input(vec!["--object-format", "symbols"])
|
||||
create_exe_with_object_input(vec!["--object-format".to_string(), "symbols".to_string()])
|
||||
}
|
||||
|
||||
// Ignored because of -lunwind linker issue on Windows
|
||||
// see https://github.com/wasmerio/wasmer/issues/3459
|
||||
#[cfg_attr(target_os = "windows", ignore)]
|
||||
#[test]
|
||||
fn create_exe_with_object_input_serialized() -> anyhow::Result<()> {
|
||||
create_exe_with_object_input(vec!["--object-format", "serialized"])
|
||||
create_exe_with_object_input(vec![
|
||||
"--object-format".to_string(),
|
||||
"serialized".to_string(),
|
||||
])
|
||||
}
|
||||
|
84
tests/integration/cli/tests/gen_c_header.rs
Normal file
84
tests/integration/cli/tests/gen_c_header.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use wasmer_integration_tests_cli::get_wasmer_path;
|
||||
use wasmer_integration_tests_cli::C_ASSET_PATH;
|
||||
|
||||
fn create_exe_wabt_path() -> String {
|
||||
format!("{}/{}", C_ASSET_PATH, "wabt-1.0.37.wasmer")
|
||||
}
|
||||
|
||||
fn create_exe_test_wasm_path() -> String {
|
||||
format!("{}/{}", C_ASSET_PATH, "qjs.wasm")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_c_header_works() -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
let operating_dir: PathBuf = temp_dir.path().to_owned();
|
||||
|
||||
let wasm_path = operating_dir.join(create_exe_test_wasm_path());
|
||||
let out_path = temp_dir.path().join("header.h");
|
||||
|
||||
let _ = Command::new(get_wasmer_path())
|
||||
.arg("gen-c-header")
|
||||
.arg(&wasm_path)
|
||||
.arg("-o")
|
||||
.arg(&out_path)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
let file = std::fs::read_to_string(&out_path).expect("no header.h file");
|
||||
assert!(file.contains("wasmer_function_6f62a6bc5c8f8e3e12a54e2ecbc5674ccfe1c75f91d8e4dd6ebb3fec422a4d6c_0"), "no wasmer_function_6f62a6bc5c8f8e3e12a54e2ecbc5674ccfe1c75f91d8e4dd6ebb3fec422a4d6c_0 in file");
|
||||
|
||||
let _ = Command::new(get_wasmer_path())
|
||||
.arg("gen-c-header")
|
||||
.arg(&wasm_path)
|
||||
.arg("-o")
|
||||
.arg(&out_path)
|
||||
.arg("--prefix")
|
||||
.arg("abc123")
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
let file = std::fs::read_to_string(&out_path).expect("no header.h file");
|
||||
assert!(
|
||||
file.contains("wasmer_function_abc123_0"),
|
||||
"no wasmer_function_abc123_0 in file"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_c_header_works_pirita() -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::tempdir()?;
|
||||
let operating_dir: PathBuf = temp_dir.path().to_owned();
|
||||
|
||||
let wasm_path = operating_dir.join(create_exe_wabt_path());
|
||||
let out_path = temp_dir.path().join("header.h");
|
||||
|
||||
let _ = Command::new(get_wasmer_path())
|
||||
.arg("gen-c-header")
|
||||
.arg(&wasm_path)
|
||||
.arg("-o")
|
||||
.arg(&out_path)
|
||||
.arg("--atom")
|
||||
.arg("wasm-validate")
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
let file = std::fs::read_to_string(&out_path).expect("no header.h file");
|
||||
assert!(file.contains("wasmer_function_0f41d38dcfb5abc1fadb5e9acbc5c645e53fe4d0dd86270b72a09bfeee04d055_0"), "no wasmer_function_6f62a6bc5c8f8e3e12a54e2ecbc5674ccfe1c75f91d8e4dd6ebb3fec422a4d6c_0 in file");
|
||||
|
||||
let cmd = Command::new(get_wasmer_path())
|
||||
.arg("gen-c-header")
|
||||
.arg(&wasm_path)
|
||||
.arg("-o")
|
||||
.arg(&out_path)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
assert!(!cmd.status.success());
|
||||
|
||||
Ok(())
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
use anyhow::{bail, Context};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::process::{Command, Stdio};
|
||||
use wasmer_integration_tests_cli::{get_repo_root_path, get_wasmer_path, ASSET_PATH, C_ASSET_PATH};
|
||||
|
||||
fn wasi_test_python_path() -> PathBuf {
|
||||
@ -25,6 +25,7 @@ fn test_no_start_wat_path() -> PathBuf {
|
||||
fn test_cross_compile_python_windows() -> anyhow::Result<()> {
|
||||
let temp_dir = tempfile::TempDir::new()?;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
let targets = &[
|
||||
"aarch64-darwin",
|
||||
"x86_64-darwin",
|
||||
@ -33,6 +34,14 @@ fn test_cross_compile_python_windows() -> anyhow::Result<()> {
|
||||
"x86_64-windows-gnu",
|
||||
];
|
||||
|
||||
#[cfg(windows)]
|
||||
let targets = &[
|
||||
"aarch64-darwin",
|
||||
"x86_64-darwin",
|
||||
"x86_64-linux-gnu",
|
||||
"aarch64-linux-gnu",
|
||||
];
|
||||
|
||||
// MUSL has no support for LLVM in C-API
|
||||
#[cfg(target_env = "musl")]
|
||||
let compilers = &["cranelift", "singlepass"];
|
||||
@ -202,14 +211,17 @@ fn package_directory(in_dir: &PathBuf, out: &PathBuf) {
|
||||
|
||||
/// TODO: on linux-musl, the packaging of libwasmer.a doesn't work properly
|
||||
/// Tracked in https://github.com/wasmerio/wasmer/issues/3271
|
||||
#[cfg(not(target_env = "musl"))]
|
||||
#[cfg(not(any(target_env = "musl", target_os = "windows")))]
|
||||
#[cfg(feature = "webc_runner")]
|
||||
#[test]
|
||||
fn test_wasmer_create_exe_pirita_works() -> anyhow::Result<()> {
|
||||
// let temp_dir = Path::new("debug");
|
||||
// std::fs::create_dir_all(&temp_dir);
|
||||
let temp_dir = tempfile::TempDir::new()?;
|
||||
let python_wasmer_path = temp_dir.path().join("python.wasmer");
|
||||
let temp_dir = temp_dir.path().to_path_buf();
|
||||
let python_wasmer_path = temp_dir.join("python.wasmer");
|
||||
std::fs::copy(wasi_test_python_path(), &python_wasmer_path)?;
|
||||
let python_exe_output_path = temp_dir.path().join("python");
|
||||
let python_exe_output_path = temp_dir.join("python");
|
||||
|
||||
let native_target = target_lexicon::HOST;
|
||||
let root_path = get_repo_root_path().unwrap();
|
||||
@ -217,8 +229,7 @@ fn test_wasmer_create_exe_pirita_works() -> anyhow::Result<()> {
|
||||
if !package_path.exists() {
|
||||
panic!("package path {} does not exist", package_path.display());
|
||||
}
|
||||
let tmp_targz_path = tempfile::TempDir::new()?;
|
||||
let tmp_targz_path = tmp_targz_path.path().join("link.tar.gz");
|
||||
let tmp_targz_path = temp_dir.join("link.tar.gz");
|
||||
println!("compiling to target {native_target}");
|
||||
println!(
|
||||
"packaging /package to .tar.gz: {}",
|
||||
@ -241,10 +252,17 @@ fn test_wasmer_create_exe_pirita_works() -> anyhow::Result<()> {
|
||||
cmd.arg(format!("{native_target}"));
|
||||
cmd.arg("-o");
|
||||
cmd.arg(&python_exe_output_path);
|
||||
|
||||
// change temp_dir to a local path and run this test again
|
||||
// to output the compilation files into a debug folder
|
||||
//
|
||||
// cmd.arg("--debug-dir");
|
||||
// cmd.arg(&temp_dir);
|
||||
println!("running: {cmd:?}");
|
||||
|
||||
let output = cmd.output()?;
|
||||
let output = cmd
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.output()?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stdout = std::str::from_utf8(&output.stdout)
|
||||
|
Reference in New Issue
Block a user