Вступление
Go programming language поставляется с богатым набором инструментов, который делает получение пакетов и создание исполняемых файлов невероятно простым. Одна из самых мощных функций Go - возможность кросс-сборки исполняемых файлов для любой поддерживаемой Go иностранной платформы. Это значительно упрощает тестирование и распространение пакетов, потому что вам не нужен доступ к конкретной платформе, чтобы распространять для нее свой пакет.
В этом руководстве вы будете использовать инструменты Go, чтобы получить пакет из системы управления версиями и автоматически установить его исполняемый файл. Затем вы вручную создадите и установите исполняемый файл, чтобы вы могли быть знакомы с процессом. Затем вы создадите исполняемый файл для другой архитектуры и автоматизируете процесс сборки для создания исполняемых файлов для нескольких платформ. Когда вы закончите, вы узнаете, как создавать исполняемые файлы для Windows и macOS, а также для других платформ, которые вы хотите поддерживать.
Предпосылки
Чтобы следовать этому уроку, вам понадобится:
-
Один сервер Ubuntu 16.04, настроенный следующим образомthe Ubuntu 16.04 initial server setup guide, включая пользователя sudo без полномочий root и брандмауэр.
-
Go установлен, как описано вHow to Install Go 1.6 on Ubuntu 16.04.
[[step-1 -—- install-go-programs-from-version-control]] == Шаг 1. Установка программ Go из системы контроля версий
Прежде чем мы сможем создать исполняемые файлы из пакета Go, мы должны получить его исходный код. Инструментgo get
может получать пакеты из систем контроля версий, таких как GitHub. Под капотомgo get
клонирует пакеты в подкаталоги каталога$GOPATH/src/
. Затем, если применимо, он устанавливает пакет, создавая его исполняемый файл и помещая его в каталог$GOPATH/bin
. Если вы настроили Go, как описано в необходимых руководствах, каталог$GOPATH/bin
будет включен в переменную окружения$PATH
, что гарантирует, что вы можете использовать установленные пакеты из любой точки вашей системы.
Синтаксис командыgo get
:go get package-import-path
. package-import-path
- это строка, которая уникально идентифицирует пакет. Часто это расположение пакета в удаленном репозитории, таком как Github, или в каталоге в каталоге$GOPATH/src/
на вашем компьютере.
Обычноgo get
используется с флагом-u
, который инструктируетgo get
получить пакет и его зависимости или обновить эти зависимости, если они уже присутствуют на машине.
В этом руководстве мы установимCaddy, веб-сервер, написанный на Go. ДляCaddy’s instructionsx мы будем использоватьgithub.com/mholt/caddy/caddy
в качестве пути импорта пакета. Используйтеgo get
для загрузки и установки Caddy:
go get -u github.com/mholt/caddy/caddy
Выполнение команды займет некоторое время, но вы не увидите никакого прогресса, пока она извлекает пакет и устанавливает его. Отсутствие вывода фактически указывает на то, что команда выполнена успешно.
Когда команда завершится, вы обнаружите, что исходный код Кэдди доступен в$GOPATH/src/github.com/mholt/caddy
. Кроме того, поскольку у Caddy есть исполняемый файл, он был автоматически создан и сохранен в каталоге$GOPATH/bin
. Убедитесь в этом, используяwhich
для вывода местоположения исполняемого файла:
which caddy
Вы увидите следующий вывод:
Output/home/sammy/work/bin/caddy
[.Примечание]##
Note: командаgo get
устанавливает пакеты из ветки по умолчанию репозитория Git, которая во многих случаях являетсяmaster
или ветвью в разработке. Обязательно ознакомьтесь с инструкциями, которые обычно находятся в файле репозиторияREADME
, прежде чем использоватьgo get
.
Вы можете использовать команды Git, напримерgit checkout
, чтобы выбрать другую ветку для источников, полученных с помощью командыgo get
. Просмотрите руководствоHow to Use Git Branches, чтобы узнать больше о том, как переключать ветки.
Давайте рассмотрим процесс установки пакетов Go более подробно, начиная с создания исполняемых файлов из пакетов, которые мы уже получили.
[[step-2 -—- сборка исполняемого файла]] == Шаг 2 - Создание исполняемого файла
Командаgo get
загрузила исходный код и установила исполняемый файл Caddy за одну команду. Но вы можете захотеть пересобрать исполняемый файл самостоятельно или создать исполняемый файл из своего собственного кода. Командаgo build
создает исполняемые файлы.
Хотя мы уже установили Caddy, давайте создадим его заново вручную, чтобы мы могли освоиться с этим процессом. Выполнитеgo build
и укажите путь импорта пакета:
go build github.com/mholt/caddy/caddy
Как и прежде, отсутствие вывода указывает на успешную работу. Исполняемый файл будет создан в вашем текущем каталоге с тем же именем, что и каталог, содержащий пакет. В этом случае исполняемый файл будет называтьсяcaddy
.
Если вы находитесь в каталоге пакета, вы можете опустить путь к пакету и просто запуститьgo build
.
Чтобы указать другое имя или расположение для исполняемого файла, используйте флаг-o
. Давайте создадим исполняемый файл с именемcaddy-server
и поместим его в каталогbuild
в текущем рабочем каталоге:
go build -o build/caddy-server github.com/mholt/caddy/caddy
Эта команда создает исполняемый файл, а также создает каталог./build
, если он не существует.
Теперь давайте посмотрим на установку исполняемых файлов.
[[шаг-3 -—- установка исполняемого файла]] == Шаг 3 - Установка исполняемого файла
Сборка исполняемого файла создает исполняемый файл в текущем каталоге или каталоге по вашему выбору. Установка исполняемого файла - это процесс создания исполняемого файла и его сохранения в$GOPATH/bin
. Командаgo install
работает так же, какgo build
, ноgo install
заботится о размещении выходного файла в нужном для вас месте.
Чтобы установить исполняемый файл, используйтеgo install
, за которым следует путь для импорта пакета. Еще раз, используйте Caddy, чтобы попробовать это:
go install github.com/mholt/caddy/caddy
Как и в случае сgo build
, вы не увидите вывода, если команда выполнена успешно. И, как и прежде, исполняемый файл создается с тем же именем, что и каталог, содержащий пакет. Но на этот раз исполняемый файл хранится в$GOPATH/bin
. Если$GOPATH/bin
является частью вашей переменной среды$PATH
, исполняемый файл будет доступен из любой точки вашей операционной системы. Вы можете проверить его местоположение с помощью командыwhich
:
which caddy
Вы увидите следующий вывод:
Output of which/home/sammy/work/bin/caddy
Теперь, когда вы понимаете, как работаютgo get
,go build
иgo install
и как они связаны, давайте рассмотрим одну из самых популярных функций Go: создание исполняемых файлов для других целевых платформ.
[[шаг-4 -—- создание-исполняемых-файлов-для-разных-архитектур]] == Шаг 4 - Создание исполняемых файлов для разных архитектур
Командаgo build
позволяет создавать исполняемый файл для любой поддерживаемой Go целевой платформыon your platform. Это означает, что вы можете тестировать, выпускать и распространять свое приложение, не создавая исполняемые файлы на целевых платформах, которые вы хотите использовать.
Кросс-компиляция работает путем установки необходимых переменных среды, которые определяют целевую операционную систему и архитектуру. Мы используем переменнуюGOOS
для целевой операционной системы иGOARCH
для целевой архитектуры. Чтобы создать исполняемый файл, команда примет следующую форму:
env GOOS=target-OS GOARCH=target-architecture go build package-import-path
Командаenv
запускает программу в измененной среде. Это позволяет использовать переменные окружения только для текущего выполнения команды. Переменные сбрасываются или сбрасываются после выполнения команды.
В следующей таблице показаны возможные комбинацииGOOS
иGOARCH
, которые вы можете использовать:
GOOS - целевая операционная система |
GOARCH - Целевая платформа |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[.предупреждение]##
Warning: Для кросс-компиляции исполняемых файлов для Android требуетсяAndroid NDK и некоторая дополнительная настройка, выходящая за рамки данного руководства.
Используя значения в таблице, мы можем собрать Caddy для Windows 64-bit следующим образом:
env GOOS=windows GOARCH=amd64 go build github.com/mholt/caddy/caddy
Еще раз, отсутствие вывода указывает на то, что операция прошла успешно. Исполняемый файл будет создан в текущем каталоге, используя имя пакета в качестве имени. Однако, поскольку мы создали этот исполняемый файл для Windows, его имя заканчивается суффиксом.exe
.
У вас должен быть файлcaddy.exe
в вашем текущем каталоге, что вы можете проверить с помощью командыls
.
ls caddy.exe
Вы увидите файлcaddy.exe
, указанный в выводе:
Outputcaddy.exe
[.note] #Note: Вы можете использовать флаг-o
, чтобы переименовать исполняемый файл или поместить его в другое место. Однако при создании исполняемого файла для Windows и предоставлении другого имени не забудьте явно указать суффикс `.exe` при установке имени исполняемого файла.
#
Давайте посмотрим на сценарии этого процесса, чтобы упростить выпуск программного обеспечения для нескольких целевых сред.
[[step-5 -—- Creating-a-script-to-automate-cross-compilation]] == Шаг 5 - Создание сценария для автоматизации кросс-компиляции
Процесс создания исполняемых файлов для многих платформ может быть немного утомительным, но мы можем создать сценарий, чтобы упростить задачу.
Сценарий примет путь импорта пакета в качестве аргумента, перебирает предварительно определенный список пар операционной системы и платформы и генерирует исполняемый файл для каждой пары, помещая выходные данные в текущий каталог. Каждому исполняемому файлу будет присвоено имя пакета, за которым следует целевая платформа и архитектура в формеpackage-OS-architecture
. Это будет универсальный скрипт, который вы можете использовать в любом проекте.
Перейдите в домашний каталог и создайте новый файл с именемgo-executable-build.bash
в текстовом редакторе:
cd ~
nano go-executable-build.bash
Мы начнем наш скрипт со строкиshebang. Эта строка определяет, какой интерпретатор будет анализировать этот скрипт, когда он запускается как исполняемый файл. Добавьте следующую строку, чтобы указать, чтоbash
должен выполнить этот сценарий:
go-executable-build.bash
#!/usr/bin/env bash
Мы хотим взять путь импорта пакета в качестве аргумента командной строки. Для этого мы будем использовать переменную$n
, гдеn
- неотрицательное число. Переменная$0
содержит имя выполняемого вами скрипта, а$1
и выше будут содержать аргументы, предоставленные пользователем. Добавьте эту строку в сценарий, который получит первый аргумент из командной строки и сохранит его в переменной с именемpackage
:
go-executable-build.bash
...
package=$1
Далее убедитесь, что пользователь предоставил это значение. Если значение не указано, выйдите из сценария с сообщением, объясняющим, как использовать сценарий:
go-executable-build.bash
...
if [[z "$package" ]]; then
echo "usage: $0 "
exit 1
fi
Этот операторif
проверяет значение переменной$package
. Если он не установлен, мы используемecho
для вывода правильного использования, а затем завершаем сценарий, используяexit
. exit
принимает в качестве аргумента возвращаемое значение, которое должно быть0
для успешных выполнений и любое ненулевое значение для неудачных выполнений. Мы используем здесь1
, так как сценарий не удался.
[.Примечание]##
Note: если вы хотите, чтобы этот сценарий работал с предопределенным пакетом, измените переменнуюpackage
, чтобы она указывала на этот путь импорта:
go-executable-build.bash
...
package="github.com/user/hello"
Далее мы хотим извлечь имя пакета из пути. Путь импорта пакета разделен символами/
, а имя пакета находится в конце пути. Сначала мы разделим путь импорта пакета на массив, используя/
в качестве разделителя:
go-executable-build.bash
package_split=(${package//\// })
Имя пакета должно быть последним элементом этого нового массива$package_split
. В Bash вы можете использовать отрицательный индекс массива для доступа к массиву с конца, а не с начала. Добавьте эту строку, чтобы получить имя пакета из массива и сохранить его в переменной с именемpackage_name
:
go-executable-build.bash
...
package_name=${package_split[-1]}
Теперь вам нужно решить, для каких платформ и архитектур вы хотите создавать исполняемые файлы. В этом руководстве мы создадим исполняемые файлы для 64-битной Windows, 32-битной Windows и 64-битной MacOS. Мы поместим эти цели в массив с форматомOS/Platform
, поэтому мы можем разделить каждую пару на переменныеGOOS
иGOARCH
, используя тот же метод, который мы использовали для извлечения имени пакета из пути . Добавьте платформы в скрипт:
go-executable-build.bash
...
platforms=("windows/amd64" "windows/386" "darwin/amd64")
Затем мы пройдемся по массиву платформ, разделим каждую запись платформы на значения для переменных средыGOOS
иGOARCH
и будем использовать их для создания исполняемого файла. Мы можем сделать это с помощью следующего циклаfor
:
go-executable-build.bash
...
for platform in "${platforms[@]}"
do
...
done
Переменнаяplatform
будет содержать запись из массиваplatforms
на каждой итерации. Нам нужно разделитьplatform
на две переменные -GOOS
иGOARCH
. Добавьте в циклfor
следующие строки:
go-executable-build.bash
for platform in "${platforms[@]}"
do
platform_split=(${platform//\// })
GOOS=${platform_split[0]}
GOARCH=${platform_split[1]}
done
Далее мы сгенерируем имя исполняемого файла, объединив имя пакета с ОС и архитектурой. Когда мы создаем для Windows, нам также необходимо добавить суффикс.exe
к имени файла. Добавьте этот код в циклfor
:
go-executable-build.bash
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
done
Установив переменные, мы используемgo build
для создания исполняемого файла. Добавьте эту строку в тело циклаfor
прямо над ключевым словомdone
:
go-executable-build.bash
...
if [ $GOOS = "windows" ]; then
output_name+='.exe'
fi
env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
done
Наконец, мы должны проверить, не было ли ошибок при сборке исполняемого файла. Например, мы можем столкнуться с ошибкой, если попытаемся создать пакет, для которого у нас нет источников. Мы можем проверить код возврата командыgo build
на ненулевое значение. Переменная$?
содержит код возврата от выполнения предыдущей команды. Еслиgo build
возвращает что-либо, кроме0
, возникла проблема, и мы хотим выйти из скрипта. Добавьте этот код в циклfor
после командыgo build
и над ключевым словомdone
.
go-executable-build.bash
...
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
Теперь у нас есть скрипт, который будет собирать несколько исполняемых файлов из нашего пакета Go. Вот законченный скрипт:
go-executable-build.bash
#!/usr/bin/env bash
package=$1
if [[z "$package" ]]; then
echo "usage: $0 "
exit 1
fi
package_split=(${package//\// })
package_name=${package_split[-1]}
platforms=("windows/amd64" "windows/386" "darwin/amd64")
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
Убедитесь, что ваш файл соответствует предыдущему коду. Затем сохраните файл и выйдите из редактора.
Прежде чем мы сможем использовать скрипт, мы должны сделать его исполняемым с помощью командыchmod
:
chmod +x go-executable-build.bash
Наконец, протестируйте скрипт, создав исполняемые файлы для Caddy:
./go-executable-build.bash github.com/mholt/caddy/caddy
Если все идет хорошо, у вас должны быть исполняемые файлы в вашем текущем каталоге. Отсутствие вывода указывает на успешное выполнение скрипта. Вы можете проверить, созданы ли исполняемые файлы, используя командуls
:
ls caddy*
Вы должны увидеть все три версии:
Example ls outputcaddy-darwin-amd64 caddy-windows-386.exe caddy-windows-amd64.exe
Чтобы изменить целевые платформы, просто измените переменнуюplatforms
в своем скрипте.
Заключение
Из этого руководства вы узнали, как использовать инструменты Go для получения пакетов из систем контроля версий, а также для сборки и кросс-компиляции исполняемых файлов для разных платформ.
Вы также создали скрипт, который можно использовать для кросс-компиляции одного пакета для многих платформ.
Чтобы убедиться, что ваше приложение работает правильно, вы можете взглянуть наtesting иcontinuous integration, напримерTravis-CI иAppVeyor, для тестирования в Windows.
Если вас интересует Caddy и способы его использования, взгляните наHow to Host a Website with Caddy on Ubuntu 16.04.