Goでのクロスコンパイル応用：複数プラットフォーム向けにビルドする方法

## はじめに

Go言語は、クロスコンパイルの機能が充実しており、**1つのコードベースから複数のプラットフォーム向けにバイナリを生成**することができます。  
Windows, macOS, Linux, ARMなど、様々なOSやアーキテクチャ向けのアプリケーションを開発・配布する際に非常に便利です。


---

## クロスコンパイルとは？

**クロスコンパイル**とは、現在使用しているOSとは異なるプラットフォーム向けの実行ファイルを生成することを指します。

例：
- macOSでWindows用の実行ファイルをビルド
- LinuxでmacOS用のバイナリを作成
- x86マシンでARM用のバイナリを生成

GoはGOOS（ターゲットの OS）とGOARCH（ターゲットのアーキテクチャ）を指定するだけで、クロスコンパイルが可能です。

---

## クロスコンパイルの基本

**1. GOOSとGOARCHの組み合わせ**

Goで使用できるGOOSとGOARCHの組み合わせは以下の通りです。

| GOOS        | GOARCH      | 説明               |
|-------------|-------------|--------------------|
| `linux`     | `amd64`     | 64-bit Linux       |
| `linux`     | `arm64`     | 64-bit ARM Linux   |
| `darwin`    | `amd64`     | macOS x86_64       |
| `darwin`    | `arm64`     | macOS M1 (Apple Silicon) |
| `windows`   | `amd64`     | 64-bit Windows     |
| `windows`   | `386`       | 32-bit Windows     |

**2. クロスコンパイルの基本コマンド**

例えば、Linux用の64-bit実行ファイルをmacOSでビルドする場合は以下のように実行します。

```sh
GOOS=linux GOARCH=amd64 go build -o app-linux main.go
```

Windows用のバイナリを生成する場合：
```sh
GOOS=windows GOARCH=amd64 go build -o app.exe main.go
```

- `GOOS`：ターゲットの OS を指定
- `GOARCH`：ターゲットのアーキテクチャを指定
- `-o`：出力ファイルの名前を指定

---

## 応用：すべてのプラットフォーム向けにビルドする

**1. シェルスクリプトを使用した一括ビルド**

複数のプラットフォーム向けにバイナリを一括で生成するには、シェルスクリプトを使うと便利です。

**build.sh**
```sh
#!/bin/bash

platforms=(
  "windows/amd64"
  "linux/amd64"
  "linux/arm64"
  "darwin/amd64"
  "darwin/arm64"
)

for platform in "${platforms[@]}"
do
  GOOS=${platform%/*}
  GOARCH=${platform#*/}
  output_name='app-'$GOOS'-'$GOARCH
  if [ $GOOS = "windows" ]; then
    output_name+='.exe'
  fi
  
  echo "Building for $GOOS/$GOARCH..."
  env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name main.go
  if [ $? -ne 0 ]; then
    echo "An error has occurred! Aborting the script execution..."
    exit 1
  fi
done
```

**実行方法**
```sh
chmod +x build.sh
./build.sh
```

- GOOSとGOARCHをループで回し、複数のバイナリを生成
- output_nameをOSやアーキテクチャに応じて動的に設定
- エラーチェックを追加して、ビルド失敗時にスクリプトを中断

---

## 応用：CGO を使ったクロスコンパイル

GoはCGOを使用してC言語のライブラリを呼び出すことができますが、クロスコンパイルを行う場合には設定が必要です。

**1. CGOを無効化する**

まず、CGO_ENABLEDを0に設定して無効化することで、依存関係を排除します。

```sh
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app-linux main.go
```

**2. CGOを有効化してクロスコンパイル**

CGOを使用する場合、ターゲット環境のクロスコンパイラが必要です。

#### **例：macOS から Linux 用にビルドする**
```sh
brew install FiloSottile/musl-cross/musl-cross  # macOSの場合
```

```sh
CGO_ENABLED=1 CC=x86_64-linux-musl-gcc GOOS=linux GOARCH=amd64 go build -o app-linux main.go
```

- `CGO_ENABLED=1`：CGO を有効化
- `CC`：ターゲット環境に合わせたクロスコンパイラを指定

---

## CI/CD への組み込み

**1. GitHub Actions を使ったクロスコンパイル**

GitHub Actionsを使うことで、プッシュ時に自動でクロスコンパイルを実行できます。

**.github/workflows/build.yml**
```yaml
name: Build Cross-Platform Binaries

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        goos: [linux, windows, darwin]
        goarch: [amd64, arm64]
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Go
        uses: actions/setup-go@v2
        with:
          go-version: '1.19'

      - name: Build
        run: |
          GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go build -o app-${{ matrix.goos }}-${{ matrix.goarch }} main.go

      - name: Upload artifacts
        uses: actions/upload-artifact@v2
        with:
          name: binaries
          path: app-*
```

- `matrix` を使用して、複数のプラットフォームに対して並列にビルド
- バイナリをGitHub Actionsのartifactsとしてアップロード

---

## まとめ

| 項目 | 説明 |
|------|------|
| **GOOS と GOARCH** | ターゲットの OS とアーキテクチャを指定してクロスコンパイル |
| **CGO** | C 言語のライブラリを利用する場合、クロスコンパイラが必要 |
| **GitHub Actions** | CI/CD に組み込み、複数プラットフォームへのビルドを自動化 |

Goのクロスコンパイルを活用することで、マルチプラットフォームに対応したアプリケーションを効率よく開発・配布できます。