Unable to build ruby packages with native extensions

Yesterday I tried nixifying the build process of jekyll website I had to update. I tried using pkgs.bundlerEnv with bundix like it is recommended everywhere and I got this error:

error: Cannot build '/nix/store/4h3gib4xs0iclfkp17hr9svcx4mfnvzm-ruby3.4-http_parser.rb-0.8.0.drv'.
       Reason: builder failed with exit code 1.
       Output paths:
         /nix/store/4pcc5jhwdfkgz67n9lrvkxx1zghydn1g-ruby3.4-http_parser.rb-0.8.0
       Last 25 log lines:
       >   Plugins dir: /nix/store/4pcc5jhwdfkgz67n9lrvkxx1zghydn1g-ruby3.4-http_parser.rb-0.8.0/lib/ruby/gems/3.4.0/plugins
       > Building native extensions. This could take a while...
       > ERROR:  Error installing /nix/store/jdz0pb6qxmavbza3bh4n2wbw3xykyr4j-http_parser.rb-0.8.0.gem:
       >      ERROR: Failed to build gem native extension.
       >
       >     current directory: /nix/store/4pcc5jhwdfkgz67n9lrvkxx1zghydn1g-ruby3.4-http_parser.rb-0.8.0/lib/ruby/gems/3.4.0/gems/http_parser.rb-0.8.0/ext/ruby_http_parser
       > /nix/store/779387l7a44ypsqpjcqa8ims5312l348-ruby-3.4.7/bin/ruby extconf.rb
       > creating Makefile
       >
       > current directory: /nix/store/4pcc5jhwdfkgz67n9lrvkxx1zghydn1g-ruby3.4-http_parser.rb-0.8.0/lib/ruby/gems/3.4.0/gems/http_parser.rb-0.8.0/ext/ruby_http_parser
       > make DESTDIR\= sitearchdir\=./.gem.20251031-30-auqnyj sitelibdir\=./.gem.20251031-30-auqnyj clean
       > make: /bin/sh: No such file or directory
       > make: [Makefile:198: clean-static] Error 127 (ignored)
       > make: /bin/sh: No such file or directory
       > make: [Makefile:181: clean] Error 127 (ignored)
       >
       > current directory: /nix/store/4pcc5jhwdfkgz67n9lrvkxx1zghydn1g-ruby3.4-http_parser.rb-0.8.0/lib/ruby/gems/3.4.0/gems/http_parser.rb-0.8.0/ext/ruby_http_parser
       > make DESTDIR\= sitearchdir\=./.gem.20251031-30-auqnyj sitelibdir\=./.gem.20251031-30-auqnyj
       > make: /bin/sh: No such file or directory
       > make: *** [Makefile:250: ruby_http_parser.o] Error 127
       >
       > make failed, exit code 2
       >
       > Gem files will remain installed in /nix/store/4pcc5jhwdfkgz67n9lrvkxx1zghydn1g-ruby3.4-http_parser.rb-0.8.0/lib/ruby/gems/3.4.0/gems/http_parser.rb-0.8.0 for inspection.
       > Results logged to /nix/store/4pcc5jhwdfkgz67n9lrvkxx1zghydn1g-ruby3.4-http_parser.rb-0.8.0/lib/ruby/gems/3.4.0/extensions/x86_64-linux/3.4.0/http_parser.rb-0.8.0/gem_make.out
       For full logs, run:
         nix log /nix/store/4h3gib4xs0iclfkp17hr9svcx4mfnvzm-ruby3.4-http_parser.rb-0.8.0.drv

This is due to the problem that Ruby is trying to run make on a generated Makefile with a hardcoded /bin/sh path: Blaming ruby/lib/mkmf.rb at 65168b7eafd30fd3958d71761fa155bba00cdec5 · ruby/ruby · GitHub.
The Makefile getting generated when using create_makefile("<extension-name>") in a ruby project.

This error is reproducable with just nix build nixpkgs#rubyPackages."http_parser.rb" --rebuild so it’s nothing specific to me.

Without the rebuild flag that package gets pulled from cache which means that hydra built it at least once successfully. But how? I don’t think nix ever allowed this path in its build and that hardcoded path is from a commit from 28 years ago.

This is not specific to http_parser.rb either but to many Ruby packages that uses native extensions. These rubyPackages have the same problem:
json, ffi, eventmachine, bigdecimal

I’m not sure how to fix that problem. I think something should be added here. But I don’t know what exactly.

1 Like

Adding this to the configuration fixes that problem:

nix.settings.sandbox-paths = [ "/bin/sh=${pkgs.busybox-sandbox-shell.out}/bin/busybox" ];

I wonder why is this not the default when the nixpkgs hydra has this configured to build packages. This obviously kills the reproducibility.