Amazon Linux 2023上にRustのWindows向けクロスコンパイル環境を作ってみた

2023.07.20

初めに

以前CodeBuildのLinuxコンテナ上でWindows向けにクロスコンパイルする環境を作成しました。

上記記事ではAmazon Linuxベースのコンテナで解決できずUbuntuを利用しましたが、せっかくなのでAmazon Linux 2023のパターンでも作れる環境パターンを見てみたいなと思い試してみました。
(Amazon Linux 2の場合はamazon-linux-extrasからepelが導入可能で記載の手順で環境作成可能です)

なお今回はAmazon Linux 2023ベースのコンテナではなくAmazon Linux 2023を利用したEC2上での作業を行いますが、似たような処理を書き込めばコンテナ環境でも再現できるとは考えてます。

対応方法

Windows向けにクロスコンパイルするためにはcargo initで生成されたHello Worldのプログラムでも最低限mingw64-gcc,mingw-64-winpthreads-staticが必要となります。

残念ながらこれらのパッケージは2022/05/19時点(まだAmazon Linux 2022だった頃)の標準リポジトリには含まれていたのですが、2022/05/31のアップデート時点で消滅しており現在も再追加は行われていません。

この時点では含まれていた。

次のリリースノートでは消えていた。

https://docs.aws.amazon.com/ja_jp/linux/al2023/ug/relationship-to-fedora.html
The Generally Available (GA) version of AL2023 isn't directly comparable to any specific Fedora release. The AL2023 GA version includes components from Fedora 34, 35, and 36. Some of the components are the same as the components in Fedora and some are modified. Other components more closely resemble the components in CentOS 9 Streams or were developed independently. The Amazon Linux kernel is sourced from the long-term support options that are on kernel.org, chosen independently from Fedora.

ドキュメントを探してみるとAmazon Linux 2023はFedora 34~36やFedora34がベースとなっているCentOS Stream 9のコンポーネントが元となっているようです。

確認してみたところFedora 34の標準リポジトリにMinGW関連のパッケージは含まれているのでこちらか必要なパッケージを取得することで対応ができそうです。

注意点としてAmazon Linux 2023は完全にFedoraやCentOS Streamと同一ではなく動作が保証されるわけではないので予期せぬ動作を引き起こす可能性がある点を十分理解した上で自己責任で使う必要があります。

当然AWSからのサポートもないのでルール的にどうしてもAmazon Linux系以外が使えないという条件がなければ別のOSを選択するか、EOLが切れるまでであればAmazon Linux 2で対応するのが無難な選択肢とは思います。

設定

rpmを直接取得しインストールしてもいいですが依存関係の自力解決の手間なのでFedora 34のリポジトリからyum経由で取得できるようにします。

/etc/yum.repo.d/配下にfedora34.repoファイルを作成します。

設定値はDockerでfedora:34のコンテナを実行しそちらを参考に作成しています。

fedora34.repo

[fedora34]
name=Fedora 34 - $basearch
#baseurl=http://download.example/pub/fedora/linux/releases/$releasever/Everything/$basearch/os/
metalink=https://mirrors.fedoraproject.org/metalink?repo=fedora-34&arch=$basearch
enabled=1
countme=1
metadata_expire=7d
repo_gpgcheck=0
type=rpm
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-34-$basearch
skip_if_unavailable=False

[fedora34-updates]
name=Fedora 34 - $basearch - Updates
#baseurl=http://download.example/pub/fedora/linux/updates/$releasever/Everything/$basearch/
metalink=https://mirrors.fedoraproject.org/metalink?repo=updates-released-f34&arch=$basearch
enabled=1
countme=1
repo_gpgcheck=0
type=rpm
gpgcheck=1
metadata_expire=6h
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-34-$basearch
skip_if_unavailable=False

gpg鍵は以下より取得し配置しました。

fedora34側の設定だけ追加してなぜかNo packagesになる!と少しだけハマりましたがupdatesの方に含まれるようです。

# 手元のMAC環境のfedora:34条の実行結果(ARMプロセッサのためaarch64になっています)
$ yum install mingw64-gcc
Last metadata expiration check: 0:00:30 ago on Thu Jul 20 07:17:47 2023.
Dependencies resolved.
==============================================================================================================================================================================================================================================
 Package                                                            Architecture                                        Version                                                     Repository                                           Size
==============================================================================================================================================================================================================================================
Installing:
 mingw64-gcc                                                        aarch64                                             10.3.1-2.fc34                                               updates                                              20 M
