Кросс-компиляция Go на OSX?


143

Я пытаюсь перекрестно скомпилировать приложение go на OSX для создания двоичных файлов для Windows и Linux. Я прочитал все, что смог найти в сети. Ближайший пример, который я нашел, был опубликован (не считая многих незаконченных обсуждений в списке рассылки глупых людей):

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

пока что это не работает на моей установке. У меня есть версия 1.0.2. Поскольку 1.0.2 появилась совсем недавно, мне кажется, что все вышеперечисленные примеры не применимы к этой версии.

Пытался сделать ./make.bash --no-cleanс переменными ENV, установленными на 386 / windows, сборка идет, однако сборка идет для моей установки, которая darwin/amd64полностью игнорирует то, что установлено в ENV, которое предполагает сборку другого компилятора.

Какие-либо советы, как это можно сделать (если это вообще возможно)?


параллельно с этим я задал тот же вопрос в списке рассылки golang-nut, и с любезной помощью и терпением людей был приготовлен окончательный рецепт ... это тема обсуждения: groups.google.com/forum/?fromgroups=# ! topic / golang-nut /… было несколько шагов и выводов, по пути я ошибся, но теперь рецепт кажется довольно простым - 3 шага и несколько итераций.
ljgww

Теперь, когда я перехожу к повторению, я блуждаю относительно того, почему переменные ENV не запускали правильную компиляцию - возможно, потому, что я это сделал sudo(вероятно, я бы получил другой unix ENV при sudo-ing, поэтому GOOS и GOARCH не будут доступны, если они не будут выполнены inline)
ljgww

re: jdi - Я просто пытался скомпилировать свое "мокап" приложение go для бинарных файлов win / lin на Mac, но для этого мне пришлось собрать go для каждой комбинации платформы / процессора. (пока не могу ответить на свой вопрос - у меня недостаточно репутации)
ljgww

1
Вы ввели именно то, что написано в примере? CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash- если вы попытались разделить его более чем на одну строку, то переменная среды не будет экспортирована, что соответствует симптомам
Ник Крейг-Вуд,

Убедитесь, что вы не путаете хост и целевую архитектуру. Вы должны увидеть такой вывод: «# Сборка компиляторов и средство начальной загрузки Go для хоста, darwin / amd64». "# Сборка пакетов и команд для хоста, darwin / amd64." "# Сборка пакетов и команд для windows / 386."
Сэм

Ответы:


164

В Go 1.5 они, кажется, улучшили процесс кросс-компиляции, то есть теперь он встроен. Нет ./make.bash-ную или brew-ную требуется. Процесс описан здесь, но для участников TLDR (таких как я): вы просто устанавливаете GOOSи GOARCHпеременные среды и запускаете сборку go.

Для еще более ленивых копипастеров (вроде меня) сделайте что-нибудь вроде этого, если вы используете систему * nix:

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

Вы даже научились envтрюку, который позволяет вам совершенно бесплатно устанавливать переменные среды только для этой команды.


4
Команда envзапускает только этот вызов в настраиваемой среде и «сбрасывает» его после завершения. Например, запустить export GOOS=windows, затем команду с или без envи echo $GOOSпосле. С envГСНО ничего не изменилось.
leondepeon

3
то же самое верно (по крайней мере, в Bash) без env. Я побежал , export GOOS=windowsто GOOS=linux bash -c 'echo "GOOS: $GOOS"'потом echo "GOOS: $GOOS". envОбеспечивает ли большую совместимость с другими диалектами оболочки или с другими платформами? Если нет, то здесь это кажется лишним.
davidchambers

2
@davidchambers В BASH они эквивалентны. Хотя в какой-то другой оболочке, например, в оболочке FISH она не поддерживается FOO=bar cmd, поэтому вам придется использовать env FOO=bar cmd. Таким образом, я считаю, что самым большим преимуществом использования env FOO=bar cmdявляется совместимость.
PickBoy 01

1
Невероятный ответ прямо здесь. Вы решили мою проблему, научили меня новому трюку и заставили меня усмехнуться про себя.
T Blank

1
Отличный ответ, спасибо! Чтобы скомпилировать для использования на heroku (Intel x86), я немного изменил строку, env GOOS=linux GOARCH=386 go build -v github.com/path/to/your/appи она работает как чемпион
Ира Герман

136

Благодаря доброй и терпеливой помощи голанг-орехов рецепт такой:

1) Нужно скомпилировать компилятор Go для разных целевых платформ и архитектур. Это делается из папки src в установке go. В моем случае установка Go находится в нем, /usr/local/goпоэтому для компиляции компилятора нужно выпустить makeутилиту. Перед тем как это сделать, вам нужно знать некоторые предостережения.

При кросс-компиляции возникает проблема с библиотекой CGO, поэтому необходимо отключить библиотеку CGO.

Компиляция выполняется путем изменения местоположения на исходный каталог, поскольку компиляция должна выполняться в этой папке

cd /usr/local/go/src

затем скомпилируйте компилятор Go:

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

Вам нужно повторить этот шаг для каждой ОС и каждой архитектуры, которые вы хотите кросс-компилировать, изменив параметры GOOS и GOARCH.

Если вы работаете в пользовательском режиме, как я, sudo необходимо, потому что компилятор Go находится в системном каталоге. В противном случае вам нужно будет войти в систему как суперпользователь. На Mac вам может потребоваться включить / настроить доступ SU (по умолчанию он недоступен), но если вам удалось установить Go, возможно, у вас уже есть root-доступ.

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 переключатель указывает Go сделать выходной файл похожим на старые компиляторы для c / c ++, таким образом, использованное выше имя приложения. linux может быть любым другим расширением.


Что меня сначала смутило, так это то, что в первой части компиляции make говорит: # 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 /
Нуно Сильва

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-compile-all Создать кросс-компиляторы и поддержку среды выполнения для всех поддерживаемых платформ --cross-compile-common Создать кросс-компиляторы и поддержку среды выполнения для darwin, linux и Windows
Chip Tol

3
--cross-compile-allсейчас--with-cc-all
gianebao

@ sheeks06 - исправлено. Благодарность!
docwhat

1
Эти флаги больше не существуют, насколько я могу судить. Единственный подходящий вариант, который я вижу, - это --without-cgo :(
rdegges

5
Начиная с Go 1.5, нет отдельных кросс-компиляторов, теперь вы используете только флаги tip.golang.org/doc/go1.5#compiler_and_tools
chuckus 04

24

Вы можете сделать это довольно легко с помощью Docker, поэтому дополнительных библиотек не требуется. Просто запустите эту команду:

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?? И, кстати, Go поддерживает более трех перечисленных вами операционных систем, почему нет любви к 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


Именно то, что я искал ... Я сделал это в докере
Марчелло де Сейлз,

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. Сначала нам нужен кросс-компилятор, напримерmingw-w64

brew install mingw-w64

Это, вероятно, установит его здесь /usr/local/opt/mingw-w64/bin/ .

2. Как и в других ответах, нам сначала нужно добавить нашу арку Windows в нашу инструментальную цепочку компилятора go. Для компиляции компилятора нужен компилятор (странное предложение). Для компиляции компилятора go нужен отдельный предварительно собранный компилятор. Мы можем загрузить предварительно созданный двоичный файл или выполнить сборку из исходного кода в папке, например: ~/Documents/go теперь мы можем улучшить наш компилятор Go, в соответствии с верхним ответом, но на этот раз с CGO_ENABLED=1нашим отдельным предварительно созданным компилятором 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 с включенным 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.