Cannot install ruby gem in OSX

Hi,

I am trying to install a gem (clipper) in OSX by using

Gem.install "clipper"

but I get the error

Error: #<Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

"/Applications/SketchUp 2015/SketchUp.app/Contents/Frameworks/Ruby.framework/Versions/2.0/bin/ruby" extconf.rb
sh: /Applications/SketchUp 2015/SketchUp.app/Contents/Frameworks/Ruby.framework/Versions/2.0/bin/ruby: No such file or directory

The installation works file if I run it from the terminal.

I have checked and the bin folder is actually not there. Any advice?

Thanks

Unfortunately, SketchUp does not come properly set up to build compiled Ruby Gems under Mac OS X. What you are seeing is just the tip of the iceberg. I’ve fiddled with it extensively, manually tweaking configuration files, etc. and never got it to work. I think that a few people have managed to compile Gems outside SketchUp and get them to install, but it is tricky to get everything right since SketchUp uses a patched Ruby interpreter. At this point it is pretty much hit-or-miss.

I recently had success installing moving_images gem ‘manually’ into my SU Gem folder…
to get it to work required a standard gem instal in ‘Terminal.app’ and then carefully moving all the new files into my SU Gem folder…
I think I will automate it the next time, maybe use ditto to copy all new files after the instal…

john

Thanks slbaumgartner,

I had the same problem in Windows 7, but I was able to compile the gem in Ruby (system) and then just copy the clipper.so file in the Sketchup plugin folder. Maybe I could do something similar in OSX?

The fact is that clipper is quite important for my plugin. Maybe an alternative could be to launch a ruby script outside SketchUp.

Build outside and copy the dylib and other files is what John describes. Sometimes it works, sometimes it doesn’t. You’ll know when the Gem either doesn’t work or SketchUp blows up!

I not only copied over this lot, but also the specification and doc files, then it worked…
john

Thanks. I will give it a go. Hope it will work!

Gems are a hit and miss in SketchUp. Ruby in large part assumes to be a console app. When we wrangle the Ruby interpreter into a GUI applications all sorts of complications occur - and we have no documentation to follow. :frowning:

Are you planning to distribute extensions where you bundle these gems? Or is it for personal use?

At the moment it is for personal use, but the long term plan is to distribute it.

There is a challenge there - if you distribute your own version of the gems. If multiple people do that same thing there can be a conflict if they try to use/load different versions. We’ve seen this happening.

We’ve also seen people bundle Ruby 1.8 libs in the past without making version checks for the Ruby environment causing lots of problems when the extension is installed under Ruby 2.0.

If possible - edit the libs you distribute into your own namespace. Now, some gems modify core classes making this difficult. These are also the type of gems that often lead to clashes.

All my scripts are in my own namespace. I don’t think this gem alters any core class

It looks self contained

That looks nice and clean. That’s good. I’d still recommend you tweak the version you distribute to confine it to your own extension to be sure you won’t run into any future conflicts.

1 Like

I very much like the way they (the binder) wrapped the library class within a Ruby mixin module.
It is actually meant to be mixed into the programmer’s namespaces:

module AuthorToplevelNamespace
  module ThisPlugin

    require 'clipper' # assumes gem was pre-installed
        include Clipper # includes the Clipper mixin module

        # Now the local constant Clipper is a proxy lookup
        # to the ::Clipper::Clipper class.(Because identifiers 
        # are constants and get mixed in during the include.)

        def self::union_method(
          a = [[0, 0], [0, 100], [100, 100], [100, 0]] ,
          b = [[-5, 50], [200, 50], [100, 5]]
        )
          c = Clipper::new()
          c.add_subject_polygon(a)
          c.add_clip_polygon(b)
          c.union( :non_zero, :non_zero )
        end
 
  end
end

(1) This library was gemified, but unfortunately it is uncompiled.

(2) The version you cite is actually a year out of date. This is a good example of what Thomas was talking about. There then exists the high probability that someone else will package to later version, or if you packaged the later, someone else would likely package the earlier.

This is the latest version 5.0.3 which uses the 5.x Clipper library:
https://rubygems.org/gems/ruby_clipper
Which points at project:

So to do what Thomas says, you need to change the “rbclipper.cpp” file a bit.

Change line 353 to:

VALUE top   = rb_define_module("Rojj");

… or whatever your toplevel namespace module name is.

And change line 354 to:

VALUE mod   = rb_define_module_under(top,"Clipper");


Then the “version.rb” file needs to be also wrapped within your toplevel module.
Example:

module Rojj::Clipper
  # Keep first two components sync'd to Clipper's major/minor.
  # Last is our build number based on that.  Hopefully there
  # won't be too much churn re: Clipper's version vs. the bindings.
  VERSION = "5.0.3"
end
1 Like

Thanks a lot Dan for the detailed answer. Will test this and let you know.

OK. It was more complicated than i thought. A bit of help would be greatly appreciated.

Dan, are you saying that i should download the latest version of the gem, make the modifications you suggest and then install from the local (modified) gem file?

After that I should be able to move the compiled files to the SU plugin folder as I do in Windows 7?

Sorry if the questions are dumb, but I am a bit stuck.

Yes.

The only files that really belong in the “Plugins” folder, are the SketchupExtension class registration scripts. All plugin files and support libraries should be in sub-directories.

In the case of custom compiled gems, it is really best to convert their file & folder structure to be SketchupExtension class compatible. That means putting the compiled .so file in a plugin subdirectory (named ToplevelModule_GemName,) and write a SketchupExtension registration script for the “Plugins” directory (named ToplevelModule_GemName.rb.)

However … if you modify it as outlined above, it will become a library module wrapped within YOUR toplevel module. Noone else will be expected to use it in that way, and it will not clash with any other distribution. No one else’s distribution will be expected to wrap the gem module within your namespace, so it is safe from other plugins.

If it will only be distro’d with your plugin (and your plugin is SketchupExtension class compatible,) then you won’t need to do the above. Just package the library file along with your plugin’s other files in it’s plugin subdirectory (named ToplevelModule_PluginName.) Some where usually at the top of your plugin’s loader script, you would make a call like:
require File.dirname(__FILE__)<<"/ToplevelModule_GemName.so"
or if you know the plugin sub-dir name will not change:
require "ToplevelModule_PluginName/ToplevelModule_GemName.so"

If you look at some of Thomas’ plugins, you’ll see how he deals with distributing Mac compiled libs, along with two separate libs for Windows (32bit and 64bit.)

You can probably make things easier for your distribution by simply extracting the gem content (which you now have wrapped in your namespace) into the support folder of your extension directly.

1 Like

I said that, but it was hidden in all my rambling. (sorry)