昨日、Mac環境でRubyのネイティブ拡張を作る記事を投稿したが、WindowsとLinuxでも動く設定が確認できた。
構成
基本は前回と同じ。
まず変わったのは build.rs
で、ライブラリ名もRubyのコンフィグからWin, Mac, Linux共通の値が取得できた。
build.rs
use std::process::Command;
fn rb_config(key: &str) -> String {
let output = Command::new("ruby")
.args(&["-e", &format!("print RbConfig::CONFIG['{}']", key)])
.output()
.expect("failed run ruby");
return String::from_utf8(output.stdout).unwrap();
}
fn main() {
println!("cargo:rustc-link-search={}", rb_config("libdir"));
println!("cargo:rustc-link-lib={}", rb_config("RUBY_SO_NAME"));
}
次が Rakefile
で、Windowsでも動かしやすいようにMakefileから変更した。
RustがサポートするWindows環境はmingwとmsvcがあるが、mingwを強制している。
Rakefile
require 'fileutils'
require 'json'
NAME = JSON.parse(`cargo metadata --format-version=1`).dig("packages", 0, "name")
TARGET_SO = "#{NAME}.#{RbConfig::CONFIG["DLEXT"]}"
desc "Delete artifacts"
task :clean do
sh "cargo clean"
FileUtils.rm_f(TARGET_SO)
end
desc "Create native extension"
task :build do
env = {}
case RUBY_PLATFORM
when /mingw/
env = {"RUSTUP_TOOLCHAIN" => "stable-#{RbConfig::CONFIG["host_cpu"]}-pc-windows-gnu"}
cargo_out = "target/release/#{NAME}.dll"
when /darwin/
cargo_out = "target/release/lib#{NAME}.dylib"
when /linux/
cargo_out = "target/release/lib#{NAME}.so"
else
raise "Platform #{RUBY_PLATFORM} is not supported"
end
sh env, "cargo build --release"
cp cargo_out, TARGET_SO, preserve: true, verbose: true
end
desc "Run Ruby script"
task :run => [:clean, :build] do
ruby "run.rb"
end
他は変更なし
今後
gemとして公開するには gemspec 等が必要なので今後調べていくつもり。