Quick Start: Your First Extension
This chapter shows you how to create a Ruby gem with a Rust extension using Bundler's built-in Rust support.
Creating a Gem with Bundler
The easiest way to create a new gem with a Rust extension is with Bundler:
# Create a new gem with a Rust extension
bundle gem --ext=rust hello_rusty
cd hello_rusty
This command generates everything you need to build a Ruby gem with a Rust extension.
Understanding the Generated Files
Let's examine the key files Bundler created:
hello_rusty/
├── ext/hello_rusty/ # Rust extension directory
│ ├── Cargo.toml # Rust dependencies
│ ├── extconf.rb # Ruby extension config
│ └── src/lib.rs # Rust code
├── lib/hello_rusty.rb # Main Ruby file
└── hello_rusty.gemspec # Gem specification
The Rust Code (lib.rs)
Bundler generates a simple "Hello World" implementation:
#![allow(unused)] fn main() { // ext/hello_rusty/src/lib.rs use magnus::{define_module, function, prelude::*, Error}; #[magnus::init] fn init() -> Result<(), Error> { let module = define_module("HelloRusty")?; module.define_singleton_method("hello", function!(|| "Hello from Rust!", 0))?; Ok(()) } }
You can click the "play" button on code blocks to try them out in the Rust Playground where appropriate. For code that depends on the Ruby API, you won't be able to run it directly, but you can experiment with Rust syntax and standard library functions.
The Extension Configuration (extconf.rb)
# ext/hello_rusty/extconf.rb
require "mkmf"
require "rb_sys/mkmf"
create_rust_makefile("hello_rusty/hello_rusty")
This file connects Ruby's build system to Cargo.
Enhancing the Default Implementation
Let's improve the default implementation by adding a simple class:
Click the eye icon () to reveal commented lines with additional functionality that you could add to your implementation.
Building and Testing
Compile the Extension
# Install dependencies and compile
bundle install
bundle exec rake compile
What happens during compilation:
- Ruby's
mkmf
reads yourextconf.rb
create_rust_makefile
generates a Makefile with Cargo commands- Cargo compiles your Rust code to a dynamic library
- The binary is copied to
lib/hello_rusty/hello_rusty.{so,bundle,dll}
Run the Tests
Bundler generates a basic test file. Let's update it:
Run the tests:
Try It in the Console
Once in the console, you can interact with your extension:
Customizing the Build
You can customize the build process with environment variables:
Remember that building in release mode will produce optimized, faster code but will increase compilation time.
Next Steps
Congratulations! You've created a Ruby gem with a Rust extension. In the next chapters, we'll explore:
- Better project organization
- Working with Ruby objects in Rust
- Memory management and safety
- Performance optimization