tinygo-org / tinygo

Go compiler for small places. Microcontrollers, WebAssembly (WASM/WASI), and command-line tools. Based on LLVM.
https://tinygo.org
Other
15.46k stars 912 forks source link

tinygo can't build packages other than main when modules are used #3464

Open the80srobot opened 1 year ago

the80srobot commented 1 year ago

I don't think there is any way to get tinygo to produce a build of a package (e.g. for use as a WASM export) if you're using go modules.

If you have a project with a go.mod file, then you can build it with Go, but not with tinygo. After a couple of hours of messing with tinygo, I haven't discovered any way to get it to actually build a Go project with modules that's not just a main package.

# Succeeds, produces mnist.o:
docker run --rm -v $(pwd):/home/tinygo tinygo/tinygo:0.27.0 go build -o mnist.o ./mnist/

# Fails for made-up reasons?
docker run --rm -v $(pwd):/home/tinygo tinygo/tinygo:0.27.0 tinygo build -o mnist.o ./mnist/
panic: expected main package to have name 'main'

goroutine 1 [running]:
github.com/tinygo-org/tinygo/loader.(*Package).Check(0x40002d9c20)
    /home/runner/work/tinygo/tinygo/loader/loader.go:389 +0x354
github.com/tinygo-org/tinygo/loader.(*Program).Parse(0x4000101110)
    /home/runner/work/tinygo/tinygo/loader/loader.go:315 +0xac
github.com/tinygo-org/tinygo/builder.Build({0xffffefbaff40, 0x8}, {0xffffefbaff38, 0x7}, {0x40000263f0, 0x15}, 0x40001c64b0)
    /home/runner/work/tinygo/tinygo/builder/build.go:205 +0x100c
main.Build({0xffffefbaff40, 0x8}, {0xffffefbaff38, 0x7}, 0x40001d0000)
    /home/runner/work/tinygo/tinygo/main.go:168 +0x194
main.main()
    /home/runner/work/tinygo/tinygo/main.go:1525 +0x2f58
aykevl commented 1 year ago

If you have a project with a go.mod file, then you can build it with Go, but not with tinygo. After a couple of hours of messing with tinygo, I haven't discovered any way to get it to actually build a Go project with modules that's not just a main package.

What happens in the case of go build? What kind of binary does it produce and how is the runtime initialized? Note that you can't just call exported functions without initializing the runtime first.

aykevl commented 1 year ago

Did a quick check and go build on a non-main package produces an archive, not an executable. I do not think it does what you think it does.

bxparks commented 1 year ago

For me, the usefulness of go build on a non-main package is that it runs the compiler, and produces warnings and error messages. This is currently not possible with tinygo build due to the above panic message.

The workaround is to create a stub xxx_test.go file, with an empty Test() function. We can then use tinygo test to run the compiler on the package.

During development and refactoring, the tests often lag behind the package code. It is useful to run tinygo build on the package code, get it compiling first, before moving on to fix all the broken tests.

aykevl commented 1 year ago

For me, the usefulness of go build on a non-main package is that it runs the compiler, and produces warnings and error messages. This is currently not possible with tinygo build due to the above panic message.

Right, that's actually a sensible use case. I'm not sure what to do with this though, as it doesn't make sense for TinyGo to produce archives (it currently requires whole-program transformation passes to work).

otaxhu commented 3 months ago

Same issue here, tinygo should allow compiling non-main packages and generate some kind of object file with symbols to link to another packages (main or others) using //go:linkname compiler directive.

The current behaviour of go build command in non-main packages is generating a Unix archive file containing two Go object files with unlinkable symbols.

The feature of compiling symbols to link against another packages has been shadow-removed from go build command and moved away to commands go tool compile and go tool link, I made an example recently of this in this repository

otaxhu commented 3 months ago

This could possibly fix this issue also #2703

By allowing compiling non-main packages

aykevl commented 1 month ago

I have turned the panic into a normal error message here: https://github.com/tinygo-org/tinygo/pull/4520 (Not a fix for this issue, and I'm not sure we even want to support this, but at least it prints an actual error message instead of panicking).