does using ":platforms =>" in your gemfile work?
Asked Answered
R

8

22

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
Reasoned answered 7/12, 2011 at 19:30 Comment(3)
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.Hallett
@Hallett the line from the docs (ruby: C Ruby ... NOT Windows) disagrees with youReasoned
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.Hallett
A
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?

Arneson answered 19/7, 2012 at 14:44 Comment(1)
For a linux or darwin env using the requires, as described here works well too https://mcmap.net/q/219002/-how-to-add-mac-specific-gems-to-bundle-on-mac-but-not-on-linuxArctogaea
H
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
Hallett answered 10/12, 2011 at 18:13 Comment(4)
So the docs are just wrong? That's what I'm really trying to get at.Reasoned
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.Chilopod
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.Hallett
@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).Cinque
C
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.

Chilopod answered 10/12, 2011 at 22:8 Comment(0)
P
6

Rails 5:

if Gem.win_platform?
  # Install gem for Windows
else
  # Install another gem
end
Phillipphillipe answered 24/2, 2018 at 14:58 Comment(0)
R
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
Reedbuck answered 15/12, 2019 at 20:36 Comment(0)
T
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.

Terrain answered 7/12, 2011 at 20:37 Comment(2)
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.Reasoned
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.Terrain
S
0
gem 'win32-security', '~> 0.3.1' if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)

That works pretty well for me.

Supper answered 17/1, 2015 at 21:24 Comment(0)
P
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...

Pipe answered 4/1, 2018 at 7:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.