Golangはどのようにクロスプラットフォームの開発とテストを簡素化するのか

このチュートリアルでは、**Golang**がどのように**クロスプラットフォーム**の開発とテストを簡素化するかを探り、このサービスを利用するためのベストプラクティスを提供します。


[ Alibaba Cloud Community Blog ](https://www.alibabacloud.com/blog?spm=a2c65.11461447.0.0.38a82a97fdPRTj)著者Alex

アプリケーションを開発するために、開発者はOS X、Windows、またはLinuxが動作する自分のマシンを使用します。同時に、UbuntuやCentOSがインストールされたAlibaba CloudのECSインスタンスなど、海外のプラットフォームをテスト用に使用します。そのため、複数のプラットフォームで動作するバイナリを1つのシステムでコンパイルする機能が非常に求められています。Golangはこの問題に対する解決策を提供します。開発者は、多様なプラットフォームで動作するシステムを設計することができます。クロスコンパイルとも呼ばれるGolangは、クロスプラットフォームの開発者に多大なメリットをもたらします。この言語には、プラットフォームを超えた開発をサポートする多くの機能が組み込まれています。この記事では、開発プロセスの負担を軽減するためにそのようなソリューションをどのように使用するか、ベストプラクティスは何か、そしてGolangが新しいソリューションのテストやパッケージ配布をどのように促進するかを探ります。

#ベストプラクティス
まず最初に、クロスコンパイルを実現するための主要なベストプラクティスを簡単にご紹介します。

###インターフェイス
Goのインターフェース要件を満たすためには、すべてのオブジェクトは定義されたすべてのメソッドの実装を保証しなければなりません。そのため、異なるプラットフォームの2つのオブジェクトが別々に実装されていても、Goのインターフェースの要件を満たしていることになります。プラットフォーム固有のものはすべて、Goのインターフェイスの背後で抽象化することをお勧めします。

###ビルド制約
Goのビルド制約は、言語構造を使用してコンパイルされたファイルのプラットフォームを制御します。これには2つのタイプがあります。

- シンプルで柔軟性に欠けるファイルベースの制約
- 複雑で柔軟なto-of-file制約でのコメント


###OSとアーキテクチャ
ランタイムパッケージのGOOSとGOARCHの値を使って、実行時にOSとアーキテクチャの情報を得ます。次に、標準的な条件式を使用したものと、すでに判明している値を比較します。しかし、実行時のチェックは、エラーが発生する可能性が高くなるため、ほとんどの場合は役に立ちません。

#チュートリアルに必要なもの
チュートリアルを実行するには、以下の必要なものが必要です。

- Ubuntu 16.04がインストールされているAlibaba ECSインスタンス
- ファイアウォールとSudoの非rootユーザー
- システムにインストールされたGo

#特定のターゲットOS用にコンパイルする
Darwin/amd64やLinux/amd64などの特定のターゲット・オペレーティング・システム（OS）用に実行ファイルをコンパイルし、ローカル・マシン（このチュートリアルではMacBook）でこれらの実行ファイルをビルドします。実行ファイルをGitHubアカウントにエクスポートし、Alibaba CloudがホストするUbuntuサーバーにクローンします。

###Mac OS
ローカルのMacマシンでは、Darwin/amd64ターゲット用の実行ファイルをビルドします。Goがインストールされたら、以下のコマンドを実行してください。

```
cd src
GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 ./make.bash ¨Cno-clean
```

以下は、先のコマンドから予想される応答です。

```
Installed Go for darwin/amd64 in /Users/name/go
Installed commands in /Users/name/go/bin
```

このコマンドを実行すると、go、godoc、および gofmt ディレクトリにすべてのライブラリとツールが作成されます。以下のコマンドを実行して、ツールのPATHを作成します。

```
export PATH=$HOME/go/bin:$PATH
```

次のコマンドでGoの環境を確認します。

```
go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="linux"
GOPATH=""
GORACE=""
GOROOT="/Users/name/go"
GOTOOLDIR="/Users/name/go/pkg/tool/darwin_amd64"
CC="gcc"
GOGCCFLAGS="-g -O2 -fPIC -m64"
CGO_ENABLED="1"
```

以下のコマンドを実行して、Goのバージョンを確認します。

```
go version
go version go1.12.1 darwin/amd64
```

Goターゲットの設定時に発生する以下の想定されるエラーについては、[本ガイド](http://www.computersnyou.com/2025/2013/06/install-command-line-tools-in-osx-10-9-mavericks-how-to/?spm=a2c65.11461447.0.0.38a82a97fdPRTj)を参照してください。

```
crypto/x509 root_darwin.go:9:43: error: 
CoreFoundation/CoreFoundation.h: 
root_darwin.go:10:31: error: Security/Security.h: 
```

Goディレクトリを開くと、Goプログラムをビルドするために必要なすべてのツールが表示されます。このチュートリアルでは、Mac用の`darwin_amd64`フォルダを表示しています。


###Linux amd64
このステップでは、Linux/amd64で実行するための実行ファイルをコンパイルします。まず、以下のコマンドを実行してください。

```
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 ./make.bash ¨Cno-clean
```

`CGO_ENABLED`を0にしてクロスコンパイルを実施すると、以下のような出力が得られます。

```
Installed Go for linux/amd64 in /Users/name/go
Installed commands in /Users/name/go/bin
```

これで、binディレクトリとPKGディレクトリにLinux/amd64用の新しいフォルダができました。

#指定したターゲットへのビルド
以下の表を参考に、ターゲットOSを選択してください。

|$GOOS|	$GOARCH	||
|:-----------|------------:|:------------:|
|darwin|	386|	32-bit MacOSX|
|darwin|	amd64|	64-bit MacOSX|
|freebsd|	386	|
freebsd|	amd64	|
|linux|	386	|32 bit Linux|
|linux	|amd|	RISC Linux|
|netbsd|	386	|
|netbsd	|amd64|	
|openbsd|	386	|
|openbsd|	amd64	|
|plan9|	386	|
|windows|	386|	32 bit Windows|
|windows|	amd64|	64 bit Windows|


ここで、以下のコマンドを実行して、LinuxおよびUbuntu上で動作するプログラムをビルドします。

```
cd $HOME
mkdir example
```

以下のようにGOPATHを設定します。

```
export GOPATH=$HOME/example
cd example
mkdir src
cd src
mkdir simple
cd example/src/simple
```

次に、ディレクトリ内に`main.go`という名前の新規ファイルを以下の内容で作成します。

```
package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello World!")
}
```

ターミナルで以下のコマンドを実行して、Linux/amd64用の実行ファイルをビルドします。

```
export GOARCH="amd64"
export GOOS="linux"

go build
file simple

Simple: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
```

ターミナルで以下のコマンドを実行して、darwin/amd64の実行ファイルをビルドします。

```
go build
file simple

simple: Mach-O 64-bit executable x86_64
```

コマンド内のOS/ARCH変数を変更することで、異なるプラットフォームやアーキテクチャを選択することができます。ビルドが完了したら、対象のOS/ARCH変数に対応した実行ファイルを取得します。

#ターゲットプラットフォーム用のコンパイルの自動化
実行ファイルを複数のプラットフォームに展開するのは、非常に時間のかかる作業です。このプロセスを自動化するためのプログラムを書いてみましょう。スクリプトにはOSとプラットフォームのペアがあり、ディレクトリに実行ファイルを生成するものとします。

では、早速始めましょう。

以下のコマンドを実行して、ホームディレクトリに切り替えます。

```
cd ~
```

以下のコマンドを実行して、`auto-build.bash`という名前の新しいbashファイルを作成します。

```
nano auto-build.bash
```

プロセスが複雑にならないように、スクリプトに何が含まれている必要があるかを確認してから、速やかにコンパイルしてください。何をすべきかを理解すれば、このようなスクリプトを扱うのはとても簡単です。

まず、以下のコマンドでスクリプトを実行可能な状態にします。

```
auto-build.bash
#!/usr/bin/env bash
```


スクリプトの要件を以下のように考えます。

- コマンドライン引数として$n変数を使用し、インポートパスを指定します。0変数には実行されたスクリプトの名前があり、1変数にはユーザーが提供する引数があります。
- ユーザーが引数の値を提供することを強制します。それがないと実行することができません。
- 変数`$package`の値をチェックするIF文を使用します。
- 与えられたパスから / 文字で示されるパッケージの名前を抽出します。それを`$package_split`の配列に分割するとよいでしょう。
- スクリプトでは、さらに引数で対象となるOSやアーキテクチャを指定する必要があります。
- FORループでOSとアーキテクチャーの組み合わせごとに環境変数GOOSとGOARCHの引数を入れます。
- パッケージ名、OS、アーキテクチャを使って、FORループを使って実行ファイルの名前を生成します。
- スクリプトは、GO buildコマンドを使用して、FORループで実行ファイルを作成します。
- スクリプトは、ビルドエラーがないかエラーチェックを実行します。

上記の要件に基づいて、以下のスクリプトを参照してください。

```
auto-build.bash

#!/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" "linux/amd64" "linux/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 'We have encountered an error while executing! Aborting the process...'
        exit 1
    fi
done
```

上記のスクリプトでは、Windows 64-bit、32-bit、Linux 64-bit、Linux 32-bit用の実行ファイルをビルドすることができます。スクリプトの作成方法はいろいろありますが、変数や方法はほぼ同じです。では、以下のコマンドを実行して、実行可能な状態にします。

```
- chmod +x auto-build.bash
```

これで完成です。これで、実行ファイルをコンパイルするプロセスが自動化され、以下のコマンドで実行できるようになりました。

```
./auto-build.bash $GOPATH/
```

完成したプロセスの出力はないので、実行ファイルが正常に作成されたかどうかは、ISコマンドで判断してください。platforms変数でOSやアーキテクチャを自由に組み合わせて使用します。

#Goツール
選択したプラットフォームとアーキテクチャ用のGoプログラムをビルドした後、以下のコマンドを実行してGoツールをインストールします。

```
go get golang.org/x/tools/cmd/godoc
go get golang.org/x/tools/cmd/vet
go get golang.org/x/tools/cmd/goimports
go get golang.org/x/tools/cmd/gorename
go get golang.org/x/tools/cmd/oracle
go get golang.org/x/tools/cmd/gotype
go get github.com/golang/lint/golint
```

#結論
このチュートリアルでは、開発者がGoを使ってパッケージを扱い、異なるターゲット・プラットフォーム用に実行ファイルをクロスコンパイルする方法について説明しています。このチュートリアルでは、LinuxとWindowsのコンパイルプロセスを自動化するために、シンプルなスクリプトを使用して時間を節約し、効率を上げる方法を提案します。ソースからGoの実行ファイルをビルドする方法についての包括的な情報は、[Goのドキュメント](http://golang.org/doc/install/source?spm=a2c65.11461447.0.0.38a82a97fdPRTj)を参照してください。また、[gox](https://github.com/mitchellh/gox?spm=a2c65.11461447.0.0.38a82a97fdPRTj)というツールを使って、最小限の要件でさまざまなプラットフォーム用の実行ファイルをビルドしてみましょう。さて、早速ですが、Alibaba Cloud ECSにサブスクライブして、レッスンを始めましょう。

Alibaba Cloudのアカウントをお持ちではないですか？アカウントに登録すると、最大1200ドル相当の[40以上の製品を無料でお試し](https://account.alibabacloud.com/register/intl_register.htm?spm=a2c65.11461447.0.0.38a82a97fdPRTj)いただけます。[Get Started with Alibaba Cloud](https://account.alibabacloud.com/register/intl_register.htm?spm=a2c65.11461447.0.0.38a82a97fdPRTj)で詳細をご覧ください。


*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/golang-cross-compilation-on-alibaba-cloud_595773)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*