Forum: JRuby MRI/JRuby Bundler Gemspec/Gemfile Problem

486ca04f06d968004643ce5b47376ded?d=identicon&s=25 Keith B. (keith_b)
on 2013-06-12 20:27
(Received via mailing list)
Hi, everyone.

I'm writing a gem that can be used from both MRI Ruby and JRuby to talk
to
a Java library in a jar file.  In JRuby talking to the Java library
requires no special configuration, but from MRI Ruby I need to use the
rjb
(Ruby Java Bridge) gem.
So, I want to install the rjb gem if in MRI Ruby, bot want *not* to
install
it if in JRuby, since it requires some native building.
I have this in my gemspec, which works fine:
  unless /java/ === RUBY_PLATFORM    spec.add_dependency 'rjb'  end
However, when I run bundle in MRI, the resulting Gemfile.lock contains
the
rjb dependency without any condition not to use it in JRuby:
...    rake (10.0.4)    rjb (1.4.6)    rspec (2.13.0) ... So if I build
the
gem, distribute it, and then gem install it in JRuby, the gem install
tries
to build rjb, and fails because of the native extensions.
What's the best way to deal with this?  Should I duplicate the gem
dependencies, putting them in the Gemfile instead of the 'gemspec'
that's
there now?  Or build two different gems (I hope not)?
Thanks,Keith
2553a4e57589e8d210aaf7c1e29906c9?d=identicon&s=25 "Sébastien Le Callonnec" <slc_ie@yahoo.ie> (Guest)
on 2013-06-12 22:02
(Received via mailing list)
Hi Keith,

You do need to create a separate gem for the different platforms –
thankfully, rake-compiler (https://github.com/luislavena/rake-compiler)
makes it easy to do so.
I had described how over at SO
(http://stackoverflow.com/a/13540730/289466), but I should probably
stick that somewhere in the wiki too.

Regards,
Sébastien.

Le mer. 12 juin 2013 19:26:12 IST, Keith Bennett a écrit :
486ca04f06d968004643ce5b47376ded?d=identicon&s=25 Keith B. (keith_b)
on 2013-06-12 23:25
(Received via mailing list)
Sebastien -

I've been trying to get your instructions to work but have been unable.
 I've tried the following:

> rake native gem  # in MRI
...Don't know how to build task 'ext/my_gem_name/extconf.rb'...

> rake java gem  # in JRuby
...javac: no source files...

> rake gem
...Don't know how to build task 'gem'...

I gem installed rake-compiler.  Is it not there?

In my case, I don't need to compile anything.  The *only* difference is
that MRI has a dependency that JRuby does not (RJB).  What am I doing
wrong?

- Keith
748797a1a0dc3de4c50e722d90589129?d=identicon&s=25 Rhett Sutphin (Guest)
on 2013-06-12 23:52
(Received via mailing list)
Hi Keith,

I am not familiar with rake-compiler and I'm not sure it will help you
in this case, but I can give you an overview of what you need to
achieve.

When you have a gem that has different dependencies on different rubies,
you need to package the gem separately for each platform. Adding a
condition on the dependency in the gemspec is not sufficient; you
actually need to build and publish variants of the gem with different
values in the gemspec's "platform" attribute. (This is because the
gemspec that is packaged in the gem isn't the literal code you author in
the gemspec file -- it's a serialized representation derived from
interpreting the gemspec in the interpreter on which the gem is being
packaged. Any conditions will be evaluated in the published gemspec.)

One of my gems, ladle[1], has both JRuby and generic ruby versions. You
can take a look at its source[2] to see how this happens, but basically
I use RVM to package it separately on both MRI and JRuby and then
publish both.

I believe if you do handle the packaging like this, bundler will do the
right thing. I haven't tried it though, so I don't know for sure.

Rhett

[1]: http://rubygems.org/gems/ladle
[2]: https://github.com/NUBIC/ladle ; ladle.gemspec and meta.rakefile
are the key files
2553a4e57589e8d210aaf7c1e29906c9?d=identicon&s=25 "Sébastien Le Callonnec" <slc_ie@yahoo.ie> (Guest)
on 2013-06-13 00:28
(Received via mailing list)
Hi Keith,

As you mentioned, you have the following in your gemspec:

unless /java/ === RUBY_PLATFORM  spec.add_dependency 'rjb'  end

The gemspec file is the description of how to package your gem, so the
RUBY_PLATFORM here will be the one of the ruby you use to build/package
your gem, not the one you
486ca04f06d968004643ce5b47376ded?d=identicon&s=25 Keith B. (keith_b)
on 2013-06-13 05:21
(Received via mailing list)
Rhett and Sebastien -

Maybe I'm overthinking this...my code doesn't contain any extensions at
all, I just have a dependency on a gem on one platform but not the
other.
 I don't think I need rake-compile.

If I have to create one gem per platform, then I guess all I need to do
is
something like this:

rvm 1.9
./build_gem.sh

rvm jruby
./build_gem.sh

...where build_gem.sh is the shell script I posted at
https://gist.github.com/keithrbennett/5770915.

My gemspec file has this:

  is_jruby = /java/ === RUBY_PLATFORM
  spec.version = is_jruby ? CaptiveValidator::VERSION + '.java' :
CaptiveValidator::VERSION

I've seen other gems use an underscore instead (_java) (yours included,
Rhett), but when I try specifying that in the gemspec I get an error
from
the gem build:

Malformed version number string 0.1.0_java

Rhett, how did you do it?  Did you rename the file manually?  I could
certainly do that, but I assume if the gem build forbids it there is a
good
reason...or no?

Thanks,
Keith
748797a1a0dc3de4c50e722d90589129?d=identicon&s=25 Rhett Sutphin (Guest)
on 2013-06-13 05:34
(Received via mailing list)
Hi Keith,

> I've seen other gems use an underscore instead (_java) (yours included, Rhett),
but when I try specifying that in the gemspec I get an error from the gem build:
>
> Malformed version number string 0.1.0_java
>
> Rhett, how did you do it?  Did you rename the file manually?  I could certainly
do that, but I assume if the gem build forbids it there is a good reason...or 
no?

You don't want to change the version number. You want to change
`spec.platform`  if it is anything other than "ruby", rubygems will add
an appropriate platform suffix to the gem package name. The platform
attribute is also what rubygems (and hopefully bundler) will use to pick
the right gem to install on MRI vs. JRuby.

Rhett
486ca04f06d968004643ce5b47376ded?d=identicon&s=25 Keith B. (keith_b)
on 2013-06-13 15:36
(Received via mailing list)
Rhett -

Thanks, I realized that shortly after writing you, and was composing
another message when you responded.

I'm now doing the same thing with another gem, and gem build appends
".java" to the gem file name instead of "-java".  Any idea why?  The
".java" is interpreted by Gem in a Box as meaning it's a prerelease
version
(a gem convention I think), but that was not my intention.

Also, given that the Gemfile.lock file will differ in the respective
platform, how do you deal with committing it to the version control
repo?

- Keith
486ca04f06d968004643ce5b47376ded?d=identicon&s=25 Keith B. (keith_b)
on 2013-06-14 15:45
(Received via mailing list)
Sorry, I could swear I checked the gemspec and version files, but I had
made the .java stuff happen myself.

I'm still perplexed as to how to handle committing the Gemfile.lock,
given
that it will differ for the two platforms.

- Keith
B80b0b3f9bfd5804ab03f8ca365bb7f1?d=identicon&s=25 Brendan G. (brendan_g)
on 2013-06-14 16:34
(Received via mailing list)
I think the recommendation when developing a gem is to not check your
Gemfile.lock into source control so it would just be generated for each
platform you create the gem for.

http://yehudakatz.com/2010/12/16/clarifying-the-ro...

"*When developing a gem*, use the
gemspec<http://gembundler.com/rubygems.html> method
in your Gemfile to avoid duplication. In general, a gem’s Gemfile should
contain the Rubygems source and a single gemspec line. *Do not check
your
Gemfile.lock into version control*, since it enforces precision that
does
not exist in the gem command, which is used to install gems in practice.
Even if the precision could be enforced, you wouldn’t want it, since it
would prevent people from using your library with versions of its
dependencies that are different from the ones you used to develop the
gem."
748797a1a0dc3de4c50e722d90589129?d=identicon&s=25 Rhett Sutphin (Guest)
on 2013-06-14 17:10
(Received via mailing list)
Hi,

> I'm still perplexed as to how to handle committing the Gemfile.lock, given that
it will differ for the two platforms.

I don't have experience doing this with a real application, but I just
tried a trivial test app and it seemed to work. I created a Gemfile with
a gem that had both generic and java versions. Then I did `bundle
install` on MRI, which created a Gemfile.lock. And then I did `bundle
install` on JRuby, which updated Gemfile.lock so that it included the
java-platform dependencies also. Then I switched back to MRI and did
`bundle install` a third time; the java platform information in
Gemfile.lock was preserved.

So, try it and see.

Rhett
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.