Kompilacja krzyżowa Idź na OSX?

142

Próbuję skompilować krzyżowo aplikację go na OSX, aby zbudować pliki binarne dla systemu Windows i Linux. Przeczytałem wszystko, co mogłem znaleźć w sieci. Najbliższy przykład, jaki znalazłem, został opublikowany (poza wieloma niedokończonymi dyskusjami na liście mailingowej go-nuts):

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

jednak nie działa na mojej instalacji. Mam przejść 1.0.2. Ponieważ wersja 1.0.2 jest całkiem nowa, wydaje mi się, że wszystkie powyższe przykłady nie mają zastosowania do tej wersji.

Próbowałem zrobić ./make.bash --no-cleanze zmiennymi ENV ustawionymi na 386 / windows, kompiluje się, jednak kompiluje się dla mojej instalacji, która jest darwin/amd64i całkowicie ignoruje to, co jest ustawione w ENV, które zakłada budowanie innego kompilatora.

Jakieś rady, jak to zrobić (jeśli w ogóle można to zrobić)?

ljgww
źródło
równolegle do tego zadałem to samo pytanie na liście mailingowej golang-nuts iz życzliwą pomocą i cierpliwością tamtejszych ludzi ugotowano ostateczny przepis ... oto wątek dyskusyjny: groups.google.com/forum/?fromgroups=# ! topic / golang-nuts /… było kilka kroków i wniosków, pomyliłem się po drodze, ale teraz przepis wydaje się całkiem prosty - 3 kroki i kilka iteracji.
ljgww
teraz, gdy przeglądam podsumowanie, zastanawiam się, dlaczego vars ENV nie wyzwolił prawidłowej kompilacji - może dlatego, że tak sudo(prawdopodobnie dostałbym inny unix ENV podczas sudo, więc GOOS i GOARCH nie byłyby dostępne, gdyby nie zostały wykonane inline)
ljgww
re: jdi - Po prostu próbowałem skompilować moją "makietę" aplikację go do binarnych plików Win / lin na Macu, ale aby to zrobić, musiałem skompilować go dla każdej kombinacji platformy / procesora. (nie mogę jeszcze odpowiedzieć na własne pytanie - nie mam tu wystarczającej reputacji)
ljgww
1
Czy wpisałeś dokładnie to, co napisano w przykładzie? CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash- jeśli próbowałeś podzielić go na więcej niż jedną linię, zmienna środowiskowa nie zostanie wyeksportowana, która pasuje do objawów
Nick Craig-Wood
Upewnij się, że nie mylisz architektury hosta i celu. Powinieneś zobaczyć następujące dane wyjściowe: „# Budowanie kompilatorów i narzędzie rozruchowe Go dla hosta, darwin / amd64”. „# Budowanie pakietów i poleceń dla hosta, darwin / amd64”. „# Budowanie pakietów i poleceń dla systemu Windows / 386”.
Sam,

Odpowiedzi:

157

Wydaje się, że dzięki Go 1.5 poprawili proces kompilacji krzyżowej, co oznacza, że ​​jest teraz wbudowany. Nie jest wymagane ./make.bashani brew-ing ani -ing. Proces ten opisany jest tutaj ale dla TLDR-ers (jak ja) tam: wystarczy ustawić GOOSi GOARCHzmienne środowiskowe i uruchomić odchodzenie budować.

Dla jeszcze bardziej leniwych kopiarek (takich jak ja) zrób coś takiego, jeśli korzystasz z systemu * nix:

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

Nauczyłeś się nawet envsztuczki, która pozwala ustawić zmienne środowiskowe tylko dla tego polecenia, całkowicie bezpłatnie.

