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.

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

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况