はじめに
備忘用。
Rustで記述されたHello Worldを出力するだけのコードを、WSLでコンパイルし、Windows向けのバイナリを生成する手順を記します。
手順
前提
環境はWSL2(Ubuntu 22.04)を使用しました。
rustupのインストール
公式1より、WSL内で以下を実行します。
> curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
以下が通れば、インストール成功です。
> rustup -v
(省略)
rustup 1.27.1 (54dd3d00f 2024-04-24)
(省略)
Hello Worldプロジェクトの作成
ここでは、test_rust
ディレクトリにプロジェクトを新規作成します。
> mkdir test_rust
> cd test_rust
> cargo init
上記の実行によって生成されるtest_rust/src/main.rs
の内容は以下の通りです。(既にHello Worldを出力するようなコードとなっているため、特に修正しません。)
fn main() {
println!("Hello, world!");
}
crossのインストール
クロスコンパイルには、cross2を利用します。
以下のようにして、インストールをします。
> cargo install cross
dockerのインストール
crossを使うためには、コンテナエンジン(DockerかPodman)をインストールしておく必要があるとのこと。
今回利用しているディストリビューションはUbuntuなので、Dockerの公式docのUbuntuへのインストール手順3を参照しインストールをしました。
なお、自分の環境では、Dockerデーモンが起動していなかったので、以下で起動しておきました。
> sudo service docker start
Windows用のバイナリを生成
crossを使えば、Cargoプロジェクト配下(今回でいうtest_rust/
配下)で以下を実行するだけで、Windows用のバイナリを生成できます。
(具体的には、test_rust/target/x86_64-pc-windows-gnu/debug/test_rust.exe
が生成されます。)
> cross build --target x86_64-pc-windows-gnu
--target
オプションには、デフォルトで利用可能だったx86_64-pc-windows-gnu
を指定しました。他にも、x86_64-pc-windows-msvc
などが指定可能だったりします(rustup target list
でtargetに指定可能なリストを確認できます)。
cargo build
と同様に、--release
オプションも指定可能です。以下を実行することで、test_rust/target/x86_64-pc-windows-gnu/release/test_rust.exe
が生成されます。
> cross build --target x86_64-pc-windows-gnu --release
(参考)ターゲットにx86_64-pc-windows-msvcを指定する
cross build
の際、--target
にx86_64-pc-windows-msvc
を指定すると、エラーが発生します。以下に、エラーメッセージの抜粋を示します。
= note: the `x86_64-pc-windows-msvc` target may not be installed
= help: consider downloading the target with `rustup target add x86_64-pc-windows-msvc`
要は、インストールされていないとのこと。メッセージにあるrustup target add x86_64-pc-windows-msvc
を実行した後、再度cross build
を実行してもエラーとなります。そのエラーメッセージには以下が書かれていました。
[cross] warning: `cross` does not provide a Docker image for target x86_64-pc-windows-msvc, specify a custom image in `Cross.toml`.
つまり、x86_64-pc-windows-msvc
用のDockerイメージが無いとのことなので、イメージを作成する必要がありそうです。
そこで、crossのREADME4を確認すると、以下のような記載がありました。
Additional Dockerfiles for other targets can be found in cross-toolchains. These include MSVC and Apple Darwin targets, which we cannot ship pre-built images of.
そこで、cross-toolchains5を使って、イメージをビルドします。READMEに従って、イメージを作成します。具体的なコマンドは以下の通り。
# 適当なディレクトリに移動
> cd ~/workspace
# クローン&サブモジュール化
> git clone https://github.com/cross-rs/cross
> cd cross
> git submodule update --init --remote
# crosstoolイメージ用の設定
> cargo xtask configure-crosstool
# イメージのビルド
> cargo build-docker-image x86_64-pc-windows-msvc-cross --tag local
なお、自分が実行した際、ビルド時に以下のようなエラーが出ましたが、同様の事象を扱った記事6を参考にさせていただき、~/.docker/config.json
を修正して、解決しました(謎)。
ERROR: failed to solve: ubuntu:20.04: failed to resolve source metadata for docker.io/library/ubuntu:20.04: error getting credentials - err: exec: "docker-credential-desktop.exe": executable file not found in $PATH, out: ``
次に、test_rust
配下にCross.toml
を作成し、以下を記述します。
[target.x86_64-pc-windows-msvc]
image = "ghcr.io/cross-rs/x86_64-pc-windows-msvc-cross:local"
そして、以下を実行することで、test_rust/target/x86_64-pc-windows-msvc/debug/test_rust.exe
が生成されます。
> cross build --target x86_64-pc-windows-msvc
なお、x86_64-pc-windows-msvc
とx86_64-pc-windows-gnu
の違いは、いくつかの記事やスレッド7で触れられたりしています。
-
https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository ↩
-
https://github.com/cross-rs/cross?tab=readme-ov-file#supported-targets ↩
-
https://www.reddit.com/r/rust/comments/a63dlt/comment/ebrbi8d/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button によると、ビルドにMinGWを利用するのが
gnu
、Visual Studio Build Toolsを使うのがmsvc
とのこと。他にも、https://github.com/sharkdp/fd/issues/726 や https://users.rust-lang.org/t/x86-64-pc-windows-gnu-and-x86-64-pc-windows-msvc-abi-compatibility/117236 などで両者の違いについて触れられている。 ↩