前書き
Go programming languageには、パッケージの取得と実行可能ファイルの構築を非常に簡単にする豊富なツールチェーンが付属しています。 Goの最も強力な機能の1つは、Goでサポートされている任意の外部プラットフォームの実行可能ファイルをクロスビルドできることです。 これにより、パッケージを配布するために特定のプラットフォームにアクセスする必要がないため、テストとパッケージの配布がはるかに簡単になります。
このチュートリアルでは、Goのツールを使用してバージョン管理からパッケージを取得し、その実行可能ファイルを自動的にインストールします。 次に、実行可能ファイルを手動でビルドしてインストールし、プロセスに精通できるようにします。 次に、異なるアーキテクチャ用の実行可能ファイルをビルドし、ビルドプロセスを自動化して複数のプラットフォーム用の実行可能ファイルを作成します。 完了したら、WindowsとmacOS、およびサポートする他のプラットフォーム用の実行可能ファイルを作成する方法がわかります。
前提条件
このチュートリアルを実行するには、次のものが必要です。
-
sudo非rootユーザーとファイアウォールを含むthe Ubuntu 16.04 initial server setup guideをフォローしてセットアップされた1つのUbuntu16.04サーバー。
-
How to Install Go 1.6 on Ubuntu 16.04で説明されているように、インストールします。
[[step-1 -—- installing-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
にパッケージとその依存関係を取得するか、それらの依存関係がすでにマシンに存在する場合はそれらを更新するように指示します。
このチュートリアルでは、Goで記述されたWebサーバーであるCaddyをインストールします。 Caddy’s instructionsxごとに、パッケージのインポートパスに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
[。注意]##
Note:go get
コマンドは、Gitリポジトリのデフォルトブランチ(多くの場合、master
または開発中のブランチ)からパッケージをインストールします。 go get
を使用する前に、通常はリポジトリのREADME
ファイルにある手順を確認してください。
git checkout
などのGitコマンドを使用して、go get
コマンドを使用して取得したソースで別のブランチを選択できます。 ブランチを切り替える方法の詳細については、チュートリアルHow to Use Git Branchesを確認してください。
Goパッケージのインストールプロセスを詳しく見てみましょう。まず、既に入手したパッケージから実行可能ファイルを作成します。
[[step-2 -—- building-an-executable]] ==ステップ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
ディレクトリも作成します。
では、実行可能ファイルのインストールを見てみましょう。
[[step-3 -—- installing-an-executable]] ==ステップ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つである他のターゲットプラットフォーム用の実行可能ファイルの作成について見ていきましょう。
[[step-4 -—- building-executables-for-different-architectures]] ==ステップ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と、このチュートリアルの範囲を超える追加のセットアップが必要です。
表の値を使用して、次のようにWindows 64ビット用のCaddyを構築できます。
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]}
次に、実行可能ファイルを構築するプラットフォームとアーキテクチャを決定する必要があります。 このチュートリアルでは、Windows 64ビット、Windows 32ビット、および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
を2つの変数(GOOS
とGOARCH
)に分割する必要があります。 次の行をfor
ループに追加します。
go-executable-build.bash
for platform in "${platforms[@]}"
do
platform_split=(${platform//\// })
GOOS=${platform_split[0]}
GOARCH=${platform_split[1]}
done
次に、パッケージ名とOSおよびアーキテクチャを組み合わせて、実行可能ファイルの名前を生成します。 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*
3つのバージョンがすべて表示されるはずです。
Example ls outputcaddy-darwin-amd64 caddy-windows-386.exe caddy-windows-amd64.exe
ターゲットプラットフォームを変更するには、スクリプトのplatforms
変数を変更するだけです。
結論
このチュートリアルでは、Goのツールを使用してバージョン管理システムからパッケージを取得する方法と、さまざまなプラットフォーム用の実行可能ファイルをビルドおよびクロスコンパイルする方法を学びました。
また、多くのプラットフォームで単一のパッケージをクロスコンパイルするために使用できるスクリプトを作成しました。
アプリケーションが正しく機能することを確認するために、WindowsでテストするためにTravis-CIやAppVeyorのようなtestingとcontinuous integrationを調べることができます。
キャディとその使用方法に興味がある場合は、How to Host a Website with Caddy on Ubuntu 16.04をご覧ください。