duanlaiyin2356 2014-06-22 11:17
浏览 162
已采纳

如何在Linux上编译跨平台的Go语言项目?

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&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=osaka&amp;aq=&amp;sll=34.885931,-115.180664&amp;sspn=29.912003,39.506836&amp;brcurrent=3,0x6000e86b2acc70d7:0xa399ff48811f596d,0&amp;ie=UTF8&amp;hq=&amp;hnear=%E5%A4%A7%E9%98%AA%E5%BA%9C%E5%A4%A7%E9%98%AA%E5%B8%82&amp;ll=34.693738,135.502165&amp;spn=0.471406,0.617294&amp;z=11&amp;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
")
}

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.
  • 写回答

1条回答 默认 最新

  • douzhantao2857 2014-06-22 12:56
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 python使用pulp线性优化时报错
  • ¥15 开源或低价数据中台哪个最好
  • ¥15 arduino编程出现字符串疑似覆盖现象
  • ¥15 我的b站在没有碰到屏幕的情况下偶尔会自动跳出进度条,就像在屏幕上点了一下一样,但我并没有点。而且视频进度并没有变。这可能是什么原因造成的?
  • ¥30 STK matlab python仿真
  • ¥15 关于IMageEnView 图标定位问题
  • ¥20 求解答(matlab)
  • ¥30 ffmpeg库使用过程中遇到的问题
  • ¥15 pyqt5 中python如何通过Qtwebchannel主动发消息给web前端
  • ¥15 关于HTML中title获取xml内容的问题