(失敗)Rustのクロスコンパイルcross用のdockerを自前で用意する(glibcバージョン対策)
結論
※現在、ほしいGlibcのバージョンのubuntu(21.10)はサポート外のため、断念しました。
素直にdocker hubでほしいコンテナ探して、そこでビルドしました。
要件
Rustのビルドを、 x86-64_linux_unknown_gnu ターゲットで行うとき、
その環境のglibcバージョンでバイナリが作成される。
cross の自動ビルドを
このとき、バイナリ実行に必要な条件として、
ビルド環境のglibcバージョン <= バイナリを実行する環境のglibc
である必要があるため、
開発環境のビルド環境が新しすぎたりすると、古い環境でバイナリ実行できないことがある。
また、利用しているcrateによっては、glibcのバージョンに制約がある場合があり、
ビルド環境のglibcバージョンを、明示的にセットしたいということがある。
方法として、
・dockerでその環境を作ってビルド
・クロスコンパイルツール"cross" 用に、docker imageを準備してそれを利用してビルドする
がある。
crossで用意されているバイナリは、一昔前のものが多いので、
例えばx86_64-unknown-linux-gnu は、libcバージョンは 2.31 となっている。
(このバージョンで良ければ、すでに用意されているものが使われるので、何もせずcross buildすればOK)
今回、libcのバージョン2.34が必要なので、
それを作るまでをメモしていきます。
参考記事
方針
crossで用意されているdocker fileを元に、glibcのバージョンを2.34のubuntuバージョンに書き換える
docker fileをチェック
crossが用意しているx86_64-unknown-linux-gnuのDockerfile
ubuntu21.10が、glibcのバージョン2.34なので、
ここを書き換える
FROM ubuntu:20.04 as cross-base
ENV DEBIAN_FRONTEND=noninteractive
↓
FROM ubuntu:21.10 as cross-base
ENV DEBIAN_FRONTEND=noninteractive
このファイルを保存する。
また、DockerFile内で利用しているファイルがいくつかあるので、あらかじめcrossのgithub上から
落としておく
Crossの設定をCross.tomlに記述
Cargo.tomlと同じ階層に、Cross.tomlを作成し、ターゲット別のビルドルールを記述する。
ここで、上記で保存したDockerFileのパスを指定
[target.x86_64-unknown-linux-gnu]
dockerfile = "./shells/DockerFile_glibc2.34.x86_64-unknown-linux-gnu"
dockerkitを入れる
crossは、Docker Buildx を使ってるので、環境にDocker buildkitが入ってない場合は事前に入れておく
#!/bin/bash
#
# https://docs.docker.com/build/buildkit/
# https://github.com/docker/buildx/releases/
# https://github.com/docker/buildx
## docker builder prune --all
## docker buildx du --verbose
## For Ubuntu 24.04 try: sudo apt install docker-buildx
## Or run the commands below.
#VERSION=v0.14.1
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/docker/buildx/releases/latest)
VERSION=${VERSION##*/}
mkdir -p $HOME/.docker/cli-plugins
wget https://github.com/docker/buildx/releases/download/$VERSION/buildx-$VERSION.linux-amd64 -O $HOME/.docker/cli-plugins/docker-buildx
chmod +x $HOME/.docker/cli-plugins/docker-buildx
export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1
echo 'export DOCKER_BUILDKIT=1' >> $HOME/.profile
echo 'export COMPOSE_DOCKER_CLI_BUILD=1' >> $HOME/.profile
crossのdockerから、一連のファイルを持ってきて、ローカルでbuildする
git clone --filter=blob:none --sparse https://github.com/cross-rs/cross.git
cd cross
git sparse-checkout set docker
# 結果、cross/docker ディレクトリだけがチェックアウトされる
# cross-toolchains も同様に(全体を取得したい場合は sparse-checkout は不要です)
cd docker
git clone --filter=blob:none https://github.com/cross-rs/cross-toolchains.git
#作成しておいたdockerFileをコピーし、それをビルド
cp ../../DockerFile_glibc2.34.x86_64-unknown-linux-gnu ./
docker build -t glibc2.34.x86_64-unknown-linux-gnu -f DockerFile_glibc2.34.x86_64-unknown-linux-gnu .
ここで、すでにサポートが切れていたubuntu:21.10は、apt-get apdateやautoconfでエラーが発生し、
進まなくなってしまった。。。
その前の20.04LTS は使えるのだが、Glibcのバージョンが古すぎて合わず・・・
この方法は断念。