Compilazione incrociata Vai su OSX?


142

Sto cercando di compilare in modo incrociato un'app go su OSX per creare binari per Windows e Linux. Ho letto tutto quello che ho potuto trovare in rete. L'esempio più vicino che ho trovato è stato pubblicato su (a parte molte discussioni non finite sulla mailing list go-nuts):

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

tuttavia non funziona sulla mia installazione. Sono andato 1.0.2. Poiché 1.0.2 è abbastanza recente, mi sembra che tutti gli esempi sopra riportati non si applichino a questa versione.

Ho provato a fare ./make.bash --no-cleancon ENV vars impostato su 386 / windows, build go go, tuttavia build va per la mia installazione che è darwin/amd64e ignora completamente ciò che è impostato in ENV che suppone di costruire un compilatore diverso.

Qualcuno consiglia come può essere fatto (se può essere fatto affatto)?


parallelamente a questo ho fatto la stessa domanda sulla mailing list golang-nut, e con il gentile aiuto e la pazienza delle persone c'è stata cucinata la ricetta finale ... questo è il thread di discussione: groups.google.com/forum/?fromgroups=# ! topic / golang-nuts / ... ci sono stati diversi passaggi e conclusioni, mi sono sbagliato sulla strada, ma ora la ricetta sembra piuttosto semplice - 3 passaggi e alcune iterazioni.
ljgww,

ora che sto ricapitolando, mi chiedo perché i Vars ENV non abbiano innescato la compilazione corretta - forse perché l'ho fatto sudo(probabilmente avrei ottenuto ENV unix diversi quando sudo-so in modo che GOOS e GOARCH non sarebbero disponibili se non fossero fatti inline)
ljgww

re: jdi - Stavo solo cercando di compilare la mia app go "mockup" per vincere binari / lin su mac, ma, per farlo, ho dovuto costruirlo da solo per ogni combinazione di piattaforma / processore. (non posso ancora rispondere alla mia domanda - non avendo abbastanza reputazione qui)
ljgww

1
Hai digitato esattamente ciò che diceva nell'esempio? CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash- se hai tentato di dividerlo su più di una riga, la variabile d'ambiente non verrà esportata che si adatta ai sintomi
Nick Craig-Wood,

Assicurarsi di non confondere l'architettura host e di destinazione. Dovresti vedere questo output: "# Compilatore di compilatori e strumento Go bootstrap per host, darwin / amd64." "# Creazione di pacchetti e comandi per host, darwin / amd64." "# Creazione di pacchetti e comandi per windows / 386."
Sam,

Risposte:


157

Con Go 1.5 sembrano aver migliorato il processo di compilazione incrociata, il che significa che è integrato ora. Nessuna necessità ./make.basho brewnecessità. Il processo è descritto qui, ma per i TLDR (come me) là fuori: hai appena impostato il GOOSe ilGOARCH variabili e ambiente ed eseguire go build.

Per i copia-paster ancora più pigri (come me) là fuori, fai qualcosa di simile se sei su un sistema * nix:

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

Hai persino imparato il envtrucco, che ti consente di impostare le variabili di ambiente solo per quel comando, completamente gratuito.


4
Il envcomando esegue solo quella chiamata in un ambiente personalizzato e lo "ripristina" dopo averlo fatto. Ad esempio export GOOS=windows, eseguire , quindi il comando con o senza enve in echo $GOOSseguito. Con il envGOOS non è stato modificato.
leondepeon,

3
lo stesso vale (almeno in Bash) senza env. Ho eseguito export GOOS=windowsquindi GOOS=linux bash -c 'echo "GOOS: $GOOS"'poi echo "GOOS: $GOOS". Non envfornire maggiore compatibilità con altri dialetti guscio o con altre piattaforme? Altrimenti sembra superfluo qui.
davidchambers,

2
@davidchambers In BASH sono equivalenti. Mentre in qualche altra shell, ad esempio shell FISH, non supporta FOO=bar cmd, quindi è necessario utilizzare env FOO=bar cmd. Quindi penso che il più grande vantaggio da usare env FOO=bar cmdsia la compatibilità.
PickBoy

1
Incredibile risposta proprio qui. Hai risolto il mio problema, mi hai insegnato un nuovo trucco e mi hai fatto ridere.
T Blank

1
Ottima risposta, grazie! Per compilare per l'uso su Heroku (Intel x86) ho leggermente modificato la linea env GOOS=linux GOARCH=386 go build -v github.com/path/to/your/appe funziona come una campionessa
Ira Herman,

136

Grazie al gentile e paziente aiuto delle noci di Golang, la ricetta è la seguente:

1) È necessario compilare il compilatore Go per diverse piattaforme e architetture di destinazione. Questo viene fatto dalla cartella src nell'installazione go. Nel mio caso, l'installazione di Go si trova in /usr/local/gomodo da compilare un compilatore che è necessario emettere makeutility. Prima di farlo devi conoscere alcuni avvertimenti.

Si è verificato un problema con la libreria CGO durante la compilazione incrociata, pertanto è necessario disabilitare la libreria CGO.

La compilazione viene eseguita modificando la posizione nella directory di origine, poiché la compilazione deve essere eseguita in quella cartella

cd /usr/local/go/src

quindi compilare il compilatore Go:

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

È necessario ripetere questo passaggio per ciascun sistema operativo e architettura che si desidera incrociare compilando modificando i parametri GOOS e GOARCH.