leondepeon
źródło
4
W envbiegnie tylko że polecenie wywołania w środowisku niestandardowym i resetuje „” to po to jest zrobione. Na przykład run export GOOS=windows, a następnie polecenie z lub bez, enva echo $GOOSnastępnie. Z envGOOS nie został zmieniony.
leondepeon
3
to samo jest prawdą (przynajmniej w Bash) bez env. Pobiegłem export GOOS=windowspo czym GOOS=linux bash -c 'echo "GOOS: $GOOS"'następnie echo "GOOS: $GOOS". Czy envzapewnia większą kompatybilność z innymi dialektami powłoki lub z innymi platformami? Jeśli nie, wydaje się to tutaj zbyteczne.
davidchambers
2
@davidchambers W BASH są one równoważne. Podczas gdy w jakiejś innej powłoce, np. Powłoce FISH, nie obsługuje FOO=bar cmd, więc musisz użyć env FOO=bar cmd. Dlatego myślę, że największą zaletą env FOO=bar cmdjest kompatybilność.
PickBoy
1
Niesamowita odpowiedź tutaj. Rozwiązałeś mój problem, nauczyłeś mnie nowej sztuczki i sprawiłeś, że chichotałem do siebie.
T Blank
1
Świetna odpowiedź, dziękuję! Aby skompilować do użytku na heroku (intel x86) nieznacznie zmodyfikowałem linię na env GOOS=linux GOARCH=386 go build -v github.com/path/to/your/appi działa jak mistrz
Ira Herman
136

Dzięki życzliwej i cierpliwej pomocy golang-orzeszków receptura jest następująca:

1) Należy skompilować kompilator Go dla różnych platform docelowych i architektur. Odbywa się to z folderu src podczas instalacji go. W moim przypadku instalacja Go znajduje się w, /usr/local/gowięc aby skompilować kompilator, musisz wydać makenarzędzie. Zanim to zrobisz, musisz poznać kilka zastrzeżeń.

Występuje problem dotyczący biblioteki CGO podczas kompilacji krzyżowej, dlatego konieczne jest wyłączenie biblioteki CGO.

Kompilacja odbywa się poprzez zmianę lokalizacji na katalog źródłowy, ponieważ kompilacja musi być wykonana w tym folderze

cd /usr/local/go/src

następnie skompiluj kompilator Go:

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

Musisz powtórzyć ten krok dla każdego systemu operacyjnego i architektury, które chcesz skompilować krzyżowo, zmieniając parametry GOOS i GOARCH.

Jeśli pracujesz w trybie użytkownika tak jak ja, sudo jest potrzebne, ponieważ kompilator Go znajduje się w katalogu systemowym. W przeciwnym razie musisz być zalogowany jako superużytkownik. Na Macu może być konieczne włączenie / skonfigurowanie dostępu SU (domyślnie nie jest dostępny), ale jeśli udało ci się zainstalować Go, prawdopodobnie masz już uprawnienia roota.

2) Po utworzeniu wszystkich kompilatorów krzyżowych możesz z radością skompilować swoją aplikację przy użyciu następujących ustawień, na przykład:

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

Zmień GOOS i GOARCH na cele, które chcesz zbudować.

Jeśli napotkasz problemy z CGO, umieść CGO_ENABLED = 0 w linii poleceń. Zauważ również, że pliki binarne dla Linuksa i Maca nie mają rozszerzenia, więc możesz dodać rozszerzenie, aby mieć różne pliki. -o przełącznik instruuje Go, aby plik wyjściowy był podobny do starych kompilatorów dla c / c ++, więc powyżej używanego appname.linux może być dowolnym innym rozszerzeniem.

ljgww
źródło
Początkowo zmyliło mnie to, że w pierwszej części kompilacji make mówi: # Building compilers and Go bootstrap tool for host, darwin/amd64ale później faktycznie kończy się jako: --- Installed Go for windows/386 in /usr/local/go Installed commands in /usr/local/go/bintak więc należy obserwować raczej zakończenie niż początek kompilacji kompilatora.
ljgww
wszystko zaczęło się od próby zrobienia: $ GOARCH=386 GOOS=linux go build app.goi otrzymania błędu # 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
Pakiet Go w Homebrew ma opcję "--cross-compile-all", która automatycznie zbuduje wszystkie kompilatory krzyżowe.
nimrodm
8
świetna wskazówka @nimrodm! aby ponownie skompilować instalację go, musisz uruchomićbrew reinstall go --cross-compile-all
linqu
1
@ljgww 'sudo' nie ma skonfigurowanego ENV. Skończyło się na używaniu chown na / usr / local / go / pkg / linux_amd64 /
Nuno Silva
63

