รวบรวมข้ามไปบน OSX?


142

ฉันพยายามคอมไพล์แอพ go บน OSX เพื่อสร้างไบนารีสำหรับ windows และ linux ฉันได้อ่านทุกสิ่งที่ฉันสามารถหาได้ในอินเทอร์เน็ต ตัวอย่างที่ใกล้เคียงที่สุดที่ฉันพบได้รับการเผยแพร่ใน (นอกเหนือจากการสนทนาที่ยังไม่เสร็จจำนวนมากในรายชื่อผู้รับจดหมาย go-nuts):

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

แต่มันไม่สามารถใช้งานได้กับการติดตั้งของฉัน ฉันไปแล้ว 1.0.2 เนื่องจาก 1.0.2 ค่อนข้างล่าสุดฉันคิดว่าตัวอย่างด้านบนทั้งหมดไม่สามารถใช้ได้กับเวอร์ชันนี้

พยายามทำ./make.bash --no-cleanด้วย ENV vars ที่ 386 / windows มันสร้างไป แต่มันสร้างไปสำหรับการติดตั้งของฉันซึ่งเป็นdarwin/amd64และไม่สนใจสิ่งที่ตั้งอยู่ใน ENV ที่คาดว่าจะสร้างคอมไพเลอร์ที่แตกต่างกัน

มีคำแนะนำใด ๆ ว่าจะทำได้อย่างไร (ถ้าทำได้)


ขนานกับสิ่งนี้ฉันได้ถามคำถามเดียวกันในรายชื่อผู้รับจดหมาย golang-nuts และด้วยความช่วยเหลือและความอดทนของผู้คนที่มีสูตรขั้นสุดท้ายได้ปรุง ... นี่คือกระทู้สนทนา: groups.google.com/forum/?fromgroups=# ! topic / golang-nuts / ... มีหลายขั้นตอนและข้อสรุปฉันผิดทาง แต่ตอนนี้สูตรดูเหมือนง่ายมาก - 3 ขั้นตอนและการทำซ้ำบางอย่าง
ljgww

ตอนนี้ฉันกำลังจะไปสรุปฉันไปทำไม vars ENV ไม่เรียกการรวบรวมที่ถูกต้อง - อาจเป็นเพราะฉันsudo(อาจจะได้รับ unix ENV ที่แตกต่างกันเมื่อ sudo-ing ดังนั้น GOOS & GOARCH จะไม่สามารถใช้ได้ถ้าพวกเขาไม่ได้ทำ แบบอินไลน์)
ljgww

เรื่อง: jdi - ฉันแค่พยายามรวบรวม "mockup" แอพของฉันเพื่อชนะ / lin ไบนารีบน mac แต่เพื่อทำฉันต้องสร้างตัวเองสำหรับการรวมกันของแพลตฟอร์ม / โปรเซสเซอร์ (ยังไม่สามารถตอบคำถามของฉันเองในขณะนี้ - มีชื่อเสียงไม่เพียงพอที่นี่)
ljgww

1
คุณพิมพ์สิ่งที่พูดในตัวอย่างหรือไม่ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash- หากคุณพยายามที่จะแยกมันมากกว่าหนึ่งบรรทัดแล้วตัวแปรสภาพแวดล้อมจะไม่ถูกส่งออกซึ่งเหมาะกับอาการ
Nick Craig-Wood

ตรวจสอบให้แน่ใจว่าคุณไม่สับสนสถาปัตยกรรมโฮสต์และเป้าหมาย คุณควรเห็นผลลัพธ์นี้: "# Building compilers และเครื่องมือ bootstrap Go สำหรับโฮสต์, darwin / amd64" "# การสร้างแพ็คเกจและคำสั่งสำหรับโฮสต์, ดาร์วิน / amd64" "# การสร้างแพ็คเกจและคำสั่งสำหรับ windows / 386"
แซม

คำตอบ:


157

ด้วย Go 1.5 พวกเขาดูเหมือนจะปรับปรุงกระบวนการรวบรวมข้ามซึ่งหมายความว่ามันถูกสร้างขึ้นในขณะนี้ ไม่จำเป็นต้อง - ./make.bashหรือbrew- กระบวนการอธิบายไว้ที่นี่แต่สำหรับ TLDR-ers (อย่างฉัน) ออกไปที่นั่น: คุณเพิ่งตั้งค่าGOOSและGOARCHตัวแปรสภาพแวดล้อมและเรียกใช้งานบิลด์

