veandco / go-sdl2

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

Cross-compiling from Windows to Mac #497

Open kkevinchou opened 2 years ago

kkevinchou commented 2 years ago

Hello is there any guidance for cross-compiling from Windows to Mac? I get the following error:

$ CGO_ENABLED=1 GOOS=darwin CC="gcc" GOARCH=amd64 go build -o output
# runtime/cgo
gcc: error: x86_64: No such file or directory
gcc: error: unrecognized command line option '-arch'; did you mean '-march='?

I am using MinGW

veeableful commented 2 years ago

Hi @kkevinchou, we haven't tried to cross-compile from Windows to other OS. Perhaps using the Windows Subsystem for Linux, you could use the Linux to macOS method of cross-compilation?

kkevinchou commented 2 years ago

Thanks for the suggestion, I was hoping for something a little more out-of-the-box but that's a reasonable workaround 👍

veeableful commented 2 years ago

Sorry about that! It is because cross-compiling to macOS requires macOS' toolchain to do it. I'll write the steps here if you plan to try that method:

git clone https://github.com/tpoechtrager/osxcross
cd osxcross/tarballs
curl -O https://go-sdl2.veandco.sg-sin1.upcloudobjects.com/MacOSX10.11.sdk.tar.xz
cd ..
sudo apt update
sudo ./tools/get_dependencies.sh
sudo apt install -y cmake
SDK_VERSION=10.11 ./build.sh
./build_compiler_rt.sh

And then update PATH like this:

OSXCROSS="[path/to/osxcross]"
DARWIN="${OSXCROSS}/target"
DARWIN_SDK="${DARWIN}/SDK/MacOSX${SDK_VERSION}.sdk"
export PATH="${DARWIN}/bin:${DARWIN_SDK}/bin:${PATH}"

After that you should be able to cross-compile to macOS though I haven't fully tested those steps myself. Let me know if you encounter any problem!

CGO_ENABLED=1 CC=x86_64-apple-darwin15-clang GOOS=darwin GOARCH=amd64 go build -tags static -ldflags "-s -w" -a

There's on-going progress in implementing it for arm64 but due to some issues, it hasn't been fully realized.

depili commented 2 years ago

When I try with the above on a docker container I first get several linker warnings about the static libs being on newer osx versions than the binary being linked and then the linking fails on sdl_mixer with:

