I'm writing a gem, that includes a C extension. Usually when I write a gem, I follow a process of TDD, where I'll write a failing spec and then work on the code until it passes, etc etc...
With my C extension in "ext/mygem/mygem.c" and a valid extconf.rb configured in the gemspec's "extensions", how do I run my specs and still have my C extension loaded? When I make changes to the C code, what steps do I need to take to recompile the code?
This is probably a stupid question, but typing 'bundle install' from inside my gem's development source tree does not build any native extensions. When I manually run ruby ext/mygem/extconf.rb
I do get a Makefile (in the root of the whole project) and when I then run make
, I do get a shared object (again, in the root of the whole project). I must be following the wrong workflow, since I understand that the .so is supposed to be placed under lib/. Unless I'm just supposed to do that by hand during development?
Don't know whether it's the 'right' way but the way I've done this in the past is
Add
$: << File.dirname(__FILE__) + '/../ext'
To my spec helper
And then have a rakefile that looks like
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new('spec')
task :build do
Dir.chdir('ext') do
output = `ruby extconf.rb`
raise output unless $? == 0
output = `make`
raise output unless $? == 0
end
end
task :spec => :build
So rake spec
builds the c code for me each time, with the built library existing in ext/. The change to the load path ensures that this copy is loaded. This github repo illustrates this.
The solution I went with in the end was to use rake-compiler, on github:
https://github.com/luislavena/rake-compiler
You just add a rake task to do the compile (documented in the README), then make the 'spec' task(s) depend on that build phase.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With