Conditionally Bundling Gems Based on Platform

There are a couple of libraries which I usually include in my Gemfiles because they make Guard more awesome on Ubuntu. However, they don’t make sense to require on other platforms, and they probably don’t even compile when not on Linux.

As far as I can tell, there’s no “official” way to conditionally include gems in a Gemfile based on the current OS platform. Or at least there wasn’t the last time I looked at the Bundler documentation. Fortunately a Gemfile is just Ruby, so that’s not really a limitation.

So here’s what I put in my Gemfile:

group :test, :development do
  # ...
  gem 'rb-inotify' if RUBY_PLATFORM =~ /linux/i
  gem 'libnotify' if RUBY_PLATFORM =~ /linux/i
end

This works well for me, but if there’s a better way I’d love to know it.

This entry was posted in Ruby and tagged , , . Bookmark the permalink.
  • josemotanet

    The bundler manual has this on the Gemfile (read this: http://gembundler.com/man/gemfile.5.html):

    As with groups, you can specify one or more platforms:
    gem “weakling”, :platforms => :jruby ,(…)

    This probably means that you might be able to use something like:

    platforms :jruby, :mri_1.9 do
    gem “weakling”
    gem “hookah”
    end

    Hope to have helped.

    • http://avdi.org Avdi Grimm

      Yes, but that’s for the type of Ruby VM, not the OS.

      • josemotanet

        You’re right, I should have noticed that. Thanks for pointing it out.

  • http://docwhat.org The Doctor What

    What you want is: “gem ‘libnotify’, :require => false”

    An example is at https://gist.github.com/3843679

    These libraries will be installed, but won’t be required and therefore won’t bork other platforms.
    The method you have above, which I’m sure you are aware, will cause the Gemfile.lock file to change depending on which platform you run “bundle install” on.
    Ciao!

    • http://avdi.org Avdi Grimm

      I’m not sure that’s what I want, since last I checked at least one of those gems won’t even compile on non-linux platforms.

      • http://docwhat.org The Doctor What

        I’ve used it on windows, Ubuntu, and Mac OS X successfully. If you have problems, I’d like to know about it.

  • KevinSjoberg

    By looking at https://github.com/rubygems/rubygems/blob/master/lib/rubygems/platform.rb and https://github.com/carlhuda/bundler/blob/master/spec/other/ext_spec.rb, it seems that you can specify a string to :platform instead of a symbol in order to match the OS as well.

    • http://avdi.org Avdi Grimm

      Now that is indeed interesting.

  • crnixon

    I usually use Gemfile groups for these, like:

    gem ‘rb-inotify’, :group => :linux

    When I install gems, I have to specify –without in order to not install those gems, but this works well. Using if statements in the Gemfile will cause your Gemfile.lock to be generated with the logic of the platform you last ran bundle upgrade on.

  • Clemens

    Hi Avdi, I had problems with this approach when using it with Capistrano for deployment. Didn’t you encounter similar problems?
    I needed some platform specific gems for OSX (growl, terminal-notifier) and some platform specific for Linux, so as an alternative to using plain old ruby conditionals, I put it in a :osx and a :linux group and excluded :linux on osx with bundle install –without linux and vice versa. But this is not a clean solution, so I think it would be very useful to have native support in bundler, to manage platform specific gems.

    • http://twitter.com/mveldth Marten Veldthuis

      This is what I do as well. You can tell bundler to never install the “linux” group by doing `bundle config without :linux`.

    • http://www.tigraine.at Daniel Hölbling

      What always trips me with this is that on OSX i need bundler to install let’s say the fs-event gem and it then writes it to Gemfile.lock, but when I deploy to a Linux system it will cry as fs-event is in Gemfile.lock but not available on Linux.
      Any solutions to that problem?

  • Peter Jaros

    As others have said, the remaining issue is how to manage the Gemfile.lock. Have you found a solution? it would be nice if there were a way to specify the location of the Gemfile.lock and change it based on the platform, but last I checked the code’s highly coupled to the naming convention.