🦔

Rust/GoアプリケーションのAWS Lambda向けクロスビルド方法

に公開

概要

前回はPythonのデプロイパッケージのクロスビルドを紹介しました。
https://zenn.dev/lucidfrontier45/articles/dd38e25209ebca

今回はRustとGoについて、主にLinux向けのクロスビルド方法をまとめます。

これでAWS Lambda向けの開発がはかどりますね。

Rust

Rustのtoolchainに含まれるコンパイラのrustc自体は様々なターゲット向けにコンパイルすることができますが、linkerを含んでいないのとCに依存したRustのライブラリの時にやはりCのコンパイラが必要になるのでRustのtoolchainだけでは完結しません。Linux向けのクロスビルドの環境を構築する最も簡単な方法はZigを使用することです。といってもZig言語とは全く関係なく、もっぱらZigにCのtoolchainを利用するのがポイントになります。Zigに含まれるzigコマンドはCのコンパイラやリンカーとしても使用でき、さらに様々なターゲット向けのヘッダーファイルも含んでいるのです。

https://actually.fyi/posts/zig-makes-rust-cross-compilation-just-work/

そしてZigをRustのinnkerやCのコンパイラとしてCargoに統合する拡張がcargo-zigbuildです。

https://github.com/rust-cross/cargo-zigbuild

クロスビルドの環境構築と実際の手順をまとめると以下の通りになります。

  1. Rustのtargetを追加する rustup target add [x86_64|aarch64]-unknown-linux-[gnu|musl]
  2. Zigを公式サイトからダウンロードしてPATHを通す。
  3. cargo-zigbuildをGitHubのリリースページからダウンロードしてPATHを通す。
  4. cargo zigbuild --release --target x86_64|aarch64]-unknown-linux-[gnu|musl]

Go

GoはRustとは異なり、toolchain自体にlinkerも含んでいますので大抵は

GOOS=linux GOARCH=[amd64|arm64] go build

で事足りますが、一部のDBのドライバーなど一部のライブラリはCを含んでいてCGO_ENABLED=1を指定する必要があります。そしてこの時にはCのコンパイラとlinkerが必要になってきます。ここでも最も簡単な方法はZigを利用することです。

https://dev.to/kristoff/zig-makes-go-cross-compilation-just-work-29ho

https://zig.news/kristoff/building-sqlite-with-cgo-for-every-os-4cic

上記の記事をまとめますと手順としてはRustの時と同様にZigをインストールし、

CGO_ENABLED=1 GOOS=linux GOARCH=[amd64|arm64] CC='zig cc -target [x86_64|aarch64]-linux-[gnu|musl]' go build

とするだけです。いくつかの記事ではmuslを使用する場合にはさらに-ldflags='-linkmode=external'が必要と書かれてありますが、私がgo1.25.1で試した限りではおそらくautoになっているのか必要な場合には自動的にlinkmode=externalになってextldにzig cc -target ..が入っていました。もちろんlinkmode=internalを明示的に指定するとエラーになります。

Discussion