最近話題のrustを自分でも勉強しようと思って。
rustのインストール
このページに書いてあることをなぞる。
curl https://sh.rustup.rs -sSf | sh
一度ログアウトして再度ログイン。
$ rustc --version
rustc 1.25.0 (84203cac6 2018-03-25)
mkdir hello_world
cd hello_world
hello_world.rs を作成。
hello_world.rs
fn main() {
println!("Hello, world!");
}
コンパイルして実行。
$ rustc hello_world.rs
$ ./hello_world
Hello, world!
$ file ./hello_world
./hello_world: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9671f9cd6d9b1bb7b84022bde4d26af80fe992f4, not stripped
$ ls -lh ./hello_world
-rwxrwxr-x 1 koba koba 4.5M Apr 30 07:41 ./hello_world
ダイナミックリンクなのに、かなりサイズが大きいな。
クロスコンパイルの準備
rustのコンパイラはLLVMベースで構成されていて、いろいろなターゲットを切り換えることができます。追加可能なターゲットの一覧は以下の通り。
$ rustup target list
aarch64-apple-ios
aarch64-linux-android
aarch64-unknown-cloudabi
aarch64-unknown-fuchsia
aarch64-unknown-linux-gnu
aarch64-unknown-linux-musl
arm-linux-androideabi
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf
arm-unknown-linux-musleabi
arm-unknown-linux-musleabihf
armv5te-unknown-linux-gnueabi
armv7-apple-ios
armv7-linux-androideabi
armv7-unknown-cloudabi-eabihf
armv7-unknown-linux-gnueabihf
armv7-unknown-linux-musleabihf
armv7s-apple-ios
asmjs-unknown-emscripten
i386-apple-ios
i586-pc-windows-msvc
i586-unknown-linux-gnu
i586-unknown-linux-musl
i686-apple-darwin
i686-linux-android
i686-pc-windows-gnu
i686-pc-windows-msvc
i686-unknown-cloudabi
i686-unknown-freebsd
i686-unknown-linux-gnu
i686-unknown-linux-musl
mips-unknown-linux-gnu
mips-unknown-linux-musl
mips64-unknown-linux-gnuabi64
mips64el-unknown-linux-gnuabi64
mipsel-unknown-linux-gnu
mipsel-unknown-linux-musl
powerpc-unknown-linux-gnu
powerpc64-unknown-linux-gnu
powerpc64le-unknown-linux-gnu
s390x-unknown-linux-gnu
sparc64-unknown-linux-gnu
sparcv9-sun-solaris
wasm32-unknown-emscripten
wasm32-unknown-unknown
x86_64-apple-darwin
x86_64-apple-ios
x86_64-linux-android
x86_64-pc-windows-gnu
x86_64-pc-windows-msvc
x86_64-rumprun-netbsd
x86_64-sun-solaris
x86_64-unknown-cloudabi
x86_64-unknown-freebsd
x86_64-unknown-fuchsia
x86_64-unknown-linux-gnu (default)
x86_64-unknown-linux-gnux32
x86_64-unknown-linux-musl
x86_64-unknown-netbsd
x86_64-unknown-redox
armv7-unknown-linux-gnueabihf に必要なものを追加でインストール。
$ rustup target add armv7-unknown-linux-gnueabihf
info: downloading component 'rust-std' for 'armv7-unknown-linux-gnueabihf'
39.6 MiB / 39.6 MiB (100 %) 8.3 MiB/s ETA: 0 s
info: installing component 'rust-std' for 'armv7-unknown-linux-gnueabihf'
リンカーとしてクロスのgccを使用するので、以下の記事に従ってインストール。
x86_64のUbuntuでC/C++のソースコードをARM/ARM64用にクロスコンパイルしてQEMUで実行する方法のまとめ
クロスコンパイルと実行
以下のようにオプションを指定するとarm用にクロスコンパイルできます。
$ rustc -C linker=arm-linux-gnueabihf-gcc --target=armv7-unknown-linux-gnueabihf hello_world.rs
$ file ./hello_world
./hello_world: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=359e7216dc873f9b567c030dde53f825ee07c290, not stripped
$ ls -lh ./hello_world
-rwxrwxr-x 1 koba koba 4.0M Apr 30 07:50 ./hello_world
QEMUをセットアップしてあるので、この実行ファイルはそのまま実行可能です。
$ ./hello_world
Hello, world!
追記:stripしてみた
実行ファイルのサイズがとても大きいことが気になったのですが、コメントで教えてもらったことを参考に、stripコマンドでシンボル情報を除去してみました。
$ file ./hello_world
./hello_world: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=359e7216dc873f9b567c030dde53f825ee07c290, not stripped
$ cp ./hello_world hello_world_g
$ arm-linux-gnueabihf-strip ./hello_world
$ ls -lh hello_world*
-rwxrwxr-x 1 koba koba 330K Apr 30 11:09 hello_world
-rwxrwxr-x 1 koba koba 4.0M Apr 30 11:09 hello_world_g
-rw-rw-r-- 1 koba koba 46 Apr 30 07:40 hello_world.rs
1/10以下に小さくなりました。実機にはstrip済みの実行ファイルをインストールします。