21

I have a Rails app that I'm developing on Windows and deploying to Linux. I suspect I'll just switch entirely over to Linux in the future. Anyway, on Linux I need 'execjs' and 'therubyracer' but I don't need those in Win7. So I put these lines in my gemfile:

gem 'therubyracer', :platforms => :ruby
gem 'execjs', :platforms => :ruby

Ran a bundle install on the Linux VM and the app started up fine. But on Windows I get:

Uncaught exception: Could not find execjs-1.2.11 in any of the sources

Now, from what I read (here under PLATFORMS) it tells me that "If a gem should only be used in a particular platform or set of platforms, you can specify them" and the sample is this:

gem "weakling",   :platforms => :jruby 

And it says "ruby C Ruby (MRI) or Rubinius, but NOT Windows". So to me that says that bundler should be ignoring the execjs line on Windows. However on Windows when I ran bundle install I saw this:

Installing execjs (1.2.11)

So that says to me I'm missing something about the docs or bundler is ignoring the platforms command. Am I doing something wrong?

PS>bundle -v
Bundler version 1.0.21
jcollum
  • 43,623
  • 55
  • 191
  • 321
  • The bit of information you need is that platforms in the Gemfile refers to the implementation of Ruby, NOT the OS. :ruby == :mri on all OS platforms so you can't use that to prevent a gem from being installed on one OS or the other. – ffoeg Dec 10 '11 at 18:08
  • 1
    @ffoeg the line from the docs (ruby: C Ruby ... NOT Windows) disagrees with you – jcollum Dec 10 '11 at 18:09
  • I stand corrected. The answer to your question remains the same. platforms in Bundler does work but it is not the mechanism you want to use in this case. See my answer below. – ffoeg Dec 10 '11 at 18:14

8 Answers8

21

:platforms => :ruby does indeed exclude gems from being installed on Windows.

However, it does not work in a cygwin environment. In cygwin, it considers the platform to be :mri.

You'll also notice that ruby -e 'puts RUBY_PLATFORM' outputs i386-cygwin, not i386-mingw32 or i386-mswin like it would on Windows ruby.

Were you working in a cygwin environment?

Edward Anderson
  • 13,591
  • 4
  • 52
  • 48
9

Add code to the Gemfile like this that excludes/includes gems depending on the OS platform

if RUBY_PLATFORM=~ /win32/ 
   gem "windows-only-gem"
else
   gem "os-agnostic-gem"
end
ffoeg
  • 2,336
  • 1
  • 14
  • 13
  • So the docs are just wrong? That's what I'm really trying to get at. – jcollum Dec 10 '11 at 21:09
  • 7
    You can't use `if` blocks in your Gemfile. If you do, then Gemfile.lock will be regenerated and modified every time the project is accessed on different platforms. – Luis Lavena Dec 10 '11 at 22:10
  • so what? Sounds like some dogma you should let go of. We dev on OSX and deploy in JRuby. We only check in Gemfile.lock that's generated in JRuby. – ffoeg Dec 11 '11 at 01:57
  • 3
    @ffoeg: I agree your approach works, but I think Luis Lavena's point is important for people who follow the recommended practice of checking your Gemfile.lock whenever you add a new gem or bundle update. And it's not a bad practice -- that way all developers have the exact same gem versions (except for the platform dependent ones, ideally). – antinome Oct 09 '13 at 20:02
6

Rails 5:

if Gem.win_platform?
  # Install gem for Windows
else
  # Install another gem
end
gdfgdfg
  • 3,181
  • 7
  • 37
  • 83
6

Bundler concept of platform differs from normal understanding of RUBY_PLATFORM matching or RubyGems behaviors.

You can find the entire documentation about how to use platforms for Bundler here:

http://bundler.io/v1.14/man/gemfile.5.html

You might not need therubyraceron Windows (it actually doesn't work), but you might need execjs so CoffeeScript or other details of Asset Pipeline work properly

In your case, I will do:

gem "execjs"
gem "therubyracer", :platforms => :ruby

UPDATE: execjs gem might be installed because another dependency (not limited by platforms) is depending on it to be installed.

Robin Daugherty
  • 7,115
  • 4
  • 45
  • 59
Luis Lavena
  • 10,348
  • 1
  • 37
  • 39
2

Easy as

gem 'wdm', '~> 0.1.0' if Gem.win_platform?

Full example of a Gemfile with 1 dependency only intended for a Windows environment.

source 'https://rubygems.org'

group :development, :test do
  gem 'jekyll', '>= 4.0.0'
  gem 'jekyll-target-blank', '>= 2.0.0'
  gem 'jekyll-redirect-from', '>= 0.15.0'
  gem 'jekyll-sitemap', '>= 1.4.0'
  gem 'jekyll-toc', '>= 0.12.2'
  gem 'rouge', '>= 3.14.0'
  gem 'wdm', '>= 0.1.1' if Gem.win_platform?
end
Asbjørn Ulsberg
  • 8,721
  • 3
  • 45
  • 61
djibe
  • 2,753
  • 2
  • 17
  • 26
1

I'm not sure about the :platform switch as I've never used it. However, an alternative that I think will work for your scenario would be to wrap your declarations for those two gems in a 'group' block in your Gemfile. Such as...

group :production do
  gem 'therubyracer'
  gem 'execjs'
end

This way, those gems will only be used in your production environment, not in development.

Note that I believe bundler will still install them in development (something to do with dependency checking), but they won't actually get loaded and therefore shouldn't cause problems.

Jon Garvin
  • 1,178
  • 9
  • 26
  • 1
    This may work but doesn't actually answer my question. I didn't ask how can I work around it, I asked whether it should/does work. – jcollum Dec 07 '11 at 22:50
  • I agree that it doesn't address the question directly, however it does address the underlying problem. It's not a "work around". It's an equally valid alternative that you may not have been aware of, and that you may (or may not) feel is appropriate for your specific situation. – Jon Garvin Dec 07 '11 at 23:10
0
gem 'win32-security', '~> 0.3.1' if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)

That works pretty well for me.

almyz125
  • 648
  • 1
  • 7
  • 18
0

A variation of @ffoeg's answer worked for me, and handles all windows environments, whereas just using RUBY_PLATFORM=~ /win32/ didn't work:

if RUBY_PLATFORM =~ /mswin|mingw|cygwin/i

  gem 'windows-only'

else

  gem 'non-windows'    

end

I agree that it's not ideal to have different gemfiles, however since I'm using unicorn to serve my Jekyll blog on Heroku, so I need gem unicorn - and this relies on kgio which several sources have confirmed is virtually impossible to install on windows...

Lewy Blue
  • 452
  • 3
  • 16