Ubuntu16.04で複数のプラットフォーム用のGo実行可能ファイルを構築する方法
序章
Goプログラミング言語には、パッケージの取得と実行可能ファイルの構築を非常に簡単にする豊富なツールチェーンが付属しています。 Goの最も強力な機能の1つは、Goがサポートする外部プラットフォーム用の実行可能ファイルをクロスビルドする機能です。 これにより、パッケージを配布するために特定のプラットフォームにアクセスする必要がないため、テストとパッケージ配布がはるかに簡単になります。
このチュートリアルでは、Goのツールを使用して、バージョン管理からパッケージを取得し、その実行可能ファイルを自動的にインストールします。 次に、実行可能ファイルを手動でビルドしてインストールし、プロセスに精通できるようにします。 次に、異なるアーキテクチャ用の実行可能ファイルをビルドし、ビルドプロセスを自動化して、複数のプラットフォーム用の実行可能ファイルを作成します。 完了すると、WindowsとmacOS、およびサポートしたい他のプラットフォーム用の実行可能ファイルを作成する方法がわかります。
前提条件
このチュートリアルに従うには、次のものが必要です。
- Ubuntu16.04初期サーバーセットアップガイドに従ってセットアップされた1つのUbuntu16.04サーバー。これには、sudo非rootユーザーとファイアウォールが含まれます。
- Ubuntu16.04にGo1.6をインストールする方法の説明に従ってインストールします。
ステップ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
にパッケージとその依存関係を取得するか、それらの依存関係がすでにマシンに存在する場合はそれらを更新するように指示します。
このチュートリアルでは、Goで記述されたWebサーバーであるCaddyをインストールします。 Caddyの指示xに従って、パッケージのインポートパスにgithub.com/mholt/caddy/caddy
を使用します。 go get
を使用して、Caddyをフェッチしてインストールします。
- go get -u github.com/mholt/caddy/caddy
コマンドの完了にはしばらく時間がかかりますが、パッケージをフェッチしてインストールしている間は進行状況は表示されません。 出力がない場合は、コマンドが正常に実行されたことを実際に示しています。
コマンドが完了すると、Caddyのソースコードが$GOPATH/src/github.com/mholt/caddy
にあります。 さらに、Caddyには実行可能ファイルがあるため、自動的に作成され、$GOPATH/bin
ディレクトリに保存されます。 which
を使用して実行可能ファイルの場所を印刷することにより、これを確認します。
- which caddy
次の出力が表示されます。
Output/home/sammy/work/bin/caddy
注:go get
コマンドは、Gitリポジトリのデフォルトブランチ(多くの場合、master
または開発中のブランチ)からパッケージをインストールします。 go get
を使用する前に、通常はリポジトリのREADME
ファイルにある手順を確認してください。
git checkout
などのGitコマンドを使用して、go get
コマンドを使用して取得したソースで別のブランチを選択できます。 チュートリアルGitブランチの使用方法を確認して、ブランチを切り替える方法の詳細を確認してください。
すでに取得したパッケージから実行可能ファイルを作成することから始めて、Goパッケージをインストールするプロセスをより詳細に見てみましょう。
ステップ2—実行可能ファイルを作成する
go get
コマンドは、ソースをダウンロードし、Caddyの実行可能ファイルを1つのコマンドでインストールしました。 ただし、実行可能ファイルを自分で再構築するか、独自のコードから実行可能ファイルを構築することをお勧めします。 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—実行可能ファイルのインストール
実行可能ファイルを作成すると、現在のディレクトリまたは選択したディレクトリに実行可能ファイルが作成されます。 実行可能ファイルのインストールは、実行可能ファイルを作成して$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機能の1つである他のターゲットの実行可能ファイルの作成について見ていきましょう。プラットフォーム。
ステップ4—さまざまなアーキテクチャの実行可能ファイルを構築する
go build
コマンドを使用すると、Goがサポートするターゲットプラットフォームの実行可能ファイルをプラットフォームに作成できます。 つまり、使用するターゲットプラットフォームで実行可能ファイルをビルドしなくても、アプリケーションをテスト、リリース、および配布できます。
クロスコンパイルは、ターゲットのオペレーティングシステムとアーキテクチャを指定する必要な環境変数を設定することで機能します。 ターゲットオペレーティングシステムには変数GOOS
を使用し、ターゲットアーキテクチャにはGOARCH
を使用します。 実行可能ファイルを作成するには、コマンドは次の形式になります。
- env GOOS=target-OS GOARCH=target-architecture go build package-import-path
env
コマンドは、変更された環境でプログラムを実行します。 これにより、現在のコマンド実行にのみ環境変数を使用できます。 コマンドの実行後、変数は設定解除またはリセットされます。
次の表に、使用できるGOOS
とGOARCH
の可能な組み合わせを示します。
GOOS -ターゲットオペレーティングシステム |
GOARCH -ターゲットプラットフォーム |
---|---|
android |
arm |
darwin |
386 |
darwin |
amd64 |
darwin |
arm |
darwin |
arm64 |
dragonfly |
amd64 |
freebsd |
386 |
freebsd |
amd64 |
freebsd |
arm |
linux |
386 |
linux |
amd64 |
linux |
arm |
linux |
arm64 |
linux |
ppc64 |
linux |
ppc64le |
linux |
mips |
linux |
mipsle |
linux |
mips64 |
linux |
mips64le |
netbsd |
386 |
netbsd |
amd64 |
netbsd |
arm |
openbsd |
386 |
openbsd |
amd64 |
openbsd |
arm |
plan9 |
386 |
plan9 |
amd64 |
solaris |
amd64 |
windows |
386 |
windows |
amd64 |
警告: Android用の実行可能ファイルのクロスコンパイルには、 Android NDK と、このチュートリアルの範囲を超える追加のセットアップが必要です。
表の値を使用して、次のようにCaddy forWindows64ビットを構築できます。
- env GOOS=windows GOARCH=amd64 go build github.com/mholt/caddy/caddy
この場合も、操作が成功したことを示す出力はありません。 実行可能ファイルは、パッケージ名を名前として使用して、現在のディレクトリに作成されます。 ただし、この実行可能ファイルをWindows用にビルドしたため、名前は接尾辞.exe
で終わります。
現在のディレクトリにcaddy.exe
ファイルがあり、ls
コマンドで確認できます。
- ls caddy.exe
caddy.exe
ファイルが出力に表示されます。
Outputcaddy.exe
注:-o
フラグを使用して、実行可能ファイルの名前を変更したり、別の場所に配置したりできます。 ただし、Windows用の実行可能ファイルを作成して別の名前を付ける場合は、実行可能ファイルの名前を設定するときに、必ず.exe
サフィックスを明示的に指定してください。
複数のターゲット環境向けのソフトウェアをリリースしやすくするために、このプロセスのスクリプトを見てみましょう。
ステップ5—クロスコンパイルを自動化するスクリプトを作成する
多くのプラットフォームで実行可能ファイルを作成するプロセスは少し面倒ですが、スクリプトを作成して作業を簡単にすることができます。
スクリプトは、パッケージのインポートパスを引数として取り、オペレーティングシステムとプラットフォームのペアの事前定義されたリストを反復処理し、各ペアの実行可能ファイルを生成して、出力を現在のディレクトリに配置します。 各実行可能ファイルには、package-OS-architecture
の形式で、パッケージ名に続いてターゲットプラットフォームとアーキテクチャという名前が付けられます。 これは、あらゆるプロジェクトで使用できるユニバーサルスクリプトになります。
ホームディレクトリに切り替えて、テキストエディタでgo-executable-build.bash
という名前の新しいファイルを作成します。
- cd ~
- nano go-executable-build.bash
スクリプトはshebang行から始めます。 この行は、実行可能ファイルとして実行されるときにこのスクリプトを解析するインタープリターを定義します。 次の行を追加して、bash
がこのスクリプトを実行するように指定します。
#!/usr/bin/env bash
パッケージのインポートパスをコマンドライン引数として使用します。 これを行うには、$n
変数を使用します。ここで、n
は非負の数です。 変数$0
には実行したスクリプトの名前が含まれ、$1
以降にはユーザー指定の引数が含まれます。 この行をスクリプトに追加します。これにより、コマンドラインから最初の引数が取得され、package
という変数に格納されます。
...
package=$1
次に、ユーザーがこの値を指定したことを確認します。 値が指定されていない場合は、スクリプトの使用方法を説明するメッセージを表示してスクリプトを終了します。
...
if [[ -z "$package" ]]; then
echo "usage: $0 <package-name>"
exit 1
fi
このif
ステートメントは、$package
変数の値をチェックします。 設定されていない場合は、echo
を使用して正しい使用法を出力し、exit
を使用してスクリプトを終了します。 exit
は引数として戻り値を取ります。これは、実行が成功した場合は0
であり、実行が失敗した場合はゼロ以外の値である必要があります。 スクリプトが成功しなかったため、ここでは1
を使用します。
注:このスクリプトを事前定義されたパッケージで機能させる場合は、package
変数を変更してそのインポートパスを指すようにします。
...
package="github.com/user/hello"
次に、パスからパッケージ名を抽出します。 パッケージのインポートパスは/
文字で区切られ、パッケージ名はパスの最後にあります。 まず、/
を区切り文字として使用して、パッケージのインポートパスを配列に分割します。
package_split=(${package//\// })
パッケージ名は、この新しい$package_split
配列の最後の要素である必要があります。 Bashでは、負の配列インデックスを使用して、最初からではなく最後から配列にアクセスできます。 この行を追加して、配列からパッケージ名を取得し、package_name
という変数に格納します。
...
package_name=${package_split[-1]}
次に、実行可能ファイルをビルドするプラットフォームとアーキテクチャを決定する必要があります。 このチュートリアルでは、Windows 64ビット、Windows 32ビット、および64ビットmacOS用の実行可能ファイルを作成します。 これらのターゲットをOS/Platform
の形式で配列に配置するため、パッケージ名の抽出に使用したのと同じ方法を使用して、各ペアをGOOS
変数とGOARCH
変数に分割できます。パスから。 スクリプトにプラットフォームを追加します。
...
platforms=("windows/amd64" "windows/386" "darwin/amd64")
次に、プラットフォームの配列を反復処理し、各プラットフォームエントリをGOOS
およびGOARCH
環境変数の値に分割し、それらを使用して実行可能ファイルをビルドします。 これは、次のfor
ループで実行できます。
...
for platform in "${platforms[@]}"
do
...
done
platform
変数には、各反復でplatforms
配列からのエントリが含まれます。 platform
をGOOS
とGOARCH
の2つの変数に分割する必要があります。 for
ループに次の行を追加します。
for platform in "${platforms[@]}"
do
platform_split=(${platform//\// })
GOOS=${platform_split[0]}
GOARCH=${platform_split[1]}
done
次に、パッケージ名とOSおよびアーキテクチャを組み合わせて、実行可能ファイルの名前を生成します。 Windows用にビルドするときは、ファイル名に.exe
サフィックスを追加する必要もあります。 このコードをfor
ループに追加します。
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
キーワードのすぐ上に追加します。
...
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
キーワードの上に追加します。
...
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パッケージから複数の実行可能ファイルをビルドするスクリプトができました。 完成したスクリプトは次のとおりです。
#!/usr/bin/env bash
package=$1
if [[ -z "$package" ]]; then
echo "usage: $0 <package-name>"
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*
3つのバージョンすべてが表示されます。
Example ls outputcaddy-darwin-amd64 caddy-windows-386.exe caddy-windows-amd64.exe
ターゲットプラットフォームを変更するには、スクリプトのplatforms
変数を変更するだけです。
結論
このチュートリアルでは、Goのツールを使用してバージョン管理システムからパッケージを取得する方法と、さまざまなプラットフォーム用の実行可能ファイルをビルドおよびクロスコンパイルする方法を学習しました。
また、多くのプラットフォーム用に単一のパッケージをクロスコンパイルするために使用できるスクリプトを作成しました。
アプリケーションが正しく動作することを確認するには、テストおよびTravis-CIやAppVeyorなどの継続的インテグレーションをテスト用に確認できます。 Windowsの場合。
Caddyとその使用方法に興味がある場合は、 Ubuntu16.04でCaddyを使用してWebサイトをホストする方法を参照してください。