tinygo icon indicating copy to clipboard operation
tinygo copied to clipboard

Wasi target command flag vs environment variables

Open mattjohnsonpint opened this issue 1 year ago • 2 comments
trafficstars

My understanding is that setting GOOS=wasip1 GOARCH=wasm should produce identical output as passing the -target wasi command line flag, but it doesn't. Rather, it seem to match -target wasm.

Repro:

package main

func main() {
	println("Hello, World!")
}

You'll need wasm2wat from The WebAssembly Binary Toolkit.

Then:

  • Compile the different ways. Optimizations off to see everything.
tinygo build -target wasi -opt 0 -o test1.wasm
tinygo build -target wasm -opt 0 -o test2.wasm
GOOS=wasip1 GOARCH=wasm tinygo build -opt 0 -o test3.wasm
  • Convert output to WAT format for readability
wasm2wat test1.wasm -o test1.wat
wasm2wat test2.wasm -o test2.wat
wasm2wat test3.wasm -o test3.wat

Open each wat file in a text editor. Imports are near the top, exports are near the bottom.

test1.wat

...
(import "wasi_snapshot_preview1" "fd_write" (func $runtime.fd_write (type 4)))
(import "wasi_snapshot_preview1" "poll_oneoff" (func $runtime.poll_oneoff (type 4)))
(import "wasi_snapshot_preview1" "clock_time_get" (func $runtime.clock_time_get (type 16)))
...
(export "memory" (memory 0))
(export "malloc" (func $malloc))
(export "free" (func $free))
(export "calloc" (func $calloc))
(export "realloc" (func $realloc))
(export "_start" (func $_start))
(export "asyncify_start_unwind" (func 168))
(export "asyncify_stop_unwind" (func 169))
(export "asyncify_start_rewind" (func 170))
(export "asyncify_stop_rewind" (func 171))
(export "asyncify_get_state" (func 172))
...

test2.wat / test3.wat

...
(import "gojs" "runtime.ticks" (func $runtime.ticks (type 15)))
(import "gojs" "runtime.sleepTicks" (func $runtime.sleepTicks (type 16)))
(import "wasi_snapshot_preview1" "fd_write" (func $runtime.fd_write (type 4)))
...
(export "memory" (memory 0))
(export "malloc" (func $malloc.command_export))
(export "free" (func $free.command_export))
(export "calloc" (func $calloc.command_export))
(export "realloc" (func $realloc.command_export))
(export "_start" (func $_start.command_export))
(export "resume" (func $resume.command_export))
(export "go_scheduler" (func $go_scheduler.command_export))
(export "asyncify_start_unwind" (func 175))
(export "asyncify_stop_unwind" (func 176))
(export "asyncify_start_rewind" (func 177))
(export "asyncify_stop_rewind" (func 178))
(export "asyncify_get_state" (func 179))
...

They should be identical, but test3 is importing from gojs, and is also exporting go_scheduler. It's identical to test2, whereas I would expect it to match test1.

mattjohnsonpint avatar Aug 27 '24 15:08 mattjohnsonpint

I think this will probably be solved by https://github.com/tinygo-org/tinygo/pull/4437

/cc @aykevl

dgryski avatar Aug 27 '24 21:08 dgryski

The problem here is the file extension, which apparently overrides the environment variables. That's a bug.

https://github.com/tinygo-org/tinygo/blob/ef4f46f1d1550beb62324d750c496b2b4a7f76d0/main.go#L1569-L1571

Maybe we should just remove this special case? It means that people that currently rely on the extension will have to provide some explicit flags or environment variables, but it's certainly more explicit and less "magic". (I think it was originally introduced when wasm was mostly a browser thing and WASI didn't really exist yet).

aykevl avatar Aug 29 '24 11:08 aykevl

Note that until this is fixed, the docs are wrong. https://tinygo.org/docs/guides/webassembly/wasi/

mattjohnsonpint avatar Dec 23 '24 18:12 mattjohnsonpint

Closed as part of v0.36.0

deadprogram avatar Mar 04 '25 06:03 deadprogram