bytecodealliance / wasmtime

A fast and secure runtime for WebAssembly
https://wasmtime.dev/
Apache License 2.0
15.31k stars 1.29k forks source link

Create an actually runnable executable in `wasm compile` #4563

Closed NobodyXu closed 2 years ago

NobodyXu commented 2 years ago

Feature

wasmtime compile currently generates an ELF on Linux/Mac but it cannot be executed from cmdline as a regular executable.

I would like a new option there to generate an actually runnable executable.

Benefit

This issue originally stems from cargo-binstall, a cmdline utility similar to cargo-install except that cargo-binstall installs binaries instead of compiling everything from source for rust binaries.

It can either install it from the url specified in the Cargo.tom of the upstream, or from cargo-quickinstall, or fallback to cargo-install.

We now want to support installation of wasm binaries as a fallback if the native executable isn't available for various reasons https://github.com/ryankurte/cargo-binstall/issues/246 and a problem we faced is that the wasm executable requires users to launch them using an wasm interpreter or using binfmt_misc on Linux.

We would have to wrap the wasm in a script to launch it, which makes the feature harder to implement and more prune to error. binfmt_misc on the other hand is only available on Linux and not every user configure that on installation.

We tried wasm compile, but the native binaries it generated cannot be run directly from cmdline.

Implementation

Since wasm can already generates an ELF on linux, I think it won't be too hard to actually generate something runnable from cmdline and can be used as any other native executables.

Though I am not familiar with the internal designs of wasmtime at all and could be wrong.

Alternatives

A universal way to run wasm binaries without having to specify the interpreters on Linux/Mac/Windows.

We want to use the wasm binaries as if it is a native executable.

bjorn3 commented 2 years ago

Since wasm can already generates an ELF on linux, I think it won't be too hard to actually generate something runnable from cmdline and can be used as any other native executables.

The ELF files are dependent on the wasmtime runtime for everything from handling traps, to managing the linear memory and tables, to calling wasi api's. Generating executable files would require embedding wasmtime inside the executables.

NobodyXu commented 2 years ago

Since wasm can already generates an ELF on linux, I think it won't be too hard to actually generate something runnable from cmdline and can be used as any other native executables.

The ELF files are dependent on the wasmtime runtime for everything from handling traps, to managing the linear memory and tables, to calling wasi api's. Generating executable files would require embedding wasmtime inside the executables.

Can we split that part as a dynamic library and let the generated executable to depend on that?

bjorn3 commented 2 years ago

Probably. A part of it would need to be embedded in the executable though to invoke wasmtime. In addition you would need to make sure that the dylib version matches the version of wasmtime that compiled it.

NobodyXu commented 2 years ago

In addition you would need to make sure that the dylib version matches the version of wasmtime that compiled it.

Right, I forgot about that part.

So I think it is better to embed the wasi binary to a script and let the script dynamically detect the wasm runtime. Will that interfere with wasmtime's caching system @bjorn3 ?

bjorn3 commented 2 years ago

Not sure. I think wasmtime hashes the wasm binary to determine the cache key, in which case caching should work.

NobodyXu commented 2 years ago

Not sure. I think wasmtime hashes the wasm binary to determine the cache key, in which case caching should work.

Thanks!

liudonghua123 commented 2 years ago

I would like this feature too. I see wasmer has this feature already. see https://docs.wasmer.io/ecosystem/wasmer/usage#wasmer-create-exe.

C:\Users\Liu.D.H>wasmer compile --help
wasmer-compile 2.3.0
Compile a WebAssembly binary

USAGE:
    wasmer compile [FLAGS] [OPTIONS] <FILE> -o <OUTPUT PATH>

FLAGS:
        --enable-all                Enable support for all pre-standard proposals
        --enable-bulk-memory        Enable support for the bulk memory proposal
        --cranelift                 Use Cranelift compiler
        --dylib                     Use the Dylib Engine
        --enable-verifier           Enable compiler internal verification
    -h, --help                      Prints help information
        --llvm                      Use LLVM compiler
        --enable-multi-value        Enable support for the multi value proposal
        --enable-reference-types    Enable support for the reference types proposal
        --enable-simd               Enable support for the SIMD proposal
        --singlepass                Use Singlepass compiler
        --staticlib                 Use the Staticlib Engine
        --enable-threads            Enable support for the threads proposal
        --universal                 Use the Universal Engine
    -V, --version                   Prints version information

OPTIONS:
        --header <HEADER PATH>      Output path for generated header file
    -o <OUTPUT PATH>                Output file
    -m <cpu-features>...
        --target <target-triple>    Compilation Target triple

ARGS:
    <FILE>    Input file

C:\Users\Liu.D.H>
C:\Users\Liu.D.H>wasmer create-exe --help
wasmer-create-exe 2.3.0
Compile a WebAssembly binary into a native executable

USAGE:
    wasmer create-exe [FLAGS] [OPTIONS] <FILE> -o <OUTPUT PATH>

