Kompilasi silang Pergi di OSX?

142

Saya mencoba mengkompilasi lintas aplikasi go di OSX untuk membangun binari untuk windows dan linux. Saya telah membaca semua yang dapat saya temukan di internet. Contoh terdekat yang saya temukan telah dipublikasikan di (terlepas dari banyak diskusi yang belum selesai di milis go-nuts):

http://solovyov.net/en/2012/03/09/cross-compiling-go/

namun itu tidak berfungsi pada instalasi saya. Saya harus pergi 1.0.2. Karena 1.0.2 baru-baru ini terlihat bagi saya bahwa semua contoh di atas tidak berlaku untuk versi ini.

Mencoba melakukan ./make.bash --no-cleandengan vars ENV diatur ke 386 / windows, ia membangun pergi, tetapi itu membangun pergi untuk instalasi saya yang darwin/amd64dan sepenuhnya mengabaikan apa yang diatur dalam ENV yang seharusnya membangun kompiler yang berbeda.

Adakah yang menyarankan bagaimana hal itu dapat dilakukan (jika dapat dilakukan sama sekali)?

ljgww
sumber
paralel dengan ini saya telah mengajukan pertanyaan yang sama pada milis golang-kacang, dan dengan bantuan dan kesabaran orang-orang di sana resep akhir dimasak ... ini adalah utas diskusi: groups.google.com/forum/?fromgroups=# ! topic / golang-nuts / ... ada beberapa langkah dan kesimpulan, saya salah jalan, tapi sekarang resepnya tampak cukup sederhana - 3 langkah dan beberapa iterasi.
ljgww
sekarang saya akan rekap, saya mengembara mengapa ENV vars tidak memicu kompilasi yang benar - mungkin karena saya lakukan sudo(kemungkinan saya akan mendapatkan ENV unix yang berbeda ketika sudo-ing sehingga GOOS & GOARCH tidak akan tersedia jika tidak dilakukan inline)
ljgww
re: jdi - Saya baru saja mencoba untuk mengkompilasi app go "mockup" saya untuk memenangkan / membuat binari di mac, tetapi, untuk melakukannya saya harus membuat build sendiri untuk setiap kombinasi platform / prosesor. (belum dapat menjawab pertanyaan saya sendiri - belum memiliki reputasi yang cukup di sini)
ljgww
1
Apakah Anda mengetik persis apa yang dikatakan dalam contoh? CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash- jika Anda mencoba untuk membaginya di lebih dari satu baris maka variabel lingkungan tidak akan diekspor yang sesuai dengan gejala
Nick Craig-Wood
Pastikan Anda tidak membingungkan arsitektur host dan target. Anda akan melihat output ini: "# Membangun kompiler dan Go bootstrap tool untuk host, darwin / amd64." "# Membangun paket dan perintah untuk host, darwin / amd64." "# Paket bangunan dan perintah untuk windows / 386."
Sam

Jawaban:

157

Dengan Go 1.5 mereka tampaknya telah meningkatkan proses kompilasi silang, yang berarti sudah dibangun sekarang. Tidak perlu ./make.bashatau tidak brew. Proses ini dijelaskan di sini tetapi untuk TLDR-ers (seperti saya) di luar sana: Anda hanya mengatur GOOSdan GOARCHvariabel lingkungan dan menjalankan go membangun.

Untuk copy paste yang lebih malas (seperti saya) di luar sana, lakukan sesuatu seperti ini jika Anda menggunakan sistem * nix:

env GOOS=linux GOARCH=arm go build -v github.com/path/to/your/app

Anda bahkan mempelajari envtriknya, yang memungkinkan Anda mengatur variabel lingkungan hanya untuk perintah itu, sepenuhnya gratis.

