Compilación cruzada ¿Ir en OSX?

142

Estoy tratando de compilar una aplicación go en OSX para construir binarios para Windows y Linux. He leído todo lo que pude encontrar en la red. El ejemplo más cercano que he encontrado ha sido publicado en (aparte de muchas discusiones inconclusas sobre la lista de correo para volverse loco):

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

Sin embargo, no funciona en mi instalación. Tengo ir 1.0.2. Como 1.0.2 es bastante reciente, me parece que todos los ejemplos anteriores no se aplican a esta versión.

Intenté hacer ./make.bash --no-cleancon los vars de ENV configurados en 386 / windows, construye ir, sin embargo, construye ir para mi instalación que es darwin/amd64e ignora completamente lo que está configurado en ENV que supone construir un compilador diferente.

¿Algún consejo sobre cómo se puede hacer (si es que se puede hacer)?

ljgww
fuente
Paralelamente a esto, hice la misma pregunta en la lista de correo de Golang-Nuts, y con la amable ayuda y paciencia de la gente, la receta final se cocinó ... este es el hilo de discusión: groups.google.com/forum/?fromgroups=# ! topic / golang-nuts / ... hubo varios pasos y conclusiones, me equivoqué en el camino, pero ahora la receta parece bastante simple: 3 pasos y algunas iteraciones.
ljgww
ahora que estoy revisando la recapitulación, me pregunto por qué los vars de ENV no activaron la compilación correcta, tal vez porque lo hice sudo(probablemente obtendría un ENV de Unix diferente al sudo, por lo que GOOS & GOARCH no estaría disponible si no se realizaran) en línea)
ljgww
re: jdi - Solo estaba tratando de compilar mi aplicación de "maqueta" go para ganar / lin binarios en mac, pero, para hacerlo, tuve que compilarlo para cada combinación de plataforma / procesador. (Todavía no puedo responder a mi propia pregunta, porque no tengo suficiente reputación aquí)
ljgww
1
¿Escribiste exactamente lo que dijo en el ejemplo? CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash- si intentó dividirlo en más de una línea, la variable de entorno no se exportará, lo que se ajusta a los síntomas
Nick Craig-Wood
Asegúrese de no confundir la arquitectura de host y de destino. Debería ver esta salida: "# Compiladores de compilación y herramienta de arranque Go para host, darwin / amd64". "# Creación de paquetes y comandos para host, darwin / amd64". "# Creación de paquetes y comandos para windows / 386".
Sam

Respuestas:

157

Con Go 1.5 parecen haber mejorado el proceso de compilación cruzada, lo que significa que ahora está integrado. Sin ./make.bash-ing o brew-ing requerido. El proceso se describe aquí, pero para los tldr-res (como yo) por ahí: que acaba de establecer los GOOSy las GOARCHvariables de entorno y ejecutar la acumulación marcha.

Para los copy-pasters más perezosos (como yo), haga algo como esto si está en un sistema * nix:

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

Incluso aprendió el envtruco, que le permite establecer variables de entorno solo para ese comando, completamente gratis.

leondepeon
fuente
44
El envcomando ejecuta solo esa llamada en un entorno personalizado y la 'restablece' después de que se realiza. Por ejemplo export GOOS=windows, ejecutar , luego el comando con o sin el envy echo $GOOSluego. Con el envGOOS no se cambió.
leondepeon
3
lo mismo es cierto (al menos en Bash) sin env. Corrí export GOOS=windowsa continuación, GOOS=linux bash -c 'echo "GOOS: $GOOS"'a continuación echo "GOOS: $GOOS". ¿ envProporciona una mayor compatibilidad con otros dialectos de shell o con otras plataformas? Si no, parece superfluo aquí.
davidchambers
2
@davidchambers En BASH son equivalentes. Mientras está en otro Shell, por ejemplo, FISH shell, no es compatible FOO=bar cmd, por lo que debe usarlo env FOO=bar cmd. Por lo tanto, creo que la mayor ventaja de usar env FOO=bar cmdes la compatibilidad.
PickBoy
1
Increíble respuesta aquí mismo. Resolviste mi problema, me enseñaste un nuevo truco y me hiciste reírme.
T Blank
1
Gran respuesta, gracias! Para compilar para usar en heroku (Intel x86) modifiqué ligeramente la línea env GOOS=linux GOARCH=386 go build -v github.com/path/to/your/appy funciona como un campeón
Ira Herman
136

Gracias a la amable y paciente ayuda de las nueces de golang, la receta es la siguiente:

1) Se necesita compilar el compilador Go para diferentes plataformas y arquitecturas de destino. Esto se hace desde la carpeta src en la instalación de go. En mi caso, la instalación de Go se encuentra /usr/local/goasí, para compilar un compilador, necesita emitir una makeutilidad. Antes de hacer esto, necesita conocer algunas advertencias.

Hay un problema con la biblioteca CGO cuando se realiza una compilación cruzada, por lo que es necesario deshabilitar la biblioteca CGO.

La compilación se realiza cambiando la ubicación al directorio de origen, ya que la compilación debe realizarse en esa carpeta

cd /usr/local/go/src

luego compila el compilador Go:

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

Debe repetir este paso para cada sistema operativo y arquitectura que desee compilar cruzando cambiando los parámetros GOOS y GOARCH.