Jeśli używasz Homebrew na OS X, masz prostsze rozwiązanie:

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

lub..

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

Użyj, reinstalljeśli już gozainstalowałeś.

docwhat
źródło
3
Zauważmy, że zaktualizowane przełączniki to: --cross-compile-all Zbuduj cross-kompilatory i wsparcie dla środowiska uruchomieniowego dla wszystkich obsługiwanych platform --cross-compile-common Zbuduj cross-kompilatory i obsługę runtime dla darwin, linux i windows
Chip Tol
3
--cross-compile-alljest teraz--with-cc-all
gianebao
@ sheeks06 - naprawiono. Dzięki!
docwhat
1
Z tego, co wiem, te flagi już nie istnieją. Jedyną odpowiednią opcją, którą widzę, jest --without-cgo :(
rdegges
5
Od wersji 1.5 nie ma oddzielnych kompilatorów krzyżowych, teraz używasz tylko flag tip.golang.org/doc/go1.5#compiler_and_tools
chuckus.
24

Możesz to zrobić dość łatwo za pomocą Dockera, więc nie są wymagane żadne dodatkowe biblioteki. Po prostu uruchom to polecenie:

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
'

Więcej szczegółów znajdziesz w tym poście: https://medium.com/iron-io-blog/how-to-cross-compile-go-programs-using-docker-beaa102a316d

Travis Reeder
źródło
1
Dlaczego ktoś miałby chcieć instalować Dockera, aby to zrobić, skoro mógłby po prostu wykonać pętlę powłoki env GOOS=x GOARCH=y go install something/...i skończyć z odpowiednimi plikami binarnymi pod $GOPATH/bin/$GOOS_$GOARCH?? A tak przy okazji, Go obsługuje więcej niż trzy systemy operacyjne, które wymieniasz, dlaczego nie kochasz BSD?
Dave C,
8
Nie instalowałbyś Dockera tylko po to, aby to zrobić, ale jeśli go masz, jest to łatwiejsze i czystsze niż alternatywy.
Travis Reeder,
7

Proces tworzenia plików wykonywalnych dla wielu platform może być trochę uciążliwy, dlatego sugeruję użycie skryptu:

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

Sprawdziłem ten skrypt tylko na OSX

istota - go-executable-build.sh

Dima Kozhevin
źródło
Dokładnie to, czego szukałem ... Dokeryzowałem to :) gist.github.com/marcellodesales/…
Marcello de Sales
6

dla osób, które potrzebują włączonego CGO i kompilacji krzyżowej z okien docelowych OSX

Potrzebowałem CGO włączonego podczas kompilacji dla Windows z mojego Maca, ponieważ zaimportowałem https://github.com/mattn/go-sqlite3 i potrzebowałem tego. Kompilacja według innych odpowiedzi dała mi błąd:

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

Jeśli jesteś podobny do mnie i musisz skompilować się z CGO. Oto co zrobiłem:

1. Zamierzamy skompilować krzyżowo dla Windows z biblioteką zależną od CGO. Najpierw musimy zainstalować kompilator krzyżowy, taki jakmingw-w64

brew install mingw-w64

To prawdopodobnie zainstaluje go tutaj /usr/local/opt/mingw-w64/bin/.

2. Podobnie jak w przypadku innych odpowiedzi, musimy najpierw dodać naszą archiwa Windows do naszego zestawu narzędzi kompilatora go. Kompilacja kompilatora wymaga kompilatora (dziwne zdanie) Kompilacja go wymaga oddzielnego, wstępnie zbudowanego kompilatora. Możemy pobrać wstępnie skompilowany plik binarny lub skompilować ze źródła w folderze, np .: ~/Documents/go teraz możemy ulepszyć nasz kompilator Go, zgodnie z najlepszą odpowiedzią, ale tym razem z CGO_ENABLED=1naszym oddzielnym wstępnie skompilowanym kompilatoremGOROOT_BOOTSTRAP (Pooya to moja nazwa użytkownika):

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. Teraz podczas kompilowania naszego kodu Go użyj mingwdo skompilowania naszego pliku go przeznaczonego dla okien z włączonym 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
Pouya Sanooei
źródło