Se lavori in modalità utente come faccio io, sudo è necessario perché il compilatore Go è nella directory di sistema. Altrimenti devi essere loggato come superutente. Su Mac potrebbe essere necessario abilitare / configurare l'accesso SU (non è disponibile per impostazione predefinita), ma se sei riuscito a installare Go potresti avere già l'accesso root.

2) Dopo aver creato tutti i compilatori incrociati, è possibile compilare felicemente l'applicazione compilando ad esempio le seguenti impostazioni:

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

Cambia GOOS e GOARCH in target che desideri costruire.

In caso di problemi con CGO, includere CGO_ENABLED = 0 nella riga di comando. Si noti inoltre che i file binari per Linux e Mac non hanno estensione, quindi è possibile aggiungere l'estensione per avere file diversi. -o switch indica Go per rendere il file di output simile ai vecchi compilatori per c / c ++, quindi appname.linux sopra usato può essere qualsiasi altra estensione.


Ciò che inizialmente mi ha confuso è che nella prima parte della compilation make dice: # Building compilers and Go bootstrap tool for host, darwin/amd64ma in seguito finisce come: --- Installed Go for windows/386 in /usr/local/go Installed commands in /usr/local/go/binquindi si deve osservare la fine piuttosto che l'inizio della compilazione del compilatore.
ljgww,

tutto è iniziato provando a fare: $ GOARCH=386 GOOS=linux go build app.goe ottenendo un errore # 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
Il pacchetto di Go in Homebrew ha un'opzione "--cross-compile-all" che costruirà automaticamente tutti i compilatori incrociati.
nimrodm,

8
ottimo consiglio @nimrodm! per ricompilare la tua installazione go, devi eseguirebrew reinstall go --cross-compile-all
linqu

1
@ljgww 'sudo' non ha ENV configurato. Ho finito per usare chown su / usr / local / go / pkg / linux_amd64 /
Nuno Silva,

63

Se usi Homebrew su OS X, hai una soluzione più semplice:

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

o..

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

Utilizzare reinstallse si è già goinstallato.


3
Notando che gli switch aggiornati sono: --cross-compile-all Crea i cross-compilatori e il supporto di runtime per tutte le piattaforme supportate --cross-compile-common Crea i cross-compilatori e il supporto di runtime per darwin, linux e windows
Chip Tol

3
--cross-compile-allè ora--with-cc-all
gianebao

@ sheeks06 - risolto. Grazie!
docwhat,

1
Queste bandiere non esistono più da quello che posso dire. L'unica opzione rilevante che vedo è --without-cgo :(
rdegges,

5
Da Go 1.5, non ci sono cross-compilatori separati, ora usi solo le bandiere tip.golang.org/doc/go1.5#compiler_and_tools
chuckus

24

Puoi farlo abbastanza facilmente usando Docker, quindi non sono necessarie ulteriori librerie. Basta eseguire questo comando:

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
'

Puoi trovare maggiori dettagli in questo post: https://medium.com/iron-io-blog/how-to-cross-compile-go-programs-using-docker-beaa102a316d


1
Perché qualcuno dovrebbe voler installare Docker per farlo quando potrebbe semplicemente fare un loop shell env GOOS=x GOARCH=y go install something/...e finire con i binari appropriati sotto $GOPATH/bin/$GOOS_$GOARCH?? E a proposito, Go supporta più dei tre sistemi operativi che elenchi, perché nessun amore per i BSD?
Dave C,

8
Non installeresti Docker solo per fare questo, ma se ce l'hai, questo è più facile e più pulito delle alternative.
Travis Reeder,

7

Il processo di creazione di eseguibili per molte piattaforme può essere un po 'noioso, quindi suggerisco di usare uno script:

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

Ho controllato questo script solo su OSX

gist - go-executable-build.sh


Esattamente quello che stavo cercando ... l'ho ancorato :) gist.github.com/marcellodesales/…
Marcello de Sales

6

per le persone che necessitano di CGO abilitato e compilazione incrociata dalle finestre di targeting OSX

Avevo bisogno di abilitare CGO durante la compilazione per Windows dal mio mac poiché avevo importato https://github.com/mattn/go-sqlite3 e ne aveva bisogno. Compilare secondo altre risposte mi ha dato ed errore:

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

Se sei come me e devi compilare con CGO. Questo è quello che ho fatto:

1. Effettueremo la compilazione incrociata per Windows con una libreria dipendente dalla CGO. Per prima cosa abbiamo bisogno di un compilatore incrociato installato comemingw-w64

brew install mingw-w64

Questo probabilmente lo installerà qui /usr/local/opt/mingw-w64/bin/ .

2. Proprio come le altre risposte, per prima cosa dobbiamo aggiungere il nostro arco di Windows alla nostra toolchain di compilatore go ora. La compilazione di un compilatore richiede un compilatore (frase strana), mentre il compilatore go richiede un compilatore predefinito separato. Possiamo scaricare un binario predefinito o compilare dal sorgente in una cartella, ad esempio: ~/Documents/go ora possiamo migliorare il nostro compilatore Go, in base alla risposta più alta, ma questa volta con CGO_ENABLED=1e il nostro compilatore precompilato separato GOROOT_BOOTSTRAP(Pooya è il mio nome utente):

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.Ora durante la compilazione del nostro codice Go utilizzare mingwper compilare il nostro file go targeting windows con CGO abilitato:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.