Undefined symbols for architecture x86_64:
  "_AudioUnitSetParameter", referenced from:
      _native_midi_setvolume in libSDL2_mixer_darwin_amd64.a(native_midi_macosx.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Trying to setup a CI macos build up for my project so that I wouldn't have to manually create the macos builds, and gitlab doesn't yet offer macos runners.

veeableful commented 2 years ago

Hi @depili, are you perhaps using the master branch or v0.5.x? If yes, could you try with v0.4.10?

depili commented 2 years ago

That was with 0.4.1 initially, tried 0.4.10 also but still getting the same error on the linking stage.

For reference my Dockerfile is

FROM debian:bullseye
MAINTAINER Vesa-Pekka Palmu <vpalmu@depili.fi>

ENV OSXCROSS=/usr/osxcross

RUN sed -i -e's/ main/ main contrib non-free/g' /etc/apt/sources.list

RUN apt-get update &&\
    apt-get install -y --no-install-recommends \
        ca-certificates \
        git \
        wget \
        cmake \
        build-essential \
        zip &&\
        apt-get clean

RUN wget https://golang.org/dl/go1.17.2.linux-amd64.tar.gz && rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.2.linux-amd64.tar.gz

ENV PATH=$PATH:/usr/local/go/bin

RUN git clone https://github.com/tpoechtrager/osxcross.git $OSXCROSS && \
    cd $OSXCROSS && \
    git checkout 0f87f567dfaf98460244471ad6c0f4311d62079c

COPY sdks/* $OSXCROSS/tarballs/

RUN cd $OSXCROSS && \
    ./tools/get_dependencies.sh

ENV DARWIN="${OSXCROSS}/target"
ENV DARWIN_SDK="${DARWIN}/SDK/MacOSX${SDK_VERSION}.sdk"
ENV SDK_VERSION=10.11
ENV 

RUN cd $OSXCROSS && \
    UNATTENDED=1 ./build.sh

ENV ENABLE_COMPILER_RT_INSTALL=1

RUN cd $OSXCROSS && \
    ./build_compiler_rt.sh \
    rm -rf build && \
    rm -rf wrapper

RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

ENV PATH=${DARWIN}/bin:${DARWIN_SDK}/bin:${PATH}

and the project in question that I'm trying to cross compile is https://gitlab.com/Depili/clock-8001

depili commented 2 years ago

and to be specific the the v4/cmd/sdl-clock of that project.

veeableful commented 2 years ago

Hi @depili, sorry for taking so long to reply! I added a commit that seems to fix the undefined symbol issue. Could you try the v0.4.x branch? If it does fix it, I will tag it immediately.

If you still have issues, would you please open another issue? We can continue discuss it there 🙂

depili commented 2 years ago

Seems to have fixed that linking error, now just running into other issues on my osx-crossbuild with (supposedly) the golang builtin time package...

Undefined symbols for architecture x86_64:
  "_clock_gettime", referenced from:
      _runtime.walltime_trampoline.abi0 in go.o
  "_getentropy", referenced from:
      _internal/syscall/unix.libc_getentropy_trampoline.abi0 in go.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

But this is probably unrelated to the go-sdl2 in of itself, just some other issue with osxcross and golang.

depili commented 2 years ago

Actually, doing a quick test and just trying to compile the example from go-sdl2 readme results in linking errors with _clock_gettime:

package main

import "github.com/veandco/go-sdl2/sdl"

func main() {
    if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
        panic(err)
    }
    defer sdl.Quit()

    window, err := sdl.CreateWindow("test", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
        800, 600, sdl.WINDOW_SHOWN)
    if err != nil {
        panic(err)
    }
    defer window.Destroy()

    surface, err := window.GetSurface()
    if err != nil {
        panic(err)
    }
    surface.FillRect(nil, 0)

    rect := sdl.Rect{0, 0, 200, 200}
    surface.FillRect(&rect, 0xffff0000)
    window.UpdateSurface()

    running := true
    for running {
        for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
            switch event.(type) {
            case *sdl.QuitEvent:
                println("Quit")
                running = false
                break
            }
        }
    }
}
CGO_ENABLED=1 CC=x86_64-apple-darwin15-clang GOOS=darwin GOARCH=amd64 go build -tags static -ldflags "-s -w" foo2.go
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running x86_64-apple-darwin15-clang failed: exit status 1
Undefined symbols for architecture x86_64:
  "_clock_gettime", referenced from:
      _runtime.walltime_trampoline.abi0 in go.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Just compiling a go program printing out time.Now(), runtime.GOOS and runtime.ReadBuildInfo() works when cross-compiled with osxcross.

depili commented 2 years ago

Using git head (e59a63461da2cbc20cb0a5bbfc954730e50a5472) of osxcross, if that matters.

veeableful commented 2 years ago

Hi @depili, you're right. It seems like macOS SDK 10.11 can't be used, at least with the Go 1.17. I was able to compile with macOS SDK 11.3 but I think any SDK version 10.13 or newer should work which seems to be requirement for Go 1.17 (https://golang.org/doc/go1.17). It might also work with an older Go versions like 1.16 if we don't want to upgrade the macOS SDK. I used this code as a test:

package main

/*
#include <stdio.h>

static void foo()
{
        fprintf(stdout, "Hello, World!");
}
*/
import "C"

func main() {
        C.foo()
}
depili commented 2 years ago

Unfortunately, I can't seem to get osxcross up with 10.13 as build_compiler_rt.sh fails, so can't test. Will try with go 1.16

depili commented 2 years ago

Trying with go1.16.9 and SDK 10.11 still runs into a linking problem, just one this time:

***@***.***:~/clock-8001/v4# cat foo.go
package main

import "github.com/veandco/go-sdl2/sdl"

func main() {
    if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
        panic(err)
    }
    defer sdl.Quit()

    window, err := sdl.CreateWindow("test",
sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
        800, 600, sdl.WINDOW_SHOWN)
    if err != nil {
        panic(err)
    }
    defer window.Destroy()

    surface, err := window.GetSurface()
    if err != nil {
        panic(err)
    }
    surface.FillRect(nil, 0)

    rect := sdl.Rect{0, 0, 200, 200}
    surface.FillRect(&rect, 0xffff0000)
    window.UpdateSurface()

    running := true
    for running {
        for event := sdl.PollEvent(); event != nil; event =
sdl.PollEvent() {
            switch event.(type) {
            case *sdl.QuitEvent:
                println("Quit")
                running = false
                break
            }
        }
    }
}
***@***.***:~/clock-8001/v4# CGO_ENABLED=1
CC=x86_64-apple-darwin15-clang GOOS=darwin GOARCH=amd64 go build -tags
static -ldflags "-s -w" foo.go
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running
x86_64-apple-darwin15-clang failed: exit status 1
Undefined symbols for architecture x86_64:
  "_clock_gettime", referenced from:
      _runtime.walltime_trampoline in go.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)

Will need to see if I can get any SDK other than 10.11 up with osxcross, can't go lower than go 1.16 since I use embed that requires go 1.16

depili commented 2 years ago

Finally had success, using liushuyu/osxcross container that is based on 10.14 SDK and go 1.16. For some reason my attempts of creating the SDK tarballs via the osxcross/tools/ scripts resulted always in something non-functional in the end.