Leondepeon
sumber
4
The envperintah berjalan hanya itu panggilan di lingkungan adat dan 'me-reset' setelah hal itu dilakukan. Misalnya dijalankan export GOOS=windows, maka perintah dengan atau tanpa envdan echo $GOOSsesudahnya. Dengan envGOOS tidak berubah.
leondepeon
3
hal yang sama juga berlaku (setidaknya di Bash) tanpa env. Aku berlari export GOOS=windowssaat GOOS=linux bash -c 'echo "GOOS: $GOOS"'itu echo "GOOS: $GOOS". Apakah envmemberikan kompatibilitas yang lebih besar dengan dialek shell lain atau dengan platform lain? Jika tidak tampaknya berlebihan di sini.
davidchambers
2
@davidchambers Di BASH mereka setara. Sementara di beberapa Shell lain, mis. Shell IKAN, tidak mendukung FOO=bar cmd, jadi Anda harus menggunakannya env FOO=bar cmd. Jadi saya pikir keuntungan terbesar untuk digunakan env FOO=bar cmdadalah kompatibilitas.
PickBoy
1
Jawaban yang luar biasa di sini. Anda memecahkan masalah saya, mengajari saya trik baru, dan membuat saya tertawa sendiri.
T Blank
1
Jawaban yang bagus, terima kasih! Untuk mengkompilasi untuk digunakan pada heroku (intel x86) saya sedikit mengubah garis env GOOS=linux GOARCH=386 go build -v github.com/path/to/your/appdan bekerja seperti juara
Ira Herman
136

Berkat bantuan yang baik dan sabar dari kacang golang, resepnya adalah sebagai berikut:

1) Kita perlu mengkompilasi Go compiler untuk berbagai platform target dan arsitektur. Ini dilakukan dari folder src pada instalasi go. Dalam kasus saya, instalasi Go terletak di dalam /usr/local/gosehingga untuk mengkompilasi kompiler Anda perlu mengeluarkan makeutilitas. Sebelum melakukan ini, Anda perlu tahu beberapa peringatan.

Ada masalah tentang perpustakaan CGO saat kompilasi silang sehingga perlu untuk menonaktifkan perpustakaan CGO.

Kompilasi dilakukan dengan mengubah lokasi ke sumber dir, karena kompilasi harus dilakukan dalam folder itu

cd /usr/local/go/src

kemudian kompilasi kompilator Go:

sudo GOOS=windows GOARCH=386 CGO_ENABLED=0 ./make.bash --no-clean

Anda perlu mengulangi langkah ini untuk setiap OS dan Arsitektur yang ingin Anda lintas kompilasi dengan mengubah parameter GOOS dan GOARCH.

Jika Anda bekerja dalam mode pengguna seperti yang saya lakukan, sudo diperlukan karena Go compiler ada di dir sistem. Kalau tidak, Anda harus masuk sebagai pengguna super. Pada Mac Anda mungkin perlu mengaktifkan / mengkonfigurasi akses SU (ini tidak tersedia secara default), tetapi jika Anda telah berhasil menginstal Go, Anda mungkin sudah memiliki akses root.

2) Setelah Anda membangun semua kompiler silang, Anda dapat dengan senang hati mengkompilasi aplikasi Anda dengan menggunakan pengaturan berikut ini misalnya:

GOOS=windows GOARCH=386 go build -o appname.exe appname.go

GOOS=linux GOARCH=386 CGO_ENABLED=0 go build -o appname.linux appname.go

Ubah GOOS dan GOARCH ke target yang ingin Anda buat.

Jika Anda mengalami masalah dengan CGO, sertakan CGO_ENABLED = 0 di baris perintah. Juga perhatikan bahwa binari untuk linux dan mac tidak memiliki ekstensi sehingga Anda dapat menambahkan ekstensi demi memiliki file yang berbeda. -o switch menginstruksikan Go untuk membuat file output yang mirip dengan kompiler lama untuk c / c ++ sehingga appname.linux yang digunakan di atas dapat berupa ekstensi lainnya.

