[Rust] 開発環境と実行環境が違う場合のビルド方法

2022.08.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

私の場合、主にM1 Macを使って開発しています。
先日Linux環境で動作させるRustプログラムを作成する必要があったので
開発環境構築まわりを調べたところ、
いくつかの方法があり、それぞれ試してみたので
それらの方法について紹介します。

ある程度の規模であればCIとか使ってちゃんとやるべきな気がしますが、
そこまでするほどでもない規模のものなので、
CIを使う以外のもう少しお手軽な方法を紹介してます。

Environment

  • OS : MacOS 12.4
  • Docker : 20.10.17
  • Rust : 1.62.1
  • IDE : VS Code 1.70.1

Mac(apple silicon)でRustコードを記述、
実行はLinux(x86)で行う想定です。

Build in various ways

EC2でビルド & Remote SSHで接続

わざわざローカルに環境つくるのが面倒くさいので、
実際にターゲット環境を作成し、VS CodeのRemote SSHを使って
ダイレクトにLinux上のRustコードをローカルのVSCodeで編集する方法。

ターゲット環境のEC2インスタンスを立てたら、↓のようにRust環境をインストールする。

# EC2へSSHログイン
% sudo apt install build-essential
% curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
・
・

そして、こことかにあるように、VSCodeの拡張機能をいれ、
EC2上のRustコードを直接編集する。ビルドはLinux上で実行する。
しかし少額とはいえ料金がかかるので注意。

Docker使ってコンテナ内でビルドする

社内できいたところ、Dockerでいいんじゃない?といわれたので。
platform指定してDockerを起動する方法です。
バインドマウントしたディレクトリにRustプロジェクトを作成しておき、
ローカルから編集してDocker内でビルドします。

# コンテナ起動
% mkdir share_data
% docker run -v $PWD/share_data:/share_data --platform linux/amd64 -it <IMAGE> /bin/bash

# コンテナにsshログインしてビルド環境構築
$ apt-get update
$ apt-get install curl
$ apt-get install gcc
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ export PATH=$PATH:~/.cargo/bin/

#Rustプログラム実行(すでにプロジェクトがある前提)
$ cd /path/your/share_data/<Rustプロジェクト>
$ cargo run ./target/debug/<app>

実際にビルドしてみると、なんか遅かった気がする。

ローカルでクロスコンパイル(cross使わない)

ローカルでLinux用にクロスコンパイルする方法です。
ターゲットのツールチェインをインストールしてconfigファイルを作成し、
cargo buildします。

% brew install SergioBenitez/osxct/x86_64-unknown-linux-gnu
% rustup target add x86_64-unknown-linux-gnu

プロジェクトの直下に.cargo/configファイルを作成。

[target.x86_64-unknown-linux-gnu]
linker = "x86_64-unknown-linux-gnu-gcc"

ローカルでクロスコンパイルします。

% cargo build --target x86_64-unknown-linux-gnu

↑と違ってビルドする場所がDockerからローカルにかわっただけなので、
生成したバイナリは先程のようにバインドマウントしてればそのままDockerで実行できます。

参考

ローカルでクロスコンパイル(cross使う)

cross(クロスコンパイルツール)をつかってローカルでクロスコンパイルする方法。
自分でtarget addとかしなくてもだいたいいい感じでビルドしてくれるので楽です。

cargo installでcrossをインストールしてcross buildするだけ。
とても簡単。

% cargo install cross
% cross build --target x86_64-unknown-linux-gnu

cross build時に関係ない.cargo/configがあると
失敗するかもしれないので注意。

UTMを使う

UTM(仮想化ツール)をつかってLinuxの仮想環境をつくって
そこでビルドする方法もあります。
Linux仮想環境を起動して、共有ディレクトリ使うなり
Remote SSHでつなぐなりすればDockerのときと同じく開発&実行可能です。
ですが、けっこう重かったりセットアップが少し大変だったりするので、
(今回の目的なら)Dockerで十分と思われます。

Summary

以上、Rustで開発・実行の環境が違う場合のビルドについて
いくつか方法を紹介しました。
実際やってみたところ、
crossインストールしてDockerのLinuxで動作確認させるのが一番簡単だと思われます。

References