I’m trying to build a ruby gem (rubyx-py to be exact), but have a hard time figuring out how to build the native extension (as these are made with rust and not with C).
The gem did not have a Cargo.lock file commited, but that was easy to add (though I added both the Cargo.lock file for rustPlatform.importCargoLock and a patch to add this to the folder itself)
My gem config thus looks like:
gems = pkgs.bundlerEnv {
ruby = pkgs.ruby_3_4;
name = "bundler-env";
gemfile = ./Gemfile;
lockfile = ./Gemfile.lock;
gemset = ./gemset.nix;
groups = [ "default" "development" "test" "production" ];
gemConfig = pkgs.defaultGemConfig // {
rubyx-py = attrs: {
buildInputs = [ pkgs.rustc pkgs.cargo pkgs.rustPlatform.cargoSetupHook ];
dontBuild = false;
patches = [ ./patches/add-cargo-lock.patch ];
cargoDeps = pkgs.rustPlatform.importCargoLock { lockFile = ./rubyx-py-Cargo.lock; };
};
};
};
At this point I run into the following error when the gem tries to build its native extensions
Running phase: installPhase
@nix { "action": "setPhase", "phase": "installPhase" }
buildFlags:
WARNING: You build with buildroot.
Build root: /
Bin dir: /nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0/bin
Gem home: /nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0
Plugins dir: /nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0/plugins
Building native extensions. This could take a while...
ERROR: Error installing rubyx-py-0.2.1.gem:
ERROR: Failed to build gem native extension.
current directory: /nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0/gems/rubyx-py-0.2.1/ext/rubyx
/nix/store/axil30p7f6cva0cll8s6kp6nxv3qvq9y-ruby-3.4.9/bin/ruby extconf.rb
checking for clang... yes
checking for clang++... yes
checking for ar... yes
checking for install_name_tool... yes
current directory: /nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0/gems/rubyx-py-0.2.1/ext/rubyx
make DESTDIR\= sitearchdir\=./.gem.20260716-545-2vqvzn sitelibdir\=./.gem.20260716-545-2vqvzn clean
current directory: /nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0/gems/rubyx-py-0.2.1/ext/rubyx
make DESTDIR\= sitearchdir\=./.gem.20260716-545-2vqvzn sitelibdir\=./.gem.20260716-545-2vqvzn
generating target/release/librubyx.dylib (release)
cargo rustc --manifest-path ./Cargo.toml --target-dir target --lib --profile release -- -C linker=clang -L native=/nix/store/axil30p7f6cva0cll8s6kp6nxv3qvq9y-ruby-3.4.9/lib -C link-arg=-Wl,-multiply_defined,suppress -C link-arg=-Wl,-undefined,dynamic_lookup -l pthread
Updating crates.io index
error: failed to get `crossbeam-channel` as a dependency of package `rubyx v0.1.0 (/nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0/gems/rubyx-py-0.2.1/ext/rubyx)`
Caused by:
download of config.json failed
Caused by:
failed to download from `https://index.crates.io/config.json`
Caused by:
[60] SSL peer certificate or SSH remote key was not OK (SSL certificate OpenSSL verify result: unable to get local issuer certificate (20))
make: *** [Makefile:365: target/release/librubyx.dylib] Error 101
make failed, exit code 2
Gem files will remain installed in /nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0/gems/rubyx-py-0.2.1 for inspection.
Results logged to /nix/store/861nnhwpxfa6vcqnrm0mbvcr8lpwpdfw-ruby3.4-rubyx-py-0.2.1/lib/ruby/gems/3.4.0/extensions/arm64-darwin-25/3.4.0/rubyx-py-0.2.1/gem_make.out
The instruction for how to build the gem come from rb-sys: rb-sys/gem/lib/rb_sys/mkmf.rb at 94b205cd8425ebdc09d5682f14503b3f3756fa9b · oxidize-rb/rb-sys · GitHub
There are a few options that can be specified there, but I don’t quite see how to configure it to not download the crates, but use the crates as downloaded by nix
Are there any examples of ruby gems with native extensions in rust and how to build them?
Thanks!