how to build gem whose dependencies depend of the platform?

J

Jarmo Pertman

Hi!

I need to build a gem whose dependencies are dependent of the platform
itself. For example when `gem install my_gem` is issued under Windows,
then in gemspec i have to have spec.add_dependency("gemX"), but if the
command is executed under linux then i need to have
spec.add_dependency("gemY").

Is there any easy way to do this or should i just do it like this
instead:
1) remove all platform specific dependencies from gemspec
2) when loading the gem, then use RUBY_PLATFORM to decide what gems to
load and rescue Gem::LoadError to print out friendly messages like
"please install gemX"

Jarmo
 
L

Luis Lavena

Hi!

I need to build a gem whose dependencies are dependent of the platform
itself. For example when `gem install my_gem` is issued under Windows,
then in gemspec i have to have spec.add_dependency("gemX"), but if the
command is executed under linux then i need to have
spec.add_dependency("gemY").

Is there any easy way to do this or should i just do it like this
instead:
1) remove all platform specific dependencies from gemspec
2) when loading the gem, then use RUBY_PLATFORM to decide what gems to
load and rescue Gem::LoadError to print out friendly messages like
"please install gemX"

This one is the best approach. Have that clearly in the documentation
and the error you present to the user is the best option.

The other will be generate one gem for every platform and indicate
there the dependencies. Lot of work for you :p
 
J

Jarmo Pertman

Ok, but this is not best solution also since user:
1) gem install mylib
2) create a script and `require "mylib"`
3) run that script
4) get an error about missing dependency
5) nevertheless of just running gem install, user needs to run gem
install again

It just feels not user friendly way to solve it. Another way would be
to create separate gems of course, but it's not a good way either.

Jarmo Pertman
 
U

Uwe Kubosch

I have solved this by making the gem depend on the "bundler" gem, and then put the gem dependecies into a Gemfile, and run the equivalent of "bundle install" as a post-install script. This takes care of everything. The only thing I am missing is that the dependencies are visible when inspecting the gem.

Having RubyGems drop the gemspec dependencies in favor of Gemfile dependencies would be my preferred way.

--
With kind regards
Uwe Kubosch
Kubosch Consulting
(e-mail address removed)
http://kubosch.no/
 
L

Luis Lavena

I have solved this by making the gem depend on the "bundler" gem, and then put the gem dependecies into a Gemfile, and run the equivalent of "bundleinstall" as a post-install script.  This takes care of everything.  The only thing I am missing is that the dependencies are visible when inspecting the gem.

RubyGems post_install is not scripts, perhaps you're using extension
compilation to make that happen, which is intrusive to the user.

You're also bringing Bundler when the user might not want it into the
mix and slowing down the gem loading process.

Bundler is awesome for development, but is awful for runtime
dependency. You should not be imposing bundler to the user and even
less for runtime execution.

Also bundler do not handle properly all the platforms, using a
different concept of "platform" of what RubyGems understand and is
widely known.
 
L

Luis Lavena

Ok, but this is not best solution also since user:
1) gem install mylib
2) create a script and `require "mylib"`
3) run that script
4) get an error about missing dependency
5) nevertheless of just running gem install, user needs to run gem
install again

It just feels not user friendly way to solve it. Another way would be
to create separate gems of course, but it's not a good way either.

You can display a post_install message after you installed "mylib"
that tells:

mylib depends on platform specific components, please install "mylib-
windows" before you start using it.

And still rescue on the LoadError.

The other way around is what I mentioned, but then you will need to
generate one gem for every RubyGems platform: linux, darwin, freebsd,
mingw32, mswin32, etc and indicate the proper dependencies.

Even if the gem itself is not different.

I feel that is more work to do, don't you think?
 
U

Uwe Kubosch

[Note: parts of this message were removed to make it a legal post.]


RubyGems post_install is not scripts, perhaps you're using extension
compilation to make that happen, which is intrusive to the user.

You are right, I use the extension compilation to run the extra install step.

