1

I have a little project that I want to share via a gem. This extension must be compiled on the user system. So the compilation must be done when the gem is installed.

My project is simple:

tree                                                                                                                                                                  
├── myext.gemspec
├── ext
│   └── myext
│       └── myext.c
│       └── extconf.rb
├── lib
│   ├── myext
│   └── myext.rb
├── Rakefile
└── test

I have checked the extconf.rb and the compilation works if I do

ruby extconf.rb && make

I have a myext.gemspec:

Gem::Specification.new do |s|
  s.name        = 'myext'
  s.version     = '0.0.1'
  s.date        = '2015-04-22'
  s.summary     = "an extension"
  s.description = "an extension that is mine"
  s.authors     = ["cedlemo"]
  require "rake" #for FileList
  s.files       = FileList['lib/*/*.{so}',
                     'lib/*.{rb}'
                    ].to_a
  s.extensions = %w(ext/myext/extconf.rb)
  s.add_development_dependency 'rake-compiler', '~> 0' 
  s.license       = 'MIT'
end

and here is my Rakefile :

require "rubygems"
require "rake/extensiontask"

spec = Gem::Specification.load('myext.gemspec')

Rake::ExtensionTask.new "myext", spec do |ext|
  ext.lib_dir = "lib/myext"
end

When I build my gem, everything is fine :

gem build myext.gemspec

And when I install the gem I havn't any error message:

gem install myext-0.0.1.gem                                                                                                                                          
Building native extensions.  This could take a while...
Successfully installed myext-0.0.1
1 gem installed

My problem is that the C code is not compiled and I don't have any .so file installed:

/home/cedlemo/.gem/ruby/2.2.0/gems/myext-0.0.1/
├── ext
│   └── myext
│       ├── extconf.rb
│       └── Makefile
└── lib
    └── myext.rb

PS: I have read a lot of documentations (official or blogs ...) and everybody is doing its own stuff so it is not very clear and I can't find a solution so don't send me link to http://guides.rubygems.org/ for example.

cedlemo
  • 3,205
  • 3
  • 32
  • 50
  • This code won’t work as shown – your `gemspec` doesn’t include the `extconf.rb` in the `files` list, so you will get an error when trying to install. If your `gemspec` actually includes `extconf.rb` but not any `c` files then you will see the behaviour you describe, so make sure they are included as well. – matt Apr 23 '15 at 11:10
  • I have tried to add ext/*/*.c and ext/*/*.h in the FileList and it works. Is it the right way to do it? You should make an answer so that I can validate it. – cedlemo Apr 23 '15 at 11:18
  • Did your actual `gemspec` include `extconf.rb` (perhaps you used `*/*.rb` rather than `lib/*.rb`)? – matt Apr 23 '15 at 11:31
  • No but as I have seen in http://guides.rubygems.org/gems-with-extensions/ I have s.extensions = %w(ext/myext/extconf.rb) since the begining – cedlemo Apr 23 '15 at 11:54
  • That would explain it, I was using a different name in my test but copied your gemspec without changing `myext` so I got the error. – matt Apr 23 '15 at 12:00

1 Answers1

2

You haven’t included the source files in your files part of your gemspec, so there is nothing to compile when installing the gem. Make sure you include all needed files:

s.files = FileList['lib/**/*.rb', 'ext/**/*.{rb,c,h}']

You don’t need to include .so files, as they will be built during installation (and might not actually be .so). Also I don’t think you need to add to_a (a FileList basically is an array already).

matt
  • 78,533
  • 8
  • 163
  • 197
  • Just a little more information how do you put the .so file in the lib/myext/ directory after compilation ? ( I use a myext.rb that load the so file)? – cedlemo Apr 23 '15 at 12:55
  • @cedlemo the gem install process should copy it into the `lib` dir, so you shouldn’t have to do anything – just `require 'the_extension'` (or whatever you’ve named it). – matt Apr 23 '15 at 13:18
  • No not if in you extconf.rb you set create_makefile(myext) instead of create_makefile(myext/myext). My bad sorry for this. thanks for you help. – cedlemo Apr 23 '15 at 13:22