ljgww
sumber
Apa yang awalnya membingungkan saya adalah bahwa pada bagian pertama kompilasi make mengatakan: # Building compilers and Go bootstrap tool for host, darwin/amd64tetapi kemudian benar-benar berakhir sebagai: --- Installed Go for windows/386 in /usr/local/go Installed commands in /usr/local/go/binjadi orang harus mengamati akhir daripada mulai mengkompilasi kompiler.
ljgww
semuanya dimulai dengan mencoba melakukan: $ GOARCH=386 GOOS=linux go build app.godan mendapatkan kesalahan # runtime /usr/local/go/src/pkg/runtime/extern.go:137: undefined: theGoos /usr/local/go/src/pkg/runtime/extern.go:137: cannot use theGoos as type string in const initializer
ljgww
30
Paket Go di Homebrew memiliki opsi "--cross-compile-all" yang secara otomatis akan membangun semua kompiler silang.
nimrodm
8
tip bagus @nimrodm! untuk mengkompilasi ulang instalasi go Anda, Anda perlu menjalankanbrew reinstall go --cross-compile-all
linqu
1
@ljgww 'sudo' tidak memiliki ENV yang dikonfigurasi. Saya akhirnya menggunakan chown di / usr / local / go / pkg / linux_amd64 /
Nuno Silva
63

Jika Anda menggunakan Homebrew di OS X, maka Anda memiliki solusi yang lebih sederhana:

$ brew install go --with-cc-common # Linux, Darwin, and Windows

atau..

$ brew install go --with-cc-all # All the cross-compilers

Gunakan reinstalljika Anda sudah gomenginstal.

docwhat
sumber
3
Memperhatikan sakelar yang diperbarui adalah: --cross-compile-all Membangun cross-compiler dan dukungan runtime untuk semua platform yang didukung --cross-compile-common Membangun cross-compiler dan dukungan runtime untuk darwin, linux dan windows
Chip Tol
3
--cross-compile-allsekarang--with-cc-all
gianebao
@ sheeks06 - diperbaiki. Terima kasih!
docwhat
1
Bendera ini tidak ada lagi dari apa yang bisa saya katakan. Satu-satunya pilihan yang relevan yang saya lihat adalah
--without
5
Sejak Go 1.5, tidak ada kompiler silang yang terpisah, Anda hanya menggunakan flag sekarang tip.golang.org/doc/go1.5#compiler_and_tools
chuckus
24

Anda dapat melakukan ini dengan cukup mudah menggunakan Docker, jadi tidak ada lib tambahan yang diperlukan. Jalankan saja perintah ini:

docker run --rm -it -v "$GOPATH":/go -w /go/src/github.com/iron-io/ironcli golang:1.4.2-cross sh -c '
for GOOS in darwin linux windows; do
  for GOARCH in 386 amd64; do
    echo "Building $GOOS-$GOARCH"
    export GOOS=$GOOS
    export GOARCH=$GOARCH
    go build -o bin/ironcli-$GOOS-$GOARCH
  done
done
'

Anda dapat menemukan rincian lebih lanjut di pos ini: https://medium.com/iron-io-blog/how-to-cross-compile-go-programs-using-docker-beaa102a316d

Travis Reeder
sumber
1
Mengapa ada orang yang ingin menginstal Docker untuk melakukan ini ketika mereka hanya bisa melakukan perulangan shell env GOOS=x GOARCH=y go install something/...dan berakhir dengan biner yang sesuai di bawah $GOPATH/bin/$GOOS_$GOARCH?? Dan BTW, Go mendukung lebih dari tiga OS yang Anda daftarkan, mengapa tidak ada cinta untuk BSD?
Dave C
8
Anda tidak akan menginstal Docker hanya untuk melakukan ini, tetapi jika Anda memilikinya, ini lebih mudah dan lebih bersih daripada alternatifnya.
Travis Reeder
7

Proses membuat executable untuk banyak platform bisa sedikit membosankan, jadi saya sarankan untuk menggunakan skrip:

#!/usr/bin/env bash

package=$1
if [[ -z "$package" ]]; then
  echo "usage: $0 <package-name>"
  exit 1
fi
package_name=$package

#the full list of the platforms: https://golang.org/doc/install/source#environment
platforms=(
"darwin/386"
"dragonfly/amd64"
"freebsd/386"
"freebsd/amd64"
"freebsd/arm"
"linux/386"
"linux/amd64"
"linux/arm"
"linux/arm64"
"netbsd/386"
"netbsd/amd64"
"netbsd/arm"
"openbsd/386"
"openbsd/amd64"
"openbsd/arm"
"plan9/386"
"plan9/amd64"
"solaris/amd64"
"windows/amd64"
"windows/386" )

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}
    output_name=$package_name'-'$GOOS'-'$GOARCH
    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
    if [ $? -ne 0 ]; then
        echo 'An error has occurred! Aborting the script execution...'
        exit 1
    fi
done

Saya memeriksa skrip ini hanya pada OSX

inti - go-executable-build.sh

Dima Kozhevin
sumber
Persis seperti apa yang saya cari ... Saya telah mer-dock-nya :) gist.github.com/marcellodesales/…
Marcello de Sales
6

untuk orang yang membutuhkan CGO diaktifkan dan kompilasi silang dari jendela penargetan OSX

Saya membutuhkan CGO diaktifkan saat mengkompilasi untuk windows dari mac saya karena saya telah mengimpor https://github.com/mattn/go-sqlite3 dan diperlukan. Kompilasi menurut jawaban lain memberi saya kesalahan:

/usr/local/go/src/runtime/cgo/gcc_windows_amd64.c:8:10: fatal error: 'windows.h' file not found

Jika Anda seperti saya dan Anda harus melakukan kompilasi dengan CGO. Inilah yang saya lakukan:

1.Kita akan melintasi kompilasi untuk windows dengan pustaka CGO dependen. Pertama kita perlu menginstal kompilator silang sepertimingw-w64

brew install mingw-w64

Ini mungkin akan menginstalnya di sini /usr/local/opt/mingw-w64/bin/.

2.Just seperti jawaban lain, pertama kita perlu menambahkan lengkungan windows kita ke toolchain compiler kita sekarang. Mengkompilasi kompiler memerlukan kompiler (kalimat aneh) kompilasi go compiler membutuhkan kompilator pre-built terpisah. Kami dapat mengunduh binary prebuilt atau build from source dalam folder mis: ~/Documents/go sekarang kami dapat meningkatkan kompiler Go kami, sesuai dengan jawaban teratas tetapi kali ini dengan CGO_ENABLED=1dan kompilator prebuilt kami yang terpisah GOROOT_BOOTSTRAP(Pooya adalah nama pengguna saya):

cd /usr/local/go/src
sudo GOOS=windows GOARCH=amd64 CGO_ENABLED=1 GOROOT_BOOTSTRAP=/Users/Pooya/Documents/go ./make.bash --no-clean
sudo GOOS=windows GOARCH=386 CGO_ENABLED=1 GOROOT_BOOTSTRAP=/Users/Pooya/Documents/go ./make.bash --no-clean

3.Sekarang saat mengkompilasi penggunaan kode Go kami mingwuntuk mengkompilasi windows penargetan file go kami dengan CGO diaktifkan:

GOOS="windows" GOARCH="386" CGO_ENABLED="1" CC="/usr/local/opt/mingw-w64/bin/i686-w64-mingw32-gcc" go build hello.go
GOOS="windows" GOARCH="amd64" CGO_ENABLED="1" CC="/usr/local/opt/mingw-w64/bin/x86_64-w64-mingw32-gcc" go build hello.go
Pouya Sanooei
sumber