Yesterday, I posted Article on making native extensions of Ruby in Mac environment, and I was able to confirm the settings that work on Windows and Linux.
The basics are the same as last time.
The first thing that changed was build.rs
, and I was able to get common values for Win, Mac, and Linux from the Ruby config for the library name.
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"));
}
Next is Rakefile
, which I changed from Makefile to make it easier to run on Windows.
The Windows environment supported by Rust is mingw and msvc, but it enforces 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
Others unchanged
To publish it as a gem, gemspec etc. are required, so I will investigate it in the future.
Recommended Posts