ypz
ypz

Reputation: 71

how do I repackage a ruby gem with native extensions

I need to install a number of ruby gems (all with C extensions) on a production server which does not have any dev tools installed. I'd like to build gems on a dev server first and then repackage and install resulting native gems on production server.

However, there seems to be no standard methods to package gem with native extensions for redistribution. I am aware of rake-compiler, but none of the gems in concern works with it out of the box. Specifically, I am working with json-1.7.5, rb-inotify-0.8.8 and ffi-1.2.1 gems.

Any pointers on how to do this task or documentations on the subject are appreciated.

Upvotes: 5

Views: 1558

Answers (3)

lukapiske
lukapiske

Reputation: 399

Hi You could do it with: gem-compiler

You need to tell RubyGems the filename of the gem you want to compile:

$ gem compile yajl-ruby-1.1.0.gem

The above command will unpack, compile any existing extensions found and repackage everything as a binary gem:

Unpacking gem: 'yajl-ruby-1.1.0' in temporary directory...
Building native extensions.  This could take a while...
Successfully built RubyGem
Name: yajl-ruby
Version: 1.1.0
File: yajl-ruby-1.1.0-x86-mingw32.gem

It have well written documentations here: https://github.com/luislavena/gem-compiler. I am using it as well as we have own gem server. Just have to be careful with distribution because some gems compiled on wheezy won't work on jessie and so on.

Upvotes: 1

Holger Just
Holger Just

Reputation: 55748

Using Jordan Sissel's fpm you can take various input archives (including gems) and compile and package them as (among others) DEBs or RPMs.

An example to compile the json gem into a deb package follows:

cd /tmp
fpm -s gem -t deb json

This will download the latest version of the json gem and create a rubygem-json-1.5.7-1.amd64.deb archive in /tmp which you can install on your server. Note that the compile box and the final server need to be rather identical. At least the distribution and bitness, the ruby version and its file layout, and the available loadable libraries should be the same. Basically all the constraints your upstream distribution deals with...

That said, in the long term I found it much easier to just install a compiler on the target servers and use rbenv or rvm on the server. For most small and mid-size installations, it's much easier to handle as you don't need to pre-compile and ship everything to your servers.

Upvotes: 2

tadman
tadman

Reputation: 211560

You're going to have to build them on a system that's almost exactly the same for this to work. If you're linking against shared libraries that are in a different location or have slightly different versions it may not work at all. Sometimes you have some slack, where it will work with a range of versions, but this cannot be assured.

There's no way to package with native extensions for this very reason, there's just too many possible combinations of libraries.

You'll also need to make sure you're using the same architecture, including 32-bit or 64-bit as required.

Sometimes you'll get lucky and there's a package for your OS that can install these for you, but these won't work with rvm or rbenv.

Upvotes: 0

Related Questions