สำหรับผู้ลอกเลียนแบบคนอื่น ๆ ที่เหมือนกัน (เช่นฉัน) ออกไปทำสิ่งนี้ถ้าคุณอยู่ในระบบ * ระวัง:

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

คุณได้เรียนรู้envเคล็ดลับซึ่งช่วยให้คุณตั้งค่าตัวแปรสภาพแวดล้อมสำหรับคำสั่งนั้นเท่านั้นโดยไม่เสียค่าใช้จ่าย


4
envคำสั่งวิ่งเดียวที่โทรในสภาพแวดล้อมที่กำหนดเองและ 'รีเซ็ต' มันหลังจากที่มันจะทำ ตัวอย่างเช่นเรียกใช้export GOOS=windowsแล้วคำสั่งที่มีหรือไม่มีenvและecho $GOOSหลังจากนั้น ด้วยenvGOOS ก็ไม่ได้เปลี่ยน
leondepeon

3
เดียวกันเป็นจริง (อย่างน้อยในทุบตี) envโดย ฉันวิ่งexport GOOS=windowsแล้วนั้นGOOS=linux bash -c 'echo "GOOS: $GOOS"' echo "GOOS: $GOOS"ไม่envให้เข้ากันได้มากขึ้นด้วยภาษาอื่น ๆ หรือเปลือกกับแพลตฟอร์มอื่น ๆ ? ถ้าไม่ดูเหมือนไม่จำเป็น
davidchambers

2
@davidchambers ใน BASH พวกเขาเทียบเท่ากัน ขณะที่ในบางอื่น ๆ เชลล์เช่นเปลือกปลาก็ไม่ได้สนับสนุนเพื่อให้คุณมีการใช้งานFOO=bar cmd env FOO=bar cmdดังนั้นฉันคิดว่าข้อดีที่สุดที่จะใช้env FOO=bar cmdคือความเข้ากันได้
PickBoy

1
คำตอบที่น่าเหลือเชื่อที่นี่ คุณแก้ปัญหาของฉันสอนเคล็ดลับใหม่และทำให้ฉันหัวเราะกับตัวเอง
T Blank

1
คำตอบที่ดีขอบคุณ! เพื่อที่จะรวบรวมเพื่อใช้กับ heroku (intel x86) ฉันปรับเปลี่ยนบรรทัดเล็กน้อยenv GOOS=linux GOARCH=386 go build -v github.com/path/to/your/appและทำงานเหมือนแชมป์
Ira Herman

136

ขอบคุณที่ใจดีและช่วยเหลือผู้ป่วยจาก golang-nuts สูตรต่อไปนี้:

1) ต้องรวบรวมคอมไพเลอร์ Go สำหรับแพลตฟอร์มและสถาปัตยกรรมเป้าหมายที่แตกต่างกัน สิ่งนี้ทำจากโฟลเดอร์ src ในระหว่างการติดตั้ง ในกรณีการติดตั้งของฉันไปตั้งอยู่ใน/usr/local/goการรวบรวมคอมไพเลอร์ที่คุณต้องออกmakeยูทิลิตี้ ก่อนที่จะทำเช่นนี้คุณจำเป็นต้องรู้ข้อแม้บางอย่าง

มีปัญหาเกี่ยวกับไลบรารี CGO เมื่อทำการคอมไพล์ข้ามดังนั้นจำเป็นต้องปิดการใช้งานไลบรารี CGO

การคอมไพล์ทำได้โดยการเปลี่ยนตำแหน่งเป็นแหล่ง dir เนื่องจากการคอมไพล์จะต้องทำในโฟลเดอร์นั้น

cd /usr/local/go/src

จากนั้นรวบรวมคอมไพเลอร์ Go:

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

คุณต้องทำซ้ำขั้นตอนนี้สำหรับแต่ละระบบปฏิบัติการและสถาปัตยกรรมที่คุณต้องการคอมไพล์โดยการเปลี่ยนพารามิเตอร์ GOOS และ GOARCH

