Compilação cruzada Ir para OSX?

142

Estou tentando compilar um aplicativo go no OSX para criar binários para Windows e Linux. Eu li tudo o que pude encontrar na net. O exemplo mais próximo que encontrei foi publicado (além de muitas discussões inacabadas na lista de discussão maluca):

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

ainda não funciona na minha instalação. Eu tenho 1.0.2. Como a 1.0.2 é bastante recente, parece-me que todos os exemplos acima não se aplicam a esta versão.

Tentado fazer ./make.bash --no-cleancom vars ENV definido como 386 / windows, ele cria go, no entanto, ele cria para minha instalação que é darwin/amd64e ignora completamente o que é definido em ENV que supõe a criação de compilador diferente.

Alguém aconselha como isso pode ser feito (se é que pode ser feito)?

ljgww
fonte
paralelo a isso, fiz a mesma pergunta na lista de e-mails de golang-nuts e, com a ajuda e paciência das pessoas, a receita final foi preparada ... este é o tópico de discussão: groups.google.com/forum/?fromgroups=# ! topic / golang-nuts /… houve várias etapas e conclusões, eu errei no caminho, mas agora a receita parece bem simples - 3 etapas e algumas iterações.
Ljgww 29/08/2012
agora que estou revendo a recapitulação, perambulo por que os vars ENV não acionaram a compilação correta - talvez porque o fiz sudo(provavelmente obteria ENV unix diferente ao fazer o sudo, para que o GOOS & GOARCH não estivesse disponível se não terminassem Inline)
ljgww
re: jdi - Eu estava apenas tentando compilar meu aplicativo go "mockup" para ganhar binários / lin no mac, mas, para fazer isso, eu tive que criar ele próprio para cada combinação de plataforma / processador. (não pode responder a minha própria pergunta ainda - não tendo o suficiente reputação aqui)
ljgww
1
Você digitou exatamente o que dizia no exemplo? CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash- se você tentou dividi-lo em mais de uma linha, em seguida, a variável de ambiente não serão exportados que se encaixa os sintomas
Nick Craig-Wood
Verifique se não está confundindo a arquitetura de host e destino. Você verá esta saída: "# Compilando compiladores e ferramenta Go bootstrap para host, darwin / amd64." "# Construindo pacotes e comandos para o host, darwin / amd64." "# Construindo pacotes e comandos para o Windows / 386."
Sam

Respostas:

157

Com o Go 1.5, eles parecem ter melhorado o processo de compilação cruzada, o que significa que ele está incorporado agora. Nenhum ./make.bash-ing ou brew-ing necessário. O processo é descrito aqui , mas para os TLDR-ers (como eu) lá fora: você acabou de definir os GOOSe as GOARCHvariáveis de ambiente e executar a construção movimento.

Para os usuários mais preguiçosos (como eu) por aí, faça algo assim se estiver em um sistema * nix:

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

Você até aprendeu o envtruque, que permite definir variáveis ​​de ambiente apenas para esse comando, completamente grátis.

leondepeon
fonte
4
O envcomando executa apenas essa chamada em um ambiente personalizado e a 'redefine' após a conclusão. Por exemplo run export GOOS=windows, então o comando com ou sem a enve echo $GOOSdepois. Com o envGOOS não foi alterado.
leondepeon
3
o mesmo é verdade (pelo menos no Bash) sem env. Eu corri export GOOS=windowsentão GOOS=linux bash -c 'echo "GOOS: $GOOS"'então echo "GOOS: $GOOS". Oferece envmaior compatibilidade com outros dialetos de shell ou com outras plataformas? Se não, parece supérfluo aqui.
Davidchambers
2
@davidchambers No BASH eles são equivalentes. Enquanto em algum outro shell, por exemplo, shell FISH, ele não suporta FOO=bar cmd, então você precisa usá-lo env FOO=bar cmd. Portanto, acho que a maior vantagem a ser usada env FOO=bar cmdé a compatibilidade.
PickBoy
1
Resposta incrível aqui. Você resolveu meu problema, me ensinou um novo truque e me fez rir de mim mesma.
T branco
1
Ótima resposta, obrigado! Para compilar para uso em heroku (Intel x86) I ligeiramente modificada da linha para env GOOS=linux GOARCH=386 go build -v github.com/path/to/your/appe funciona como um campeão
Ira Herman
136

Graças à ajuda gentil e paciente das nozes golang, a receita é a seguinte:

1) É necessário compilar o compilador Go para diferentes plataformas e arquiteturas de destino. Isso é feito na pasta src na instalação go. No meu caso, a instalação do Go está localizada /usr/local/goassim, para compilar um compilador, você precisa emitir o makeutilitário. Antes de fazer isso, você precisa conhecer algumas advertências.

Há um problema na biblioteca CGO durante a compilação cruzada, portanto, é necessário desativar a biblioteca CGO.

A compilação é feita alterando o local para o diretório de origem, pois a compilação deve ser feita nessa pasta

cd /usr/local/go/src

então compile o compilador Go:

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

Você precisa repetir esta etapa para cada SO e arquitetura que deseja cruzar a compilação, alterando os parâmetros GOOS e GOARCH.