Si está trabajando en modo de usuario como yo, sudo es necesario porque el compilador Go está en el directorio del sistema. De lo contrario, debe iniciar sesión como superusuario. En Mac, es posible que deba habilitar / configurar el acceso a SU (no está disponible de forma predeterminada), pero si ha logrado instalar Go, posiblemente ya tenga acceso de root.

2) Una vez que haya compilado todos los compiladores cruzados, puede compilar felizmente su aplicación mediante la siguiente configuración, por ejemplo:

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 el GOOS y GOARCH a los objetivos que deseas construir.

Si encuentra problemas con CGO, incluya CGO_ENABLED = 0 en la línea de comando. También tenga en cuenta que los archivos binarios para Linux y Mac no tienen extensión, por lo que puede agregar extensión por el simple hecho de tener diferentes archivos. -o switch indica Ir a hacer que el archivo de salida sea similar a los compiladores antiguos para c / c ++, por lo tanto, el nombre de aplicación utilizado anteriormente.linux puede ser cualquier otra extensión.

ljgww
fuente
Lo que inicialmente me confundió es que en la primera parte de la compilación make dice: # Building compilers and Go bootstrap tool for host, darwin/amd64pero luego en realidad termina como: --- Installed Go for windows/386 in /usr/local/go Installed commands in /usr/local/go/binasí que uno observará el final en lugar del comienzo de la compilación del compilador.
ljgww
todo comenzó tratando de hacer: $ GOARCH=386 GOOS=linux go build app.goy obteniendo un error # 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
El paquete de Go en Homebrew tiene una opción "--cross-compile-all" que construirá automáticamente todos los compiladores cruzados.
nimrodm
8
gran consejo @nimrodm! recompilar su instalación go, es necesario ejecutarbrew reinstall go --cross-compile-all
Linqu
1
@ljgww 'sudo' no tiene ENV configurado. Terminé usando chown en / usr / local / go / pkg / linux_amd64 /
Nuno Silva el
63

Si usa Homebrew en OS X, entonces tiene una solución más simple:

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

o..

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

Úselo reinstallsi ya lo ha goinstalado.

docwhat
fuente
3
Los conmutadores actualizados son: --cross-compile-all Construye los compiladores cruzados y el soporte de tiempo de ejecución para todas las plataformas compatibles --cross-compile-common Construye los compiladores cruzados y el soporte de tiempo de ejecución para darwin, linux y windows
Chip Tol
3
--cross-compile-alles ahora--with-cc-all
gianebao
@ sheeks06 - arreglado. ¡Gracias!
docwhat
1
Estas banderas ya no existen por lo que puedo decir. La única opción relevante que veo es --without-cgo :(
rdegges
55
Desde Go 1.5, no hay compiladores cruzados separados, solo usa las banderas ahora tip.golang.org/doc/go1.5#compiler_and_tools
chuckus
24

Puede hacerlo con bastante facilidad usando Docker, por lo que no se requieren libs adicionales. Solo ejecuta 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
'

Puede encontrar más detalles en esta publicación: https://medium.com/iron-io-blog/how-to-cross-compile-go-programs-using-docker-beaa102a316d

Travis Reeder
fuente
1
¿Por qué alguien querría instalar Docker para hacer esto cuando podría simplemente hacer un ciclo de shell env GOOS=x GOARCH=y go install something/...y terminar con los binarios apropiados en $GOPATH/bin/$GOOS_$GOARCH? Y, por cierto, Go admite más de los tres sistemas operativos que enumeras, ¿por qué no te gustan los BSD?
Dave C
8
No instalarías Docker solo para hacer esto, pero si lo tienes, es más fácil y limpio que las alternativas.
Travis Reeder
7

El proceso de creación de ejecutables para muchas plataformas puede ser un poco tedioso, por lo que sugiero usar un 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

Revisé este script solo en OSX

gist - go-executable-build.sh

Dima Kozhevin
fuente
Exactamente lo que estaba buscando ... lo he acoplado :) gist.github.com/marcellodesales/…
Marcello de Sales
6

para personas que necesitan CGO habilitado y compilación cruzada desde ventanas de orientación OSX

Necesitaba CGO habilitado mientras compilaba para Windows desde mi Mac ya que había importado https://github.com/mattn/go-sqlite3 y lo necesitaba. Compilar de acuerdo con otras respuestas me dio un error:

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

Si eres como yo y tienes que compilar con CGO. Esto es lo que hice:

1. Vamos a realizar una compilación cruzada para Windows con una biblioteca dependiente de CGO. Primero necesitamos un compilador cruzado instalado comomingw-w64

brew install mingw-w64

Esto probablemente lo instalará aquí /usr/local/opt/mingw-w64/bin/.

2. Al igual que otras respuestas, primero necesitamos agregar nuestro arco de Windows a nuestra cadena de herramientas del compilador de go ahora. La compilación de un compilador necesita un compilador (oración extraña) que compila el compilador de go necesita un compilador preconstruido por separado. Podemos descargar un binario precompilado o compilar desde la fuente en una carpeta, por ejemplo: ~/Documents/go ahora podemos mejorar nuestro compilador Go, de acuerdo con la respuesta principal, pero esta vez con CGO_ENABLED=1nuestro compilador GOROOT_BOOTSTRAPprecompilado por separado (Pooya es mi nombre de usuario):

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.Ahora, mientras compila nuestro código Go, use mingwpara compilar nuestras ventanas de orientación de archivos Go con CGO habilitado:

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
fuente