はじめに (対象読者・この記事でわかること)

この記事は、WindowsマシンでGo言語を使ってSQLiteを扱うアプリケーションを開発し、本番のLinuxサーバーにデプロイしたい方を対象にしています。Goは単一バイナリでデプロイできる便利さが魅力ですが、SQLiteを使うとCGOという壁に遭遇します。本記事では、Windows上で開発しながらLinux向けのバイナリを生成する手順と、CGO有効でクロスコンパイルする際の注意点を実践的に解説します。読み終えると、ローカルWindows環境でLinux用のSQLite連携Goアプリをビルドできるようになります。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 - Goの基本文法とモジュール管理(go mod) - コマンドプロンプトまたはPowerShellの基礎操作 - Linuxサーバーへのファイル転送方法(scp, rsync, FTPなど)

WindowsでSQLite+Go開発が面倒な理由

Goは標準でクロスコンパイルに対応しており、Windows上でGOOS=linux go buildとするだけでLinux向けバイナリが生成できます。しかしSQLiteはC言語で書かれたライブラリを内部で利用しており、CGO(C言語とのインターフェース)を有効にする必要があります。CGO有効時、ビルドに必要なのはGoだけでなく、対象OS・CPUアーキテクチャ用のCコンパイラと、SQLiteの静的ライブラリです。Windows上でLinux向けのこれらを揃えるには、gccのクロスコンパイル版であるx86_64-w64-mingw32-gccか、Docker・WSL2などのLinux互換環境を使うのが一般的です。本記事ではツール導入が最小で済む「zig cc」アプローチを紹介します。

実践:zig ccでCGO有効クロスビルドする

ここが記事のメインパートです。具体的な手順とコードを交えて解説します。

環境準備(zig cc導入)

  1. Zig公式からWindows用のzipを落とし、適当なフォルダ(例:C:\zig)に展開
  2. 環境変数PATHにC:\zigを追加
  3. PowerShellでzig versionが表示されることを確認

PowerShell

> zig version
0.13.0
  1. Go 1.21以上をインストール済みであること(go versionで確認)

サンプルプロジェクト作成

適当なディレクトリで以下を実行:

PowerShell

> mkdir go-sqlite-xbuild && cd go-sqlite-xbuild
> go mod init example.com/app

main.go

Go
package main import ( "database/sql" "log" _ "github.com/mattn/go-sqlite3" ) func main() { db, err := sql.Open("sqlite3", "./foo.db") if err != nil { log.Fatal(err) } defer db.Close() if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS config( key TEXT PRIMARY KEY, value TEXT );`); err != nil { log.Fatal(err) } log.Println("SQLite初期化完了") }

依存解決:

> go mod tidy

クロスコンパイル実行

zig ccをCコンパイラとして使うため、環境変数を与えてビルド:

PowerShell

$env:CGO_ENABLED="1"
$env:CC="zig cc -target x86_64-linux"
$env:CXX="zig c++ -target x86_64-linux"
$env:GOOS="linux"
$env:GOARCH="amd64"
go build -o app-linux.exe

成功するとapp-linux.exe(名前は任意)が生成。Linuxマシンに持っていて実行権与えれば動きます。

ハマった点とエラー解決

エラー1: gcc not found

現象:go build時にgcc: command not foundと出る
原因:CGO有効時、Goはデフォルトでgccコマンドを探す
解決:前述の通りCC環境変数でzig ccを明示

エラー2: undefined: sqlite3.Open

現象:ビルドは通るが、実行時にundefined: sqlite3.Openなどのリンクエラー
原因:SQLiteのコードが含まれていない
解決:-tags sqlite3を付けて静的リンクするか、環境変数CGO_CFLAGS="-DSQLITE_ENABLE_COLUMN_METADATA"で再ビルド

エラー3: Linux上でno such file or directory

現象:バイナリをコピーして実行しても上記メッセージ
原因:動的リンク先のインタプリタが存在しない(glibcのバージョン差など)
解決:zig ccはデフォルトで静的リンクを試みるが、念のため以下を追加:

$env:CGO_LDFLAGS="-static"

で完全静的リンクを強制

ビルド高速化&CI対応

zig ccは初回のみLLVMビルドで時間がかかるため、CI環境でキャッシュするとよいです。GitHub Actions例:

yaml

- uses: actions/setup-go@v5
  with:
    go-version: '1.21'
- run: |
    Invoke-WebRequest -Uri https://ziglang.org/download/0.13.0/zig-windows-x86_64-0.13.0.zip -OutFile zig.zip
    7z x zig.zip -oc:\ -bb0
    echo "c:\zig" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- run: go build -v -o app-linux
  env:
    CGO_ENABLED: 1
    CC: zig cc -target x86_64-linux
    CXX: zig c++ -target x86_64-linux
    GOOS: linux
    GOARCH: amd64
    CGO_LDFLAGS: -static

まとめ

本記事では、Windows上でGo+SQLiteアプリを開発し、zig ccを使ってLinux向けにクロスコンパイルする手順を解説しました。

  • CGO有効時でもzig cc一つでLinux用バイナリが作れる
  • 環境変数CC/CXX/GOOS/GOARCHを揃えるだけでOK
  • 静的リンクにすることで、サーバー側のlibcのバージョンを気にしなくて済む

この記事を通して、Windowsマシンで開発しながら、手元でLinux用バイナリが生成できる環境が整いました。次は、生成したバイナリをDockerイメージに入れて、より軽量な配布方法を検討してみてください。

参考資料