Search code examples
gocross-compilingcgofyne

Go Fyne project can't cross compile from Linux to Windows


I made a Go fyne project, which works fine with go run ., and builds to Linux as expected with go build ..

However, when I try cross-compiling to windows using env GOOS=windows GOARCH=arm64 go build . it prints this error:

go: downloading github.com/tevino/abool v1.2.0
package playground.com/colors
    imports fyne.io/fyne/v2/app
    imports fyne.io/fyne/v2/internal/driver/glfw
    imports fyne.io/fyne/v2/internal/driver/common
    imports fyne.io/fyne/v2/internal/painter/gl
    imports github.com/go-gl/gl/v3.1/gles2: build constraints exclude all Go files in /home/mohamed/code/go/pkg/mod/github.com/go-gl/[email protected]/v3.1/gles2

I tried a clean install of Go, tried using go clean -modcache, tried creating a separate new module.

The code for error replication:

package main

import (
    "fmt"
    "image/color"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/widget"
)

func main() {
    app := app.NewWithID("Color Mixer")
    window := app.NewWindow("Color")

    red := widget.NewSlider(0, 255)
    green := widget.NewSlider(0, 255)
    blue := widget.NewSlider(0, 255)

    red_value := widget.NewLabel("0")
    green_value := widget.NewLabel("0")
    blue_value := widget.NewLabel("0")

    red_label := widget.NewLabel("Red")
    green_label := widget.NewLabel("Green")
    blue_label := widget.NewLabel("Blue")

    colorx := color.NRGBA{R: 0, G: 0, B: 0, A: 255}
    rect := canvas.NewRectangle(colorx)
    rect.SetMinSize(fyne.NewSize(300, 300))

    red.OnChanged =
        func(f float64) {
        _, g, b, a := rect.FillColor.RGBA()
        rect.FillColor = color.NRGBA{R: uint8(f),
            G: uint8(g),
            B: uint8(b),
            A: uint8(a)}
        rect.Refresh()
        red_value.SetText(fmt.Sprintf("%.0f", f))
        }

    green.OnChanged =
        func(f float64) {
        r, _, b, a := rect.FillColor.RGBA()
        rect.FillColor = color.NRGBA{R: uint8(r),
            G: uint8(f),
            B: uint8(b),
            A: uint8(a)}
        rect.Refresh()
        green_value.SetText(fmt.Sprintf("%.0f", f))
        }

    blue.OnChanged =
        func(f float64) {
        r, g, _, a := rect.FillColor.RGBA()
        rect.FillColor = color.NRGBA{R: uint8(r),
            G: uint8(g),
            B: uint8(f),
            A: uint8(a)}
        rect.Refresh()
        blue_value.SetText(fmt.Sprintf("%.0f", f))
        }

    box := container.NewGridWithRows(
        2,
        container.NewGridWithRows(3, red_label, green_label, blue_label, red, green, blue, red_value, green_value, blue_value),
        rect)

    window.SetContent(box)
    window.ShowAndRun()
}


Solution

  • IIRC, cross-compilation by default disables cgo, and since all the files in that github.com/go-gl/gl/v3.1/gles2 package make use of it, the building process naturally excludes them all, and produces the error you're seeing.

    Hence try building while having CGO_ENABLED=1 in your environment.
    A simple

    CGO_ENABLED=1 GOOS=windows go build
    

    should do the trick.

    Note that in order for the build process to actually produce the expected outcome you need to have the C cross-compiler for your target GOOS/GOARCH combo installed, and probably communicated to the go tool via setting the CC environment variable—see the docs.

    For instance, on Debian and its derivatives you will probably need to have the following packages installed:

    • gcc-mingw-w64-x86-64-win32 — for building for windows/amd64.
    • gcc-mingw-w64-i686-win32 — for building for windows/386.

    The values to set the CC variable will be /usr/bin/i686-w64-mingw32-gcc and /usr/bin/x86_64-w64-mingw32-gcc, correspondingly.

    I have no idea whether there's a MinGW cross-compiler package to target windows/arm64 which you seem to require, though, as I have zero experience with Windows on ARM devices.

    Also note that in order to produce a sensible Windows executable image file while cross-compiling you will probably want to also have CGO_LDFLAGS=-static-libgcc in your environment as well—this will produce a binary not dependent on libgcc.dll, and maybe you will even want to have CGO_LDFLAGS=-static-libgcc -static to have a fully-static build.