หากคุณกำลังทำงานในโหมดผู้ใช้เช่นเดียวกับฉันจำเป็นต้องใช้ sudo เพราะคอมไพเลอร์ Go อยู่ในระบบ dir มิฉะนั้นคุณจะต้องเข้าสู่ระบบในฐานะผู้ใช้ขั้นสูง บน Mac คุณอาจต้องเปิดใช้งาน / กำหนดค่าการเข้าถึง SU (โดยค่าเริ่มต้นจะไม่พร้อมใช้งาน) แต่ถ้าคุณมีการจัดการเพื่อติดตั้ง Go คุณอาจมีสิทธิ์เข้าถึงรูตอยู่แล้ว

2) เมื่อคุณสร้างคอมไพเลอร์ไขว้ทั้งหมดคุณสามารถข้ามคอมไพล์แอปพลิเคชันของคุณได้อย่างมีความสุขโดยใช้การตั้งค่าต่อไปนี้:

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

เปลี่ยน GOOS และ GOARCH เป็นเป้าหมายที่คุณต้องการสร้าง

หากคุณประสบปัญหากับ CGO ให้รวม CGO_ENABLED = 0 ในบรรทัดคำสั่ง นอกจากนี้โปรดทราบว่าไบนารีสำหรับ linux และ mac ไม่มีส่วนขยายดังนั้นคุณอาจเพิ่มส่วนขยายเพื่อให้มีไฟล์ที่แตกต่างกัน -o switch สั่งให้ทำไฟล์เอาต์พุตคล้ายกับคอมไพเลอร์เก่าสำหรับ c / c ++ ดังนั้น appname.linux ที่ใช้แล้วข้างต้นสามารถเป็นนามสกุลอื่น ๆ ได้


สิ่งที่ทำให้ฉันสับสนในตอนแรกคือในส่วนแรกของการรวบรวมทำให้พูดว่า: # Building compilers and Go bootstrap tool for host, darwin/amd64แต่หลังจากนั้นมันก็จบลงที่: --- Installed Go for windows/386 in /usr/local/go Installed commands in /usr/local/go/binดังนั้นเราจะต้องสังเกตจุดสิ้นสุดแทนที่จะเริ่มต้นรวบรวมคอมไพเลอร์
ljgww

ทุกอย่างเริ่มต้นโดยพยายามทำ: $ GOARCH=386 GOOS=linux go build app.goและได้รับข้อผิดพลาด # 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
แพ็คเกจ Go ใน Homebrew มีตัวเลือก "--cross-compile-all" ซึ่งจะสร้างคอมไพเลอร์ข้ามทั้งหมดโดยอัตโนมัติ
nimrodm

8
เกร็ดน่ารู้ @nimrodm! เพื่อคอมไพล์การติดตั้ง Go ของคุณอีกครั้งคุณต้องรันbrew reinstall go --cross-compile-all
linqu

1
@ljgww 'sudo' ไม่มีการกำหนดค่า ENV ฉันลงเอยด้วยการใช้ chown ใน / usr / local / go / pkg / linux_amd64 /
Nuno Silva

63

หากคุณใช้Homebrewบน OS X แสดงว่าคุณมีวิธีแก้ไขที่ง่ายกว่า:

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

หรือ..

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

ใช้reinstallถ้าคุณได้goติดตั้งแล้ว


3
สังเกตว่าสวิตช์ที่ได้รับการปรับปรุงคือ: - ข้ามคอมไพล์ - ทั้งหมดสร้าง cross-compilers และสนับสนุน runtime สำหรับแพลตฟอร์มที่รองรับทั้งหมด - ข้ามคอมไพล์คอมไพล์ - ทั่วไปสร้าง cross-compilers และสนับสนุน runtime สำหรับดาร์วินลินุกซ์และ windows
Chip Tol

3
--cross-compile-allได้แล้ว--with-cc-all
gianebao

@ sheeks06 - แก้ไขแล้ว ขอบคุณ!
docwhat

