Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

load wasm that build with golang #18

Closed
bonly opened this issue May 30, 2019 · 12 comments
Closed

load wasm that build with golang #18

bonly opened this issue May 30, 2019 · 12 comments
Assignees
Labels
📦 component-runtime About the Wasm runtime ❓ question Further information is requested

Comments

@bonly
Copy link

bonly commented May 30, 2019

Thanks for the bug report!

Describe the bug

when I build wasm with go and wasm.NewInstance from the wasm bin, error result with:

Failed to compile the module.

A clear and concise description of what the bug is.

Steps to reproduce

  1. build wasm with go
    GOARCH=wasm GOOS=js go build -o wa.wasm wa.go
    cat wa.go:
package main

//export Sum
func Sum(x, y int) int {
	return x + y
}

func main() {
}
  1. build go program
    go build main.go
    cat main.go:
package main

import (
	"fmt"
	wasm "github.com/wasmerio/go-ext-wasm/wasmer"
)

func main() {
	bytes, err := wasm.ReadBytes("wa.wasm");
	if err != nil{
		fmt.Println(err);
		return
	}
	inst, err := wasm.NewInstance(bytes);
	if err != nil{
		fmt.Println(err);
		return
	}
	defer inst.Close();

	sum := inst.Exports["sum"]

	result, err := sum(5,37);
	if err != nil{
		fmt.Println(err);
		return;
	}
	fmt.Println(result);
}
  1. Run
./main
  1. See error
    Failed to compile the module.
@bonly bonly added the 🐞 bug Something isn't working label May 30, 2019
@syrusakbary
Copy link
Member

This is likely to be happening because some of the required imports are not present.

We probably need to improve the error message to show the detailed error.

@Hywan
Copy link
Contributor

Hywan commented Jun 3, 2019

Thanks for the bug report!
Error messages are already better in the next runtime release, see https://github.com/wasmerio/wasmer/pull/467/files.

However, maybe you can find a better definition with wasm.GetLastError. I tried with the following code:

package main

import (
	"fmt"
	wasm "github.com/wasmerio/go-ext-wasm/wasmer"
)

func main() {
	bytes, err := wasm.ReadBytes("wa.wasm")

	if err != nil {
		fmt.Println(err)
		return
	}

	inst, err := wasm.NewInstance(bytes)

	if err != nil {
		fmt.Println(err)
		fmt.Println(wasm.GetLastError())
		return
	}

	defer inst.Close()
}

Then I run it with go run main.go and got:

Failed to compile the module.
7 link errors: (1 of 7)
Import not found, namespace: go, name: runtime.wasmExit (2 of 7)
Import not found, namespace: go, name: runtime.wasmWrite (3 of 7)
Import not found, namespace: go, name: runtime.nanotime (4 of 7)
Import not found, namespace: go, name: runtime.walltime (5 of 7)
Import not found, namespace: go, name: runtime.scheduleTimeoutEvent (6 of 7)
Import not found, namespace: go, name: runtime.clearTimeoutEvent (7 of 7)
Import not found, namespace: go, name: runtime.getRandomData <nil>

I suggest to use NewInstanceWithImports but imported function are declared in the env namespace, not in the go namespace. That's a missing feature currently.

@Hywan Hywan self-assigned this Jun 3, 2019
@Hywan Hywan added ❓ question Further information is requested 📦 component-runtime About the Wasm runtime and removed 🐞 bug Something isn't working labels Jun 3, 2019
@Hywan Hywan closed this as completed Jun 4, 2019
@Hywan
Copy link
Contributor

Hywan commented Jun 4, 2019

See #29 to see how to import functions in multiple namespaces.

@Irooniam
Copy link

Irooniam commented Jun 4, 2019

Hi @Hywan can you provide a quick example how to import functions into multiple namespaces?

Like the parent, I tried running a go-compiled "hello world" wasm, and I get the following:
instance Failed to compile the module. 18 link errors: (1 of 18) Import not found, namespace: go, name: debug (2 of 18) Import not found, namespace: go, name: runtime.wasmExit (3 of 18) Import not found, namespace: go, name: runtime.wasmWrite (4 of 18) Import not found, namespace: go, name: runtime.nanotime (5 of 18) Import not found, namespace: go, name: runtime.walltime (6 of 18) Import not found, namespace: go, name: runtime.scheduleTimeoutEvent (7 of 18) Import not found, namespace: go, name: runtime.clearTimeoutEvent (8 of 18) Import not found, namespace: go, name: runtime.getRandomData (9 of 18) Import not found, namespace: go, name: syscall/js.stringVal (10 of 18) Import not found, namespace: go, name: syscall/js.valueGet (11 of 18) Import not found, namespace: go, name: syscall/js.valueSet (12 of 18) Import not found, namespace: go, name: syscall/js.valueIndex (13 of 18) Import not found, namespace: go, name: syscall/js.valueSetIndex (14 of 18) Import not found, namespace: go, name: syscall/js.valueCall (15 of 18) Import not found, namespace: go, name: syscall/js.valueNew (16 of 18) Import not found, namespace: go, name: syscall/js.valueLength (17 of 18) Import not found, namespace: go, name: syscall/js.valuePrepareString (18 of 18) Import not found, namespace: go, name: syscall/js.valueLoadString <nil>

Any help would be appreciated.

@Hywan
Copy link
Contributor

Hywan commented Jun 21, 2019

You can check https://github.com/wasmerio/go-ext-wasm/blob/722faa9f1b902d404e87c40ea2bb6bdd5e228a51/wasmer/test/imports.go#L36-L52.

Basically, it looks like:

imports, _ :=
	wasm.NewImports().
		Namespace("env1").
			Append("f", f, C.f).
			Append("g", g, C.g).
		Namespace("env2").
			Append("h", h, C.h)

instance, _ := wasm.NewInstanceWithImports(wasm_bytes, imports)
…

Does it help?

@Hywan Hywan reopened this Jun 21, 2019
bors bot added a commit that referenced this issue Jun 24, 2019
51: test(import) Test that all WAsm types can be used in imported functions r=Hywan a=Hywan

Related to #18.

Co-authored-by: Ivan Enderlin <[email protected]>
@Hywan Hywan closed this as completed Jul 8, 2019
@pkieltyka
Copy link

is it not possible for wasmer to parse out the imports when it reads the bytes and creates the instance? our nodejs version is able to load our wasm bytes just fine..

@Hywan
Copy link
Contributor

Hywan commented Aug 22, 2019

It is possible to read the imports and exports from the module. Check the Module structure:

type Module struct {
    Exports []ExportDescriptor
    Imports []ImportDescriptor
}

@rusenask
Copy link

Hello, I am new to wasm and just trying out wasmer go-ext-wasm. Getting the same one

8 link errors: (1 of 8) Import not found, namespace: go, name: debug (2 of 8) Import not found, namespace: go, name: runtime.wasmExit (3 of 8) Import not found, namespace: go, name: runtime.wasmWrite (4 of 8) Import not found, namespace: go, name: runtime.nanotime (5 of 8) Import not found, namespace: go, name: runtime.walltime (6 of 8) Import not found, namespace: go, name: runtime.scheduleTimeoutEvent (7 of 8) Import not found, namespace: go, name: runtime.clearTimeoutEvent (8 of 8) Import not found, namespace: go, name: runtime.getRandomData

And I see that the issue is closed with that example:

imports, _ :=
	wasm.NewImports().
		Namespace("env1").
			Append("f", f, C.f).
			Append("g", g, C.g).
		Namespace("env2").
			Append("h", h, C.h)

instance, _ := wasm.NewInstanceWithImports(wasm_bytes, imports)

But I am still not sure how does this help? What are these and where they are coming from?

Namespace("env1").
			Append("f", f, C.f).
			Append("g", g, C.g).
		Namespace("env2").
			Append("h", h, C.h)

Is there anything specific that we need to do before running Go? Tried tinygo and go, both have slightly different errors :|

@Hywan
Copy link
Contributor

Hywan commented Dec 6, 2019

The Go compiler emits a WebAssembly module with specific host functions (imports). It is very JavaScript centric.

The TinyGo compiler emits a WebAssembly module that works for JS but also other hosts, like a server.

See #95, which is likely to help.

One question though: What's your usecase to compile Go to Wasm, to then run it in Go?

@rusenask
Copy link

rusenask commented Dec 6, 2019

Currently writing a side project for my other side project (https://webhookrelay.com/) that will allow users to upload their wasm code snippets to modify webhooks before they are forwarded to their final destination. Initially started just with Lua but wasm seems so much more interesting, therefore after some time I decided to try out wasmer :)

For example to modify webhook method when it comes as a PUT request to POST:

extern "C" {
    fn ext_set_request_method(ptr: *const u8, len: usize);
}

#[no_mangle]
pub extern fn handleRequest(_ptr: i32, _len: i32) {
    
    let method = "POST";
    unsafe {
        ext_set_request_method(method.as_ptr(), method.len());
    }
}

As a Go developer myself I would prefer using Go, although Rust is also fun, not sure about other people though :)

@danlaine
Copy link

danlaine commented Apr 3, 2020

@Hywan Hello! So if I understand correctly there's no way to import a .wasm file that was compiled from Go. Is that right?

@Hywan
Copy link
Contributor

Hywan commented Apr 6, 2020

@danlaine It is possible, but it requires some jugglery. Take a look at #95 for an attempt to simplify this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 component-runtime About the Wasm runtime ❓ question Further information is requested
Projects
None yet
Development

No branches or pull requests

7 participants