Se você estiver trabalhando no modo de usuário como eu, o sudo será necessário porque o compilador Go está no diretório do sistema. Caso contrário, você precisa estar logado como superusuário. No Mac, pode ser necessário ativar / configurar o acesso da SU (por padrão, não está disponível), mas se você conseguiu instalar o Go, provavelmente já possui acesso root.

2) Depois de criar todos os compiladores cruzados, você poderá compilar com facilidade seu aplicativo usando as seguintes configurações, por exemplo:

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

Altere GOOS e GOARCH para os alvos que você deseja criar.

Se você encontrar problemas com o CGO, inclua CGO_ENABLED = 0 na linha de comandos. Observe também que os binários para linux e mac não têm extensão; portanto, você pode adicioná-la para ter arquivos diferentes. -o switch instrui o Go para tornar o arquivo de saída semelhante aos antigos compiladores para c / c ++, portanto acima do appname.linux usado pode ser qualquer outra extensão.

ljgww
fonte
O que inicialmente me confundiu é que, na primeira parte da compilação, make diz: # Building compilers and Go bootstrap tool for host, darwin/amd64mas mais tarde, na verdade, acaba como: --- Installed Go for windows/386 in /usr/local/go Installed commands in /usr/local/go/binentão devemos observar o final, em vez de começar a compilar o compilador.
precisa saber é
tudo começou por tentar fazer: $ GOARCH=386 GOOS=linux go build app.goe recebendo erro # 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
O pacote da Go no Homebrew tem a opção "--cross-compile-all", que criará automaticamente todos os compiladores cruzados.
Nimrodm
8
ótima dica @nimrodm! para recompilar sua instalação go, você precisa executarbrew reinstall go --cross-compile-all
linqu
1
@ljgww 'sudo' não possui o ENV configurado. Acabei usando chown em / usr / local / go / pkg / linux_amd64 /
Nuno Silva
63

Se você usa o Homebrew no OS X, tem uma solução mais simples:

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

ou..

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

Use reinstallse você já tiver goinstalado.

docwhat
fonte
3
Observando os interruptores atualizados são: --cross-compilação-tudo construir o cross-compiladores e suporte runtime para construir todas as plataformas suportadas --cross-compilação comum cross-compiladores e suporte de execução para darwin, Linux e Windows
Chip Tol
3
--cross-compile-allé agora--with-cc-all
gianebao
@ sheeks06 - corrigido. Obrigado!
Docwhat 14/05
1
Essas bandeiras não existem mais do que eu sei. A única opção relevante que vejo é --without-cgo :(
rdegges
5
Desde Go 1.5, não há cross-compiladores separados, você só pode usar as bandeiras agora tip.golang.org/doc/go1.5#compiler_and_tools
chuckus
24

Você pode fazer isso facilmente usando o Docker, portanto, não são necessárias bibliotecas extras. Basta executar este 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
'

Você pode encontrar mais detalhes neste post: https://medium.com/iron-io-blog/how-to-cross-compile-go-programs-using-docker-beaa102a316d

Travis Reeder
fonte
1
Por que alguém iria querer instalar o Docker para fazer isso quando eles poderiam fazer um loop de shell env GOOS=x GOARCH=y go install something/...e terminar com os binários apropriados em $GOPATH/bin/$GOOS_$GOARCH?? E, BTW, Go suporta mais do que os três sistemas operacionais listados, por que não ama os BSDs?
Dave C
8
Você não instalaria o Docker apenas para fazer isso, mas, se o tiver, será mais fácil e limpo do que as alternativas.
Travis Reeder
7

O processo de criação de executáveis ​​para muitas plataformas pode ser um pouco entediante, então sugiro usar um 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

Eu verifiquei este script apenas no OSX

gist - go-executable-build.sh

Dima Kozhevin
fonte
Exatamente o que eu estava procurando ... Eu o dockerizei :) gist.github.com/marcellodesales/…
Marcello de Sales
6

para pessoas que precisam de CGO ativado e compilação cruzada a partir das janelas de segmentação OSX

Eu precisava do CGO ativado durante a compilação do Windows para o Windows desde que havia importado o https://github.com/mattn/go-sqlite3 e ele precisava. Compilar de acordo com outras respostas me deu um erro:

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

Se você é como eu e precisa compilar com o CGO. Isto é o que eu fiz:

1.Nós vamos cruzar a compilação para janelas com uma biblioteca dependente de CGO. Primeiro, precisamos de um compilador cruzado instalado comomingw-w64

brew install mingw-w64

Isso provavelmente o instalará aqui /usr/local/opt/mingw-w64/bin/.

2.Como outras respostas, primeiro precisamos adicionar nosso arco do Windows à nossa cadeia de ferramentas do compilador go agora. Compilar um compilador precisa de um compilador (sentença estranha). O compilador go precisa de um compilador pré-compilado separado. Podemos fazer o download de um binário pré-construído ou compilar a partir do código-fonte em uma pasta, por exemplo: ~/Documents/go agora podemos melhorar nosso compilador Go, de acordo com a resposta principal, mas desta vez com CGO_ENABLED=1nosso compilador pré-construído separado GOROOT_BOOTSTRAP(Pooya é meu nome de usuário):

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

Agora, ao compilar nosso código Go, use-o mingwpara compilar nossas janelas de segmentação de arquivos go com o CGO ativado:

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
fonte