1
ธงเหล่านี้ไม่มีอยู่ในสิ่งที่ฉันสามารถบอกได้ ตัวเลือกที่เกี่ยวข้องเท่านั้นที่ฉันเห็นคือ - โดยไม่ต้อง - cgo :(
rdegges

5
ตั้งแต่ Go 1.5 ไม่มีคอมไพเลอร์ข้ามแยกกันคุณใช้ธงตอนนี้เท่านั้น tip.golang.org/doc/go1.5#compiler_and_tools
chuckus

24

คุณสามารถทำสิ่งนี้ได้อย่างง่ายดายโดยใช้ Docker ดังนั้นจึงไม่จำเป็นต้องใช้ libs เพิ่มเติม เพียงรันคำสั่งนี้:

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
'

คุณสามารถค้นหารายละเอียดเพิ่มเติมในโพสต์นี้: https://medium.com/iron-io-blog/how-to-cross-compile-go-programs-using-docker-beaa102a316d


1
ทำไมทุกคนต้องการติดตั้ง Docker ทำเช่นนี้เมื่อพวกเขาสามารถทำวนรอบเชลล์env GOOS=x GOARCH=y go install something/...และจบลงด้วยไบนารีที่เหมาะสมภายใต้$GOPATH/bin/$GOOS_$GOARCH? และ BTW, Go รองรับมากกว่าสาม OS ที่คุณลิสต์ทำไมไม่รัก BSD ล่ะ?
Dave C

8
คุณจะไม่ติดตั้ง Docker เพื่อทำสิ่งนี้ แต่ถ้าคุณมีมันจะง่ายกว่าและสะอาดกว่าทางเลือกอื่น
Travis Reeder

7

กระบวนการสร้างไฟล์ที่รันได้สำหรับหลาย ๆ แพลตฟอร์มนั้นค่อนข้างน่าเบื่อดังนั้นฉันแนะนำให้ใช้สคริปต์:

#!/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

ฉันตรวจสอบสคริปต์นี้ใน OSX เท่านั้น

สรุปสาระสำคัญ - go-executable-build.sh


ว่าสิ่งที่ฉันกำลังมองหา ... ฉันได้ dockerized มัน :) gist.github.com/marcellodesales/ ......
Marcello de Sales

6

สำหรับผู้ที่ต้องการเปิดใช้งานCGOและคอมไพล์ข้ามจากหน้าต่างการกำหนดเป้าหมาย OSX

ฉันต้องการCGO ที่เปิดใช้งานในขณะที่คอมไพล์สำหรับ windows จาก mac ของฉันตั้งแต่ฉันได้นำเข้าhttps://github.com/mattn/go-sqlite3และมันต้องการมัน รวบรวมตามคำตอบอื่น ๆ ให้ฉันและข้อผิดพลาด:

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

หากคุณเป็นเหมือนฉันและคุณต้องรวบรวมกับ CGO นี่คือสิ่งที่ฉันทำ:

1. เราจะข้ามการคอมไพล์สำหรับ windows ด้วย CGO ที่ขึ้นกับไลบรารี ก่อนอื่นเราต้องติดตั้ง cross compiler เช่นmingw-w64

brew install mingw-w64

นี่อาจจะติดตั้งที่นี่ /usr/local/opt/mingw-w64/bin/นี้อาจจะติดตั้งได้ที่นี่

2. เพียงแค่คำตอบอื่น ๆ เราต้องเพิ่ม windows arch ของเราในเครื่องมือคอมไพเลอร์ go ของเราทันที การคอมไพเลอร์คอมไพเลอร์ต้องการคอมไพเลอร์ (ประโยคแปลก) คอมไพเลอร์ go คอมไพเลอร์ต้องการคอมไพเลอร์ที่สร้างไว้ล่วงหน้าแยกต่างหาก เราสามารถดาวน์โหลดไบนารีที่สร้างไว้ล่วงหน้าหรือสร้างจากแหล่งที่มาในโฟลเดอร์เช่น: ~/Documents/go ตอนนี้เราสามารถปรับปรุง Go compiler ของเราตามคำตอบสูงสุด แต่คราวนี้ด้วยCGO_ENABLED=1และคอมไพเลอร์ prebuilt แยกต่างหากของเราGOROOT_BOOTSTRAP(Pooya เป็นชื่อผู้ใช้ของฉัน):

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. ตอนนี้ในขณะที่รวบรวมรหัส Go ของเราใช้mingwเพื่อรวบรวมหน้าต่าง go file target ของเราที่เปิดใช้งาน CGO:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.