Installing dependencies:
 dwz                                                                aarch64                                             0.14-1.fc34                                                 fedora                                              126 k
 efi-srpm-macros                                                    noarch                                              5-4.fc34                                                    updates                                              22 k
 file                                                               aarch64                                             5.39-7.fc34                                                 updates                                              50 k
 findutils                                                          aarch64                                             1:4.8.0-2.fc34                                              fedora                                              547 k
 fonts-srpm-macros                                                  noarch                                              1:2.0.5-5.fc34                                              fedora                                               27 k
 fpc-srpm-macros                                                    noarch                                              1.3-3.fc34                                                  fedora                                              7.7 k

インストール

ここまで来たらあとは追加したリポジトリを利用してyum(dnf)でインストールするだけです。

$ sudo yum install -y mingw64-{gcc,winpthreads-static} --enablerepo=fedora34{,-updates}
Last metadata expiration check: 0:01:48 ago on Thu Jul 20 07:36:53 2023.
Dependencies resolved.
==============================================================================================================================================================================
 Package                                           Architecture                  Version                                        Repository                               Size
==============================================================================================================================================================================
Installing:
 mingw64-gcc                                       x86_64                        10.3.1-2.fc34                                  fedora34-updates                         20 M
 mingw64-winpthreads-static                        noarch                        8.0.0-2.fc34                                   fedora34                                 31 k
Installing dependencies:
 isl                                               x86_64                        0.16.1-13.amzn2023.0.3                         amazonlinux                             872 k
 mingw-binutils-generic                            x86_64                        2.34-11.fc34                                   fedora34-updates                        1.0 M
 mingw-filesystem-base                             noarch                        118-1.fc34                                     fedora34-updates                         20 k
 mingw64-binutils                                  x86_64                        2.34-11.fc34                                   fedora34-updates                        2.4 M
 mingw64-cpp                                       x86_64                        10.3.1-2.fc34                                  fedora34-updates                        8.3 M
 mingw64-crt                                       noarch                        8.0.0-2.fc34                                   fedora34                                2.7 M
 mingw64-filesystem                                noarch                        118-1.fc34                                     fedora34-updates                        152 k
 mingw64-headers                                   noarch                        8.0.0-2.fc34                                   fedora34                                4.9 M
 mingw64-winpthreads                               noarch                        8.0.0-2.fc34                                   fedora34                                 48 k

Transaction Summary
==============================================================================================================================================================================
Install  11 Packages

...

Rust側の環境もセットアップしておきます。

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
...
$ source $HOME/.cargo/env
$ rustup target add x86_64-pc-windows-gnu
...

コンパイル

cargo initでサンプルプロジェクトを作りその中でx86_64-pc-windows-gnu向けにコンパイルを行ったところ無事Windows向けのバイナリが生成されていることを確認できました。

$ mkdir sample-rust-prj && cd sample-rust-prj && cargo init
     Created binary (application) package
$ cargo build --release --target x86_64-pc-windows-gnu
   Compiling sample-rust-prj v0.1.0 (/root/sample-rust-prj)
    Finished release [optimized] target(s) in 0.81s
# Windows向けバイナリなのでLinux上で実行すると当然失敗する
$ cargo run --release --target x86_64-pc-windows-gnu
    Finished release [optimized] target(s) in 0.00s
     Running `target/x86_64-pc-windows-gnu/release/sample-rust-prj.exe`
target/x86_64-pc-windows-gnu/release/sample-rust-prj.exe: target/x86_64-pc-windows-gnu/release/sample-rust-prj.exe: cannot execute binary file

終わりに

Amazon Linux 2023になってからEPELも利用できず標準リポジトリからもMinGW関連のパッケージが消えてしまっている状態ですが、なんとか入れ込んでWindows向けのクロスコンパイル環境を作ることができました。

まだAmazon Linux 2がEOL未到来のためそちらを使い続けることは可能ですが、到来までに何かしらの対応がない場合は今回のような方法を取るか別のOSを選択する形になってくるのではないかと思います。

今回はFedoraのリポジトリからパッケージを取得しインストールしていますが、Amazon Linux 2023はあくまで近いものであり同一ではない関係で動作は保証されるものではないですし、なんらか不具合が出る可能性も考慮すると決してリスクが低いと言えるものではないためもし利用する方はそれを踏まえた上で自己責任にて利用いただくようにご注意ください。