I am trying to set up my Go compiler on Linux which could compile project for any other architecture or platform. I am using default packages from official Ubuntu 14.04 repositories and I am using 64 bit system. This configuration allows me to compile only for Linux and only for 64 bit system. At least I would like to compile for 32 bit Linux or even for 32 bit Windows systems. Is it possible to do somehow?
One additional thing is I want to use two Go bindings: https://github.com/mattn/go-gtk and https://github.com/mattn/go-webkit
I was testing with go-webkit example code:
package main
import (
"os"
"github.com/mattn/go-gtk/gtk"
"github.com/mattn/go-webkit/webkit"
)
const HTML_STRING = `
<doctype html>
<meta charset="utf-8"/>
<style>
div { font-size: 5em }
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(function() {
$('#hello1').slideDown('slow', function() {
$('#hello2').fadeIn()
})
})
</script>
<div id="hello1" style="display: none">Hello</div>
<div id="hello2" style="display: none">世界</div>
</div>
`
const MAP_EMBED = `
<style> *{ margin : 0; padding : 0; } </style>
<iframe width="100%" height="100%" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.co.jp/maps?f=q&source=s_q&hl=en&geocode=&q=osaka&aq=&sll=34.885931,-115.180664&sspn=29.912003,39.506836&brcurrent=3,0x6000e86b2acc70d7:0xa399ff48811f596d,0&ie=UTF8&hq=&hnear=%E5%A4%A7%E9%98%AA%E5%BA%9C%E5%A4%A7%E9%98%AA%E5%B8%82&ll=34.693738,135.502165&spn=0.471406,0.617294&z=11&output=embed"></iframe>
`
func main() {
gtk.Init(nil)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window.SetTitle("webkit")
window.Connect("destroy", gtk.MainQuit)
vbox := gtk.NewVBox(false, 1)
entry := gtk.NewEntry()
entry.SetText("http://golang.org/")
vbox.PackStart(entry, false, false, 0)
swin := gtk.NewScrolledWindow(nil, nil)
swin.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swin.SetShadowType(gtk.SHADOW_IN)
webview := webkit.NewWebView()
webview.Connect("load-committed", func() {
entry.SetText(webview.GetUri())
})
swin.Add(webview)
vbox.Add(swin)
entry.Connect("activate", func() {
webview.LoadUri(entry.GetText())
})
button := gtk.NewButtonWithLabel("load String")
button.Clicked(func() {
webview.LoadString("hello Go GTK!", "text/plain", "utf-8", ".")
})
vbox.PackStart(button, false, false, 0)
button = gtk.NewButtonWithLabel("load HTML String")
button.Clicked(func() {
webview.LoadHtmlString(HTML_STRING, ".")
})
vbox.PackStart(button, false, false, 0)
button = gtk.NewButtonWithLabel("Google Maps")
button.Clicked(func() {
webview.LoadHtmlString(MAP_EMBED, ".")
})
vbox.PackStart(button, false, false, 0)
window.Add(vbox)
window.SetSizeRequest(600, 600)
window.ShowAll()
proxy := os.Getenv("HTTP_PROXY")
if len(proxy) > 0 {
soup_uri := webkit.SoupUri(proxy)
webkit.GetDefaultSession().Set("proxy-uri", soup_uri)
soup_uri.Free()
}
entry.Emit("activate")
gtk.Main()
}
It works fine if I compile it with
go build
If I try to compile it with other settings:
GOOS=windows GOARCH=386 go build
GOARCH=386 go build
I get this error:
webview.go:5:2: no buildable Go source files in /home/yeeapple/Documents/Coding/Go/Source/src/github.com/mattn/go-gtk/gtk
webview.go:6:2: no buildable Go source files in /home/yeeapple/Documents/Coding/Go/Source/src/github.com/mattn/go-webkit/webkit
Another thing I saw is that in GOPATH directory and pkg folder is only "linux_amd64" folder with *.a files.
For example, I can compile Go files for other systems if it does not have additional imports. Cross-platform compiling works fine with:
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
Versions:
$ go version
go version go1.2.1 linux/amd64
$ gccgo --version
gccgo (Ubuntu 4.9-20140406-0ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]
Copyright (C) 2014 Free Software Foundation, Inc.
With Go 1.2, the cgo
feature is disabled when cross compiling code. This means that any source file containing import "C"
will not be compiled, which leaves many packages unusable. So while your simple "hello world" program compiles, an equivalent one using cgo
will fail:
package main
/*
#include <stdlib.h>
#include <stdio.h>
*/
import "C"
import "unsafe"
func main() {
hello := C.CString("Hello world")
defer C.free(unsafe.Pointer(hello))
C.puts(hello)
}
On an amd64 Linux system, you will get a build failure if you try to compile for x86:
$ GOARCH=386 go build hello.go
can't load package: no buildable Go source files in /...
To get this program to compile, you will also need to set the environment variable CGO_ENABLED=1
to manually enable cgo
. This will cause it to attempt to compile the program, but it will still fail if you don't have an x86 compiler installed. Since you said you are using Ubuntu, you can do this by installing the gcc-multilib
package:
$ sudo apt-get install gcc-multilib
With that installed, you should be able to compile the program:
$ GOARCH=386 CGO_ENABLED=1 go build hello.go
$ file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=..., not stripped
While Ubuntu comes with a Windows cross compile tool chain (in the mingw32
package), you'll still have trouble compiling Windows binaries:
$ GOOS=windows GOARCH=386 CGO_ENABLED=1 go build hello.go
go build runtime/cgo: cannot use cgo when compiling for a different operating system
This check is no longer present in GO 1.3, so you may have some luck with that release.
Now having the cross-compiler tool chain available is only part of the battle: you will also need versions of the your dependencies compiled for the target architecture(s) available. This isn't going to be trivial for something as big as WebKit, but you could probably point Go at an appropriate copy using the CFLAGS
, LDFLAGS
and PKG_CONFIG_PATH
environment variables.