Optional support for compiling native extensions for :path gems in monorepos
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 4k
- Forks
- 1.9k
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 81
Description
Describe the problem as clearly as you can
Bundler does not compile native extensions for gems declared using the :path source. I understand this is documented and intentional behaviour.
However, this limitation becomes significant in monorepos where many internal gems live side-by-side and are composed via path: dependencies. In our case, gems live under packages/*, and one internal gem includes a native extension implemented in Rust (via rb_sys) and configured using extconf.rb.
Because Bundler does not run extension build steps for :path gems, bundle exec fails at runtime unless the extension is manually built ahead of time, or the dependency is converted to :git or packaged as a gem. Both alternatives significantly degrade the monorepo development workflow.
I am not reporting a bug in current behaviour, but requesting consideration of an opt-in feature to allow native extensions to be compiled for :path gems.
Proposed feature / behaviour
Introduce an explicit, opt-in Bundler configuration that allows native extensions to be built for :path gems, while preserving current behaviour by default.
- Opt-in only, via Bundler config (global or per-gem), so existing behaviour is unchanged unless explicitly enabled.
- Out-of-tree builds: native extensions would be compiled into a Bundler-managed build/cache directory rather than writing build artefacts into the working tree.
- Standard extension pipeline: Bundler would invoke the existing RubyGems extension build mechanism (e.g.
extconf.rb, including Rust extensions viarb_sys), without needing Rust-specific logic. - Load path integration: the build output directory would be added to
$LOAD_PATHahead of the:pathgem’slib/, allowingrequireto resolve the compiled extension while Ruby source files continue to come from the local checkout. - Monorepo-friendly: this allows internal gems under
packages/*to be used via:pathwithout requiring separate manual build steps or switching to:git.
This would preserve Bundler’s rationale for not mutating :path directories while enabling a much smoother workflow for monorepos that include native extensions.
Did you try upgrading rubygems & bundler?
Yes. This behaviour persists on the latest versions of RubyGems and Bundler available at the time of reporting.
Post steps to reproduce the problem
- Create a monorepo with multiple gems under
packages/* - One gem includes a native extension configured via
extconf.rb - Another gem (or the top-level application) depends on that gem using
gem "my_native_gem", path: "packages/my_native_gem" - Run
bundle install - Run
bundle exec ruby -e 'require "my_native_gem"'
The extension is not compiled, and the require fails at runtime because the native library is missing.
Which command did you run?
bundle install
followed by
bundle exec ruby -e 'require "my_native_gem"'
What were you expecting to happen?
With an explicit opt-in configuration, I would expect Bundler to compile the native extension for the :path gem during install, similar to how it behaves for :git or packaged gems, without writing build artefacts into the working tree.
What happened instead?
The native extension is not compiled for the :path gem, resulting in a runtime load error unless the extension is manually built beforehand.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing Bundler's :path dependency handling during bundle install and the existing RubyGems extension pipeline used by extconf.rb. Reproduce the monorepo case with a native extension, then inspect how bundle exec resolves the gem's load path. Done means an explicit opt-in builds outside the checkout and lets require load the compiled extension while default behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ruby, rust
- Domain
- build-system, developer-experience, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100