From 93b925f4c51369b915557264f63a75c4cb32ba06 Mon Sep 17 00:00:00 2001 From: Joshua Coles Date: Fri, 14 Mar 2025 17:51:55 +0000 Subject: [PATCH] Add rust extension --- Gemfile | 2 +- Gemfile.lock | 87 ++++++++++++ ext/mcp/.gitignore | 2 + ext/mcp/Cargo.lock | 347 +++++++++++++++++++++++++++++++++++++++++++++ ext/mcp/Cargo.toml | 10 ++ ext/mcp/extconf.rb | 8 +- ext/mcp/mcp.c | 9 -- ext/mcp/mcp.h | 6 - ext/mcp/src/lib.rs | 12 ++ mcp.gemspec | 7 +- spec/mcp_spec.rb | 2 +- 11 files changed, 467 insertions(+), 25 deletions(-) create mode 100644 Gemfile.lock create mode 100644 ext/mcp/.gitignore create mode 100644 ext/mcp/Cargo.lock create mode 100644 ext/mcp/Cargo.toml delete mode 100644 ext/mcp/mcp.c delete mode 100644 ext/mcp/mcp.h create mode 100644 ext/mcp/src/lib.rs diff --git a/Gemfile b/Gemfile index 7e854fd..fa24031 100644 --- a/Gemfile +++ b/Gemfile @@ -7,7 +7,7 @@ gemspec gem "rake", "~> 13.0" -gem "rake-compiler" +gem "rake-compiler", "~> 1.2.0" gem "rspec", "~> 3.0" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..3797bb6 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,87 @@ +PATH + remote: . + specs: + mcp (0.1.0) + rb_sys (~> 0.9.39) + +GEM + remote: https://rubygems.org/ + specs: + ast (2.4.2) + diff-lcs (1.6.0) + json (2.10.2) + language_server-protocol (3.17.0.4) + lint_roller (1.1.0) + parallel (1.26.3) + parser (3.3.7.1) + ast (~> 2.4.1) + racc + racc (1.8.1) + rainbow (3.1.1) + rake (13.2.1) + rake-compiler (1.2.9) + rake + rake-compiler-dock (1.9.1) + rb_sys (0.9.111) + rake-compiler-dock (= 1.9.1) + regexp_parser (2.10.0) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.3) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.3) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.2) + rubocop (1.73.2) + json (~> 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) + parallel (~> 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.38.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.38.1) + parser (>= 3.3.1.0) + rubocop-performance (1.24.0) + lint_roller (~> 1.1) + rubocop (>= 1.72.1, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + ruby-progressbar (1.13.0) + standard (1.47.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.73.0) + standard-custom (~> 1.0.0) + standard-performance (~> 1.7) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.7.0) + lint_roller (~> 1.1) + rubocop-performance (~> 1.24.0) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) + +PLATFORMS + arm64-darwin-24 + ruby + +DEPENDENCIES + mcp! + rake (~> 13.0) + rake-compiler (~> 1.2.0) + rspec (~> 3.0) + standard (~> 1.3) + +BUNDLED WITH + 2.6.2 diff --git a/ext/mcp/.gitignore b/ext/mcp/.gitignore new file mode 100644 index 0000000..d81f12e --- /dev/null +++ b/ext/mcp/.gitignore @@ -0,0 +1,2 @@ +/target +/.idea diff --git a/ext/mcp/Cargo.lock b/ext/mcp/Cargo.lock new file mode 100644 index 0000000..ab3f488 --- /dev/null +++ b/ext/mcp/Cargo.lock @@ -0,0 +1,347 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "magnus" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d87ae53030f3a22e83879e666cb94e58a7bdf31706878a0ba48752994146dab" +dependencies = [ + "magnus-macros", + "rb-sys", + "rb-sys-env", + "seq-macro", +] + +[[package]] +name = "magnus-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5968c820e2960565f647819f5928a42d6e874551cab9d88d75e3e0660d7f71e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "mcp" +version = "0.1.0" +dependencies = [ + "magnus", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rb-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "becea799ce051c16fb140be80f5e7cf781070f99ca099332383c2b17861249af" +dependencies = [ + "rb-sys-build", +] + +[[package]] +name = "rb-sys-build" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64691175abc704862f60a9ca8ef06174080cc50615f2bf1d4759f46db18b4d29" +dependencies = [ + "bindgen", + "lazy_static", + "proc-macro2", + "quote", + "regex", + "shell-words", + "syn", +] + +[[package]] +name = "rb-sys-env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb" + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/ext/mcp/Cargo.toml b/ext/mcp/Cargo.toml new file mode 100644 index 0000000..6d92ebb --- /dev/null +++ b/ext/mcp/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "mcp" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +magnus = "0.7" diff --git a/ext/mcp/extconf.rb b/ext/mcp/extconf.rb index 6e3f504..5b84136 100644 --- a/ext/mcp/extconf.rb +++ b/ext/mcp/extconf.rb @@ -1,10 +1,6 @@ # frozen_string_literal: true require "mkmf" +require "rb_sys/mkmf" -# Makes all symbols private by default to avoid unintended conflict -# with other gems. To explicitly export symbols you can use RUBY_FUNC_EXPORTED -# selectively, or entirely remove this flag. -append_cflags("-fvisibility=hidden") - -create_makefile("mcp/mcp") +create_rust_makefile("mcp/mcp") diff --git a/ext/mcp/mcp.c b/ext/mcp/mcp.c deleted file mode 100644 index b18c3cd..0000000 --- a/ext/mcp/mcp.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "mcp.h" - -VALUE rb_mMcp; - -RUBY_FUNC_EXPORTED void -Init_mcp(void) -{ - rb_mMcp = rb_define_module("Mcp"); -} diff --git a/ext/mcp/mcp.h b/ext/mcp/mcp.h deleted file mode 100644 index 38d2eac..0000000 --- a/ext/mcp/mcp.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MCP_H -#define MCP_H 1 - -#include "ruby.h" - -#endif /* MCP_H */ diff --git a/ext/mcp/src/lib.rs b/ext/mcp/src/lib.rs new file mode 100644 index 0000000..3be93c3 --- /dev/null +++ b/ext/mcp/src/lib.rs @@ -0,0 +1,12 @@ +use magnus::{function, Error, Ruby}; + +fn distance(a: (f64, f64), b: (f64, f64)) -> f64 { + ((b.0 - a.0).powi(2) + (b.1 - a.1).powi(2)).sqrt() +} + +#[magnus::init] +fn init(ruby: &Ruby) -> Result<(), Error> { + ruby.define_global_function("distance", function!(distance, 2)); + + Ok(()) +} diff --git a/mcp.gemspec b/mcp.gemspec index 65ac004..4b9cdb7 100644 --- a/mcp.gemspec +++ b/mcp.gemspec @@ -34,8 +34,11 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.extensions = ["ext/mcp/extconf.rb"] - # Uncomment to register a new dependency of your gem - # spec.add_dependency "example-gem", "~> 1.0" + # needed until rubygems supports Rust support is out of beta + spec.add_dependency "rb_sys", "~> 0.9.39" + + # only needed when developing or packaging your gem + # spec.add_development_dependency "rake-compiler", "~> 1.2.0" # For more information and examples about making a new gem, check out our # guide at: https://bundler.io/guides/creating_gem.html diff --git a/spec/mcp_spec.rb b/spec/mcp_spec.rb index ece7423..ed9086f 100644 --- a/spec/mcp_spec.rb +++ b/spec/mcp_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Mcp do it "has a version number" do - expect(Mcp::VERSION).not_to be nil + expect(distance([1, 1], [1, 2])).to eq(1) end it "does something useful" do