How is this intrusive?
You're also bringing Bundler when the user might not want it into the
mix and slowing down the gem loading process.

I would rather add Bundler than not have the gem install all its dependencies. The user experience is what matters, and this way all dependencies install correctly and the gem is ready for use regardless of the users platform.
Bundler is awesome for development, but is awful for runtime
dependency. You should not be imposing bundler to the user and even
less for runtime execution.

Why not? Bundler is awesome for runtime dependencies as well. It is the default mechanism for Ruby On Rails runtime dependencies.
Also bundler do not handle properly all the platforms, using a
different concept of "platform" of what RubyGems understand and is
widely known.


The platform concept of Bundler is different from RubyGems platform, but Bundler handles all platforms properly and the platform concept of Bundler is as well known and as intuitive as RubyGems.

If RubyGems alone would allow developers to solve the problem of dependencies varying with the user's platform, that is what I would use. As long as RubyGems falls short to solve the problem, we need to solve it some other way. Using Bundler solves the problem, and does it nicely.

--
With kind regards
Uwe Kubosch
Kubosch Consulting
(e-mail address removed)
http://kubosch.no/
 
L

Luis Lavena

You are right, I use the extension compilation to run the extra install step.

How is this intrusive?

If user grant RubyGems sudo to install the gem and it's dependencies,
you're sneaking something that the user was not aware of.

If the user using a gem list find this gem he didn't install, on
uninstallation no dependency warning will be triggered, and the
original gem will not work because of that.
I would rather add Bundler than not have the gem install all its dependencies.  The user experience is what matters, and this way all dependenciesinstall correctly and the gem is ready for use regardless of the users platform.

This is similar case to what Hoe did in the past, as add it as
dependency even that you used for development only. Search for it.
Why not?  Bundler is awesome for runtime dependencies as well.  It isthe default mechanism for Ruby On Rails runtime dependencies.

http://www.ibrasten.com/articles/2010/11/15/reducing-jruby-startup-by-ditching-bundler


The platform concept of Bundler is different from RubyGems platform, but Bundler handles all platforms properly and the platform concept of Bundler is as well known and as intuitive as RubyGems.

No, it doesn't, take for example JSON gem, is broken under 1.9.x or
1.8.x for Windows and even when the user decided to fix it manually,
bundler always force it's installation.

https://github.com/carlhuda/bundler/issues/635
https://github.com/carlhuda/bundler/issues/589
 
U

Uwe Kubosch

If user grant RubyGems sudo to install the gem and it's dependencies,
you're sneaking something that the user was not aware of.

If the user using a gem list find this gem he didn't install, on
uninstallation no dependency warning will be triggered, and the
original gem will not work because of that.

True. I consider this a flaw and would very much like to solve that, too.
This is similar case to what Hoe did in the past, as add it as
dependency even that you used for development only. Search for it.

The difference is that Bundler is a good gem for setting up runtime dependencies. It is not a development only gem.

Good article, and valid if your main concern is application startup time. My main concerns are ease of installation, and performance after startup. Bundler fits that need.
No, it doesn't, take for example JSON gem, is broken under 1.9.x or
1.8.x for Windows and even when the user decided to fix it manually,
bundler always force it's installation.

https://github.com/carlhuda/bundler/issues/635
https://github.com/carlhuda/bundler/issues/589


These are valid concerns, and it looks like they are being taken seriously, so hopefully they will be sorted out. I appreciate your efforts on improving Ruby on Windows.

If your gem hits any of these issues, you need to address them, and maybe using Bundler is not your solution. If your gem does not hit these issues, maybe you accept your gem will not be used on Windows, Bundler is a solution to the original problem of having a valid set of gems installed with your gem without the user having to do extra steps.

I would like to hear other solutions than using Bundler that enables the correct installation of dependent gems that vary with the user's platform.

--
With kind regards
Uwe Kubosch
Kubosch Consulting
(e-mail address removed)
http://kubosch.no/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top