Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .github/workflows/publish-book.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,27 @@ on:
push:
branches:
- main
- better-docs

jobs:
deploy:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- uses: actions/checkout@v4

- name: Setup mdBook
uses: peaceiris/actions-mdbook@v2
- uses: oxidize-rb/actions/setup-ruby-and-rust@v1
with:
mdbook-version: "0.4.18"
ruby-version: "3.4"
bundler-cache: true
cargo-cache: true

- name: Install mdbook
run: cargo install mdbook --version 0.4.49

- name: Build the book
run: mdbook build ./book
run: bundle exec rake book:build

- name: Deploy
uses: peaceiris/actions-gh-pages@v4
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ gem/docs
.yardoc/
.DS_Store
examples/rust_reverse/ext/rust_reverse/Cargo.lock
book/src/https:/
46 changes: 46 additions & 0 deletions book/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# The Ruby on Rust Book

This directory contains the source for "The Ruby on Rust Book" which is built using
[mdBook](https://rust-lang.github.io/mdBook/).

## SEO Setup

This book has been configured with SEO optimizations:

1. **Meta Tags**: The theme has been updated to include proper meta tags for SEO, including Open Graph and Twitter card
support.
2. **Sitemap Generation**: A sitemap.xml file is generated after the book is built.
3. **Robots.txt**: A robots.txt file is included to help search engines navigate the site.
4. **Custom CSS/JS**: Custom CSS and JS files are included to improve readability and add structured data for search
engines.

## Building the Book

To build the book with all SEO features:

```bash
# Run the Rake task from the project root
rake book:build_with_sitemap
```

This will:

1. Build the book using mdBook
2. Generate the sitemap.xml file
3. Copy the robots.txt file to the output directory

## Submitting to Search Engines

After deploying the site, you should submit the sitemap to search engines:

- Google: Submit through [Google Search Console](https://search.google.com/search-console)
- Bing: Submit through [Bing Webmaster Tools](https://www.bing.com/webmasters)

## Customizing SEO

To customize the SEO settings:

1. Edit `book.toml` to update metadata like title and description
2. Modify `theme/index.hbs` to update meta tags
3. Update `theme/css/custom.css` and `theme/js/custom.js` for styling and behavior
4. Adjust the sitemap generation settings in `rakelib/book.rake`
23 changes: 20 additions & 3 deletions book/book.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
[book]
title = "Ruby on Rust"
description = "The definitive guide for using Rust in Ruby"
authors = ["Ian Ker-Seymer"]
language = "en"
multilingual = false
src = "src"
title = "The Ruby on Rust Book"
description = "A comprehensive guide to building Ruby extensions with Rust using rb-sys"

[output.html]
git-repository-url = "https://github.com/oxidize-rb/rb-sys"
git-repository-icon = "fa-github"
site-url = "https://oxidize-rb.github.io/rb-sys/"
additional-css = ["theme/css/custom.css"]
additional-js = ["theme/js/custom.js"]

[build]
extra-watch-dirs = ["theme"]

[preprocessor.links]

# Copy robots.txt to the output directory
[[output.html.print.html-before-content]]
text = '''
<!-- This is a placeholder to ensure robots.txt is copied -->
'''
46 changes: 36 additions & 10 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,43 @@
# Summary
# Ruby on Rust

[Introduction](./introduction.md)
[Getting Started](./getting-started.md)
[Background and Concepts](./background-and-concepts.md)

---
## Part 1: Getting Started

- [Prerequisites and Installation](./getting-started.md)
- [Quick Start: Your First Extension](./quick-start.md)

## Part 2: Core Concepts

- [Project Structure](./project-setup.md)
- [Anatomy of a Rusty Ruby Gem: hello_rusty](./hello-rusty-documentation.md)
- [Development Approaches](./development-approaches.md)
- [Working with Ruby Objects](./working-with-ruby-objects.md)
- [Ruby Classes and Modules](./classes-and-modules.md)
- [Error Handling](./error-handling.md)

## Part 3: Advanced Topics

- [Memory Management & Safety](./memory-management.md)
- [The Build Process](./build-process.md)
- [Cross-Platform Development](./cross-platform.md)

# User Guide
## Part 4: Practical Development

- [Tutorial](./tutorial.md)
- [Testing Extensions](./testing.md)
- [Debugging & Troubleshooting](./debugging.md)
- [Troubleshooting Guide](./troubleshooting.md)

- [Debugging](./tutorial/testing/debugging.md)
- [Cross-Compilation](./tutorial/publishing/cross-compilation.md)
- [Documenting](./tutorial/documenting.md)
## API Reference

- [rb-sys Crate Features](./api-reference/rb-sys-features.md)
- [rb_sys Gem Configuration](./api-reference/rb-sys-gem-config.md)
- [Test Helpers](./api-reference/test-helpers.md)

## Community and Support

- [Getting Help](./community-support.md)

---

- [API Documentation](./api-documentation.md)
[Contributing to rb-sys](https://github.com/oxidize-rb/rb-sys/blob/main/CONTRIBUTING.md)
4 changes: 0 additions & 4 deletions book/src/api-documentation.md

This file was deleted.

87 changes: 87 additions & 0 deletions book/src/api-reference/rb-sys-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# rb-sys Crate Features

The `rb-sys` crate provides battle-tested Rust bindings for the Ruby C API. It uses the
[`rust-bindgen`](https://github.com/rust-lang/rust-bindgen) crate to generate bindings from the `ruby.h` header.

## Usage Notice

This is a very low-level library. If you are looking to write a gem in Rust, you should probably use the
[Magnus](https://github.com/matsadler/magnus) crate with the `rb-sys-interop` feature, which provides a higher-level,
more ergonomic API.

If you need raw/unsafe bindings to libruby, then this crate is for you!

## Writing a Ruby Gem

Ruby gems require boilerplate to be defined to be usable from Ruby. `rb-sys` makes this process painless by doing the
work for you. Simply enable the `gem` feature:

```toml
[dependencies]
rb-sys = "0.9"
```

Under the hood, this ensures the crate does not link libruby (unless on Windows) and defines a `ruby_abi_version`
function for Ruby 3.2+.

## Embedding libruby in Your Rust App

**IMPORTANT**: If you are authoring a Ruby gem, you do not need to enable this feature.

If you need to link libruby (i.e., you are initializing a Ruby VM in your Rust code), you can enable the `link-ruby`
feature:

```toml
[dependencies]
rb-sys = { version = "0.9", features = ["link-ruby"] }
```

## Static libruby

You can also force static linking of libruby:

```toml
[dependencies]
rb-sys = { version = "0.9", features = ["ruby-static"] }
```

Alternatively, you can set the `RUBY_STATIC=true` environment variable.

## Available Features

The `rb-sys` crate provides several features that can be enabled in your `Cargo.toml`:

| Feature | Description |
| -------------------------- | --------------------------------------------------------------- |
| `global-allocator` | Report Rust memory allocations to the Ruby GC (_recommended_) |
| `ruby-static` | Link the static version of libruby |
| `link-ruby` | Link libruby (typically used for embedding, not for extensions) |
| `bindgen-rbimpls` | Include the Ruby impl types in bindings |
| `bindgen-deprecated-types` | Include deprecated Ruby methods in bindings |
| `gem` | Set up the crate for use in a Ruby gem (default feature) |
| `stable-api` | Use the stable API (C level) if available for your Ruby version |

## Example Cargo.toml

```toml
[dependencies]
rb-sys = { version = "0.9", features = ["global-allocator", "stable-api"] }
```

## Ruby Version Compatibility

`rb-sys` is compatible with Ruby 2.6 and later. The crate detects the Ruby version at compile time and adapts the
bindings accordingly.

For Ruby 3.2 and later, `rb-sys` provides a `ruby_abi_version` function that is required for native extensions.

## Integration with Magnus

If you're building a Ruby extension, it's recommended to use the [Magnus](https://github.com/matsadler/magnus) crate on
top of `rb-sys`. Magnus provides a high-level, safe API for interacting with Ruby:

```toml
[dependencies]
magnus = { version = "0.7", features = ["rb-sys"] }
rb-sys = "0.9"
```
107 changes: 107 additions & 0 deletions book/src/api-reference/rb-sys-gem-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# rb_sys Gem Configuration

The `rb_sys` gem makes it easy to build native Ruby extensions in Rust. It interoperates with existing Ruby native
extension toolchains (i.e., `rake-compiler`) to make testing, building, and cross-compilation of gems easy.

## RbSys::ExtensionTask

This gem provides a `RbSys::ExtensionTask` class that can be used to build a Ruby extension in Rust. It's a thin wrapper
around `Rake::ExtensionTask` that provides sane defaults for building Rust extensions.

```ruby
# Rakefile

require "rb_sys/extensiontask"

GEMSPEC = Gem::Specification.load("my_gem.gemspec")

RbSys::ExtensionTask.new("my-crate-name", GEMSPEC) do |ext|
ext.lib_dir = "lib/my_gem"

# If you want to use `rb-sys-dock` for cross-compilation:
ext.cross_compile = true
end
```

## create_rust_makefile

The gem provides a simple helper to build a Ruby-compatible Makefile for your Rust extension:

```ruby
# ext/rust_reverse/extconf.rb

# We need to require mkmf *first* since `rake-compiler` injects code here for cross compilation
require "mkmf"
require "rb_sys/mkmf"

create_rust_makefile("rust_reverse") do |r|
# Create debug builds in dev. Make sure that release gems are compiled with
# `RB_SYS_CARGO_PROFILE=release` (optional)
r.profile = ENV.fetch("RB_SYS_CARGO_PROFILE", :dev).to_sym

# Can be overridden with `RB_SYS_CARGO_FEATURES` env var (optional)
r.features = ["test-feature"]

# You can add whatever env vars you want to the env hash (optional)
r.env = {"FOO" => "BAR"}

# If your Cargo.toml is in a different directory, you can specify it here (optional)
r.ext_dir = "."

# Extra flags to pass to the $RUSTFLAGS environment variable (optional)
r.extra_rustflags = ["--cfg=some_nested_config_var_for_crate"]

# Force a rust toolchain to be installed via rustup (optional)
# You can also set the env var `RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN=true`
r.force_install_rust_toolchain = "stable"

# Clean up the target/ dir after `gem install` to reduce bloat (optional)
r.clean_after_install = false # default: true if invoked by rubygems

# Auto-install Rust toolchain if not present on "gem install" (optional)
r.auto_install_rust_toolchain = false # default: true if invoked by rubygems
end
```

## Environment Variables

The `rb_sys` gem respects several environment variables that can modify its behavior:

| Environment Variable | Description |
| ------------------------------------- | --------------------------------------------------- |
| `RB_SYS_CARGO_PROFILE` | Set the Cargo profile (i.e., `release` or `dev`) |
| `RB_SYS_CARGO_FEATURES` | Comma-separated list of Cargo features to enable |
| `RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN` | Force installation of a Rust toolchain |
| `RUBY_STATIC` | Force static linking of libruby if set to `true` |
| `LIBCLANG_PATH` | Path to libclang if it can't be found automatically |

## Tips and Tricks

- When using `rake-compiler` to build your gem, you can use the `RB_SYS_CARGO_PROFILE` environment variable to set the
Cargo profile (i.e., `release` or `dev`).

- You can pass Cargo arguments to `rake-compiler` like so: `rake compile -- --verbose`

- It's possible to force an installation of a Rust toolchain by setting the `RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN`
environment variable. This will install [rustup](https://rustup.rs/) and [cargo](https://crates.io/) in the build
directory, so the end user does not have to have Rust pre-installed. Ideally, this should be a last resort, as it's
better to already have the toolchain installed on your system.

## Troubleshooting

### Libclang Issues

If you see an error like this:

```
thread 'main' panicked at 'Unable to find libclang: "couldn't find any valid shared libraries matching: \['libclang.so', 'libclang-*.so', 'libclang.so.*', 'libclang-*.so.*'\], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: \[\])"'
```

This means that bindgen is having issues finding a usable version of libclang. An easy way to fix this is to install the
[`libclang` gem](https://github.com/oxidize-rb/libclang-rb), which will install a pre-built version of libclang for you.
`rb_sys` will automatically detect this gem and use it.

```ruby
# Gemfile
gem "libclang", "~> 14.0.6"
```
Loading
Loading