Linux
rust
embedded
arm64

クロスコンパイルを考慮したbindgenの使い方

先日の記事の続き。
RustでLinuxのinput eventをダンプする (bindgen使用)

ビルド時にbindgenするように変更

bindgen users guide のチュートリアルに従って、cargoでビルドするときにbindgenを実行するようにbuild.rsを作りました。
そのソースコードはgithubに置きました。

https://github.com/tetsu-koba/input_event_rs

クロスビルドに対応できるようにbuild.rs を修正

ARM64向けにクロスビルドするとbindgenでエラーが発生するようになりました。
クロスビルドのときには参照するシステムのヘッダファイルもそれに応じて変える必要がありますが、それがbindgenに伝わっていないのが原因です。

環境変数 SYSROOTが設定されている場合には、それを--sysroot=に反映させるようにbuild.rs を書き直しました。

build.rs
extern crate bindgen;

use std::env;
use std::path::PathBuf;

fn main() {
    let mut builder = bindgen::Builder::default().header("wrapper.h");
    if let Ok(r) = env::var("SYSROOT") {
        builder = builder.clang_arg(format!("--sysroot={}", r))
    };
    let bindings = builder.generate().expect("Unable to generate bindings");
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

build_arm64.shでは環境変数SYSROOT を設定するようにします。

build_arm64.sh
#!/bin/sh
TARGET=input_event
STRIP=aarch64-buildroot-linux-gnu-strip
export SYSROOT=/home/koba/arm64/buildroot-2018.05/output/host/usr/aarch64-buildroot-linux-gnu/sysroot/
export PKG_CONFIG_ALLOW_CROSS=1
cargo build --target aarch64-unknown-linux-gnu --release
cd target/aarch64-unknown-linux-gnu/release/
cp $TARGET ${TARGET}_g
$STRIP $TARGET

余談

build.rs に書くようなことは普通はshell scriptかMakefile に書くような気がします。
しかし、それらが一般的でないWindowsの環境でも統一しようとすると結局このようにRust自身で書くということになったのでしょうか。

関連

rustのcargoでarm64 linux向けにクロスビルドする