veandco / go-sdl2

SDL2 binding for Go
https://godoc.org/github.com/veandco/go-sdl2
BSD 3-Clause "New" or "Revised" License
2.2k stars 218 forks source link

Linker error when compiling to Windows when importing github.com/andlabs/ui #362

Open jclc opened 5 years ago

jclc commented 5 years ago

I'm importing this package alongside github.com/andlabs/ui and I get this error when cross-compiling to Windows using mingw:

/usr/lib/go/pkg/tool/linux_amd64/link: running x86_64-w64-mingw32-g++ failed: exit status 1
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windows.o):(.text+0x17f): undefined reference to `__imp_CoInitializeEx'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0xf6): undefined reference to `ImmGetIMEFileNameA'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x144): undefined reference to `ImmGetContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x167): undefined reference to `ImmReleaseContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x1d4): undefined reference to `ImmGetCompositionStringW'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x1ec): undefined reference to `ImmGetCompositionStringW'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x3ff): undefined reference to `ImmGetIMEFileNameA'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x569): undefined reference to `GetFileVersionInfoSizeA'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x595): undefined reference to `GetFileVersionInfoA'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x5bf): undefined reference to `VerQueryValueA'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x85c): undefined reference to `__imp_SysFreeString'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x9ee): undefined reference to `ImmGetContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0xa0c): undefined reference to `ImmNotifyIME'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0xa29): undefined reference to `ImmNotifyIME'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0xa35): undefined reference to `ImmReleaseContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0xa83): undefined reference to `ImmSetCompositionStringW'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0xb13): undefined reference to `ImmAssociateContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0xc2d): undefined reference to `ImmGetContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0xc3c): undefined reference to `ImmReleaseContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x12bd): undefined reference to `ImmAssociateContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x14f5): undefined reference to `ImmAssociateContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x158c): undefined reference to `ImmGetContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x15bd): undefined reference to `ImmSetCompositionWindow'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x15c9): undefined reference to `ImmReleaseContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x16a1): undefined reference to `ImmGetContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x16ed): undefined reference to `ImmReleaseContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x17de): undefined reference to `ImmGetContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x17ff): undefined reference to `ImmGetCandidateListW'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x1814): undefined reference to `ImmReleaseContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x198b): undefined reference to `ImmGetContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x1a21): undefined reference to `ImmReleaseContext'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x1a6d): undefined reference to `ImmGetCandidateListW'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x1dc6): undefined reference to `__imp_SysFreeString'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_windowskeyboard.o):(.text+0x1ebb): undefined reference to `__imp_SysFreeString'
/usr/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(SDL_wasapi.o):(.text+0x355): undefined reference to `__imp_PropVariantClear'
collect2: virhe: ld:n paluuarvo oli 1

The package ui uses C++, could this be confusing the Go linker into using C++ linkage for SDL2?

jclc commented 5 years ago

https://github.com/andlabs/ui/issues/326#issuecomment-426847357 Apparently some linker flags are lost in the ether when including both packages. Appending -lole32 -loleaut32 -limm32 -lversion to CGO_LDFLAGS fixes this issue.

veeableful commented 5 years ago

Hi @jclc, does that mean the ui package is the one that requires the extra link libraries?

jclc commented 5 years ago

The error message is triggered by SDL2, so I would imagine that it's an SDL2 issue. Adding these linker flags as a CGO directive would probably fix it, but I'd like to know the root cause of it.

veeableful commented 5 years ago

It seems some people experienced it because they were compiling statically or have only static SDL2 library in their paths. Maybe it's because the ui package compiles with -static option?

jclc commented 5 years ago

You're right, it seems that SDL2 is now linked statically... that's not good. ui being linked statically shouldn't affect SDL2, so I believe this is an issue with Go.

veeableful commented 5 years ago

Perhaps you could try compiling the program via go get -tags static and go build -tags static? We had support for static build since 0.3 (thanks gen2brain!).

jclc commented 5 years ago

Yeah that's the thing though, ui seems to force static linking on SDL2 which I don't want. Also, the error comes from g++ for some reason. ui uses C++ on Windows and it's also forcing SDL2 to use it as well, I don't think that's intended.

andlabs commented 5 years ago

It should still be possible to dynamically link SDL2 even with package ui; that's weird. I'll have to look at the build tags of this package...

The C++ linker should not affect anything. If SDL is affected by it, then we have a problem with SDL...

jclc commented 5 years ago

Returning to my project after a while, I'm finding more linker flags being lost.

/usr/local/go/pkg/tool/linux_amd64/link: running x86_64-w64-mingw32-g++ failed: exit status 1
/usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld: /usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(hid.o):(.text+0x382): undefined reference to `__imp_SetupDiGetClassDevsA'
/usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld: /usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(hid.o):(.text+0x391): undefined reference to `__imp_SetupDiGetDeviceRegistryPropertyA'
/usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld: /usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(hid.o):(.text+0x3e0): undefined reference to `__imp_SetupDiEnumDeviceInterfaces'
/usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld: /usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(hid.o):(.text+0x40d): undefined reference to `__imp_SetupDiGetDeviceInterfaceDetailA'
/usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld: /usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(hid.o):(.text+0x445): undefined reference to `__imp_SetupDiGetDeviceInterfaceDetailA'
/usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld: /usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(hid.o):(.text+0x456): undefined reference to `__imp_SetupDiEnumDeviceInfo'
/usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld: /usr/lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libSDL2.a(hid.o):(.text+0x585): undefined reference to `__imp_SetupDiDestroyDeviceInfoList'

Adding -lsetupapi fixes this error. I'm not sure if upgrading mingw or SDL2 triggered this. Again, this only happens when importing both go-sdl2 and ui in the same program.

Edit: Right, it's because Go is forcing static linking but without the static tag, so the LDFLAGS in sdl/sdl_cgo_static.go are being omitted. -lsetupapi was added in the most recent commit. Maybe a more appropriate name for this issue is "importing github.com/andlabs/ui forces static linking".

andlabs commented 5 years ago

Right; I've taken steps to allow libui to be statically linkable specifically to make it more Go-like in nature; the interplay between this and that is an interesting question, and one that's in scope for the next release. Please file a bug there so I can keep track of it.

jclc commented 5 years ago

Are you sure it's an issue with libui though? I have no issues importing both ui and https://github.com/mattn/go-sqlite3; only go-sdl2 seems to have this issue.

FYI the code I'm using to test this:

package main

import (
    _ "github.com/andlabs/ui"
    _ "github.com/mattn/go-sqlite3"
//  _ "github.com/veandco/go-sdl2/sdl"
    "fmt"
)

func main() {
    fmt.Println("ok")
}

CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ GOOS=windows go build main.go

veeableful commented 5 years ago

Hi @jclc, I'll have a look at this as well during the weekend. I'll keep you posted!

andlabs commented 5 years ago

It's not so much a problem with libui but a subtlety with mixing packages that expect different linking requirements. My question is about what's conventional for the rest of the Go open-source world, so I can provide the best possible solution. libui can be used dynamically and it would be great if I could provide that option as well...

veeableful commented 5 years ago

Hi @jclc, do you have problem when compiling with -tags static like this?

CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ GOOS=windows go build -tags static

I can't seem to reproduce the problem on my Linux OS with this code:

package main

import (
        _ "github.com/andlabs/ui"
        _ "github.com/mattn/go-sqlite3"
        _ "github.com/veandco/go-sdl2/sdl"
        "fmt"
)

func main() {
        fmt.Println("ok")
}
jclc commented 5 years ago

With https://github.com/veandco/go-sdl2/commit/d969945fa22d438e43c81c992cd4243d5278be05 that works, but only when using -tags static. The problem was linking ui statically but sdl dynamically.

veeableful commented 5 years ago

@jclc Ahh I see now! You're cross-compiling on Linux to Windows but require SDL2 to be dynamic.

In that case, could you try modifying sdl/sdl_cgo.go by replacing the #cgo windows ... line to this?

//#cgo windows LDFLAGS: -Wl, -Bdynamic -lSDL2

For me, I had to specify include path as well like the following. Perhaps you also need it.

//#cgo windows LDFLAGS: -Wl, -Bdynamic -lSDL2 -L [path-to-lib-dir]

I haven't tried to run it but at least it compiled for me =P

jclc commented 5 years ago

@veeableful Hi, sorry for the delay, I've been busy. What version of Go are you using? For me it says those flags are not valid; even adding them to CGO_LDFLAGS_ALLOW doesn't make a difference.

invalid flag in #cgo LDFLAGS: -Wl,

As a sidenote, I've decided it's better to just use static linkage on Windows anyway; maybe even on other platforms. I'll still help out figuring out this issue if needed.

andlabs commented 5 years ago

Remove the space after the comma.

jclc commented 5 years ago

Right, thanks... It does link SDL2 dynamically but now it also requires libstdc++-6.dll