はじめに (対象読者・この記事でわかること)
この記事は、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導入)
- Zig公式からWindows用のzipを落とし、適当なフォルダ(例:
C:\zig)に展開 - 環境変数PATHに
C:\zigを追加 - PowerShellで
zig versionが表示されることを確認
PowerShell
> zig version
0.13.0
- Go 1.21以上をインストール済みであること(
go versionで確認)
サンプルプロジェクト作成
適当なディレクトリで以下を実行:
PowerShell
> mkdir go-sqlite-xbuild && cd go-sqlite-xbuild
> go mod init example.com/app
main.go
Gopackage 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イメージに入れて、より軽量な配布方法を検討してみてください。
参考資料