FLAGS:
        --enable-all                Enable support for all pre-standard proposals
        --enable-bulk-memory        Enable support for the bulk memory proposal
        --cranelift                 Use Cranelift compiler
        --enable-verifier           Enable compiler internal verification
    -h, --help                      Prints help information
        --llvm                      Use LLVM compiler
        --enable-multi-value        Enable support for the multi value proposal
        --enable-reference-types    Enable support for the reference types proposal
        --enable-simd               Enable support for the SIMD proposal
        --singlepass                Use Singlepass compiler
        --enable-threads            Enable support for the threads proposal
    -V, --version                   Prints version information

OPTIONS:
    -o <OUTPUT PATH>                Output file
    -m <cpu-features>...
    -l <libraries>...               Additional libraries to link against. This is useful for fixing linker errors that
                                    may occur on some systems
        --target <target-triple>    Compilation Target triple

ARGS:
    <FILE>    Input file

C:\Users\Liu.D.H>
C:\Users\Liu.D.H>wasmtime compile --help
wasmtime-compile 1.0.0
Compiles a WebAssembly module

USAGE:
    wasmtime compile [OPTIONS] <MODULE>

ARGS:
    <MODULE>
            The path of the WebAssembly to compile

OPTIONS:
        --config <CONFIG_PATH>
            Use specified configuration file

        --cranelift-enable <SETTING>
            Enable a Cranelift boolean setting or preset.
            Use `wasmtime settings` to list Cranelift settings for a target.

        --cranelift-set <NAME=VALUE>
            Set a Cranelift setting to a given value.
            Use `wasmtime settings` to list Cranelift settings for a target.

        --disable-address-map
            Disables the on-by-default address map from native code to wasm code

        --disable-cache
            Disable cache system

        --disable-logging
            Disable logging

        --disable-memory-init-cow
            Disables the default of attempting to initialize linear memory via a copy-on-write
            mapping

        --dynamic-memory-guard-size <SIZE>
            Byte size of the guard region after dynamic memories are allocated

        --enable-cranelift-debug-verifier
            Enable Cranelift's internal debug verifier (expensive)

        --enable-cranelift-nan-canonicalization
            Enable Cranelift's internal NaN canonicalization

        --epoch-interruption
            Executing wasm code will yield when a global epoch counter changes, allowing for async
            operation without blocking the executor

        --fuel <N>
            Enable execution fuel with N units fuel, where execution will trap after running out of
            fuel.

            Most WebAssembly instructions consume 1 unit of fuel. Some instructions, such as `nop`,
            `drop`, `block`, and `loop`, consume 0 units, as any execution cost associated with them
            involves other instructions which do consume fuel.

    -g
            Generate debug information

    -h, --help
            Print help information

        --jitdump
            Generate jitdump file (supported on --features=profiling build)

        --log-to-files
            Log to per-thread log files instead of stderr

    -o, --output <OUTPUT>
            The path of the output compiled module; defaults to <MODULE>.cwasm

    -O, --optimize
            Run optimization passes on translated functions, on by default

        --opt-level <LEVEL>
            Optimization level for generated functions
            Supported levels: 0 (none), 1, 2 (most), or s (size); default is "most"

        --pooling-allocator
            Enables the pooling allocator, in place of the on-demand allocator

        --static-memory-forced
            Force using a "static" style for all wasm memories

        --static-memory-guard-size <SIZE>
            Byte size of the guard region after static memories are allocated

        --static-memory-maximum-size <MAXIMUM>
            Maximum size in bytes of wasm memory before it becomes dynamically relocatable instead
            of up-front-reserved

        --target <TARGET>
            The target triple; default is the host triple

    -V, --version
            Print version information

        --vtune
            Generate vtune (supported on --features=vtune build)

        --wasi-modules <MODULE,MODULE,...>
            Enables or disables WASI modules

        --wasm-features <FEATURE,FEATURE,...>
            Enables or disables WebAssembly features

By default, no CPU features or presets will be enabled for the compilation.

Supported values for `--wasm-features`:

all               enables all supported WebAssembly features
bulk-memory       enables support for bulk memory instructions
multi-memory      enables support for the multi-memory proposal
multi-value       enables support for multi-value functions
reference-types   enables support for reference types
simd              enables support for proposed SIMD instructions
threads           enables support for WebAssembly threads
memory64          enables support for 64-bit memories

Supported values for `--wasi-modules`:

default                    enables all stable WASI modules (no experimental modules)
wasi-common                enables support for the WASI common APIs, see
https://github.com/WebAssembly/WASI
experimental-wasi-nn       enables support for the WASI neural network API (experimental), see
https://github.com/WebAssembly/wasi-nn
experimental-wasi-crypto   enables support for the WASI cryptography APIs (experimental), see
https://github.com/WebAssembly/wasi-crypto

Features prefixed with '-' will be disabled.

Usage examples:

Compiling a WebAssembly module for the current platform:

  wasmtime compile example.wasm

Specifying the output file:

  wasmtime compile -o output.cwasm input.wasm

Compiling for a specific platform (Linux) and CPU preset (Skylake):

  wasmtime compile --target x86_64-unknown-linux --cranelift-enable skylake foo.wasm

C:\Users\Liu.D.H>