2022-06-07

EarthlyでRaspberryPi向けにビルドする

RaspberryPi向けのビルドとなると依存管理とかが面倒なのでmuslを使いたい。 GNU libcの方がパフォーマンス良いと言ってもRaspberyPiならパフォーマンスとか関係ないし。

ただhyperとかtokio::netとか使おうとするとopensslやらringやら(muslでビルドしようとするとaarch64-linux-musl-gccを要求される)が引っ付いてきて、 crossでは荷が重く、ローカルに構築するには依存が増えてローカルが汚染される。 Dockerのbuildxでマルチアーキなビルドが出来ることを利用してクロスコンパイルすると楽だが、やや目的外な雰囲気がある。

Earthlymake + Dockerといったソフトウェアで、MakefileっぽくDockerイメージのビルドを書ける上、 バイナリのコンパイルのようなDockerだとやや無理矢理感のある事も自然に書ける。VSCode向けのExtensionもある。

サンプルはこんな感じ。ほとんど公式サイトに載ってるexampleそのまんま。

Rustをビルドする時はからのmain.rsを作成してビルドしてからソースコードを運んできてビルドすることで依存を毎回ビルドするのをスキップ出来る。 ここではreqwestdefault-features=false, features=["rustls-webpki-roots"]を使ってopensslca-certificatesへの依存を追い出しているが、DockerなのでOpenSSLを持って来ればnative-tlsでのビルドも簡単。

FROM文でaarch64向けのイメージのDigestを指定してクロスコンパイルさせている。この例だとバイナリをそのまま出しているが、 大抵の場合はここからDockerイメージをビルドするだろう。

VERSION 0.6
FROM rust:latest@sha256:97fa23369c500e6b41bf9091b4af614e6728498c81a0c1717c73480085eefb9e
WORKDIR /work

all:
    BUILD +build

build:
    RUN mkdir src
    RUN echo "fn main(){}" > src/main.rs
    COPY Cargo.toml .
    COPY Cargo.lock .
    RUN apt-get update && apt-get install -y musl-dev musl-tools
    RUN ln -sf $(which musl-gcc) /usr/local/bin/aarch64-linux-musl-gcc
    RUN rustup target install aarch64-unknown-linux-musl
    RUN cargo build --release --target=aarch64-unknown-linux-musl

    COPY src src
    RUN cargo build --release --target=aarch64-unknown-linux-musl
    SAVE ARTIFACT target/aarch64-unknown-linux-musl/release/something-awesome AS LOCAL something-awesome