SU2019 Requires Multiple Binaries

I noticed SU2019 has two different Ruby builds. I am to release a C++ extension, I had an issues where users would complain about SU2019 not being functional. And that was due to them using an older version of SU2019. My binaries were built for the latest version of SU2019. Up until now I have been asking users to update to the latest SU2019 version whenever they have a problem with loading on SU2019. I am wondering how other developers approach this problem. Do you build just a single binary for SU2019 aka Ruby 2.5 or multiple binaries targeting the different Ruby version of SU2019? Or do you just drink your hot mocha and call it a day?

This is a good thing as cryptography and SSL libs were also updated late in the 2019 release cycle.

You may run into the same thing with 2021 as it began with Ruby 2.7.1 and has just been updated to 2.7.2.

1 Like

I noticed SU2019 has two different Ruby builds

They only differ in the patch number. Ruby C Extensions should remain compatible within major.minor Ruby versions they are built against.

Do you have some more details on what failed on older SU2019 versions?

I need a link to download SU2019.1 (where Ruby version was 2.5.1). Othwerwise, I cannot prove it… A link for Windows

Actually a link to SU2019.0 might be even better. Perhaps the change has nothing to do with the Ruby change but with something else.

Ruby 2.5.1 had a bad logic bug (affected if statements). That was the main reason the patch version was updated in SU2019.2. I wouldn’t attempt to support or debug any Ruby issues under SU2019.1 and SU2019.0.

That being said, even if your C extension was built against 2.5.1 binaries you are fine with 2.5.5. The binary interface is the same. I suspect you got hit by the logic bug in Ruby 2.5.1 and not actually binary incompatibility.

I have dug up the error. I had a couple of users report it and apparently, as far as I am aware, it only occurs on Mac OS X SU2019.0.684. Forget my rambling about Windows:

dlopen(/users/USERNAME/library/application support/sketchup 2019/sketchup/plugins/ams_clothworks/libraries/1.7.4c/osx64/2.5/cw_lib.bundle, 9): Library not loaded: @executable_path/../Frameworks/Ruby.framework/Versions/2.5.5/Ruby

  Referenced from: /users/USERNAME/library/application support/sketchup 2019/sketchup/plugins/ams_clothworks/libraries/1.7.4c/osx64/2.5/cw_lib.bundle

  Reason: image not found - /users/USERNAME/library/application support/sketchup 2019/sketchup/plugins/ams_clothworks/libraries/1.7.4c/osx64/2.5/cw_lib.bundle>

/users/USERNAME/library/application support/sketchup 2019/sketchup/plugins/ams_clothworks/extension_manager.rbe:173:in `rescue in block in require_all'

/users/USERNAME/library/application support/sketchup 2019/sketchup/plugins/ams_clothworks/extension_manager.rbe:169:in `block in require_all'

/users/USERNAME/library/application support/sketchup 2019/sketchup/plugins/ams_clothworks/extension_manager.rbe:165:in `each'

/users/USERNAME/library/application support/sketchup 2019/sketchup/plugins/ams_clothworks/extension_manager.rbe:165:in `require_all'

/users/USERNAME/library/application support/sketchup 2019/sketchup/plugins/ams_clothworks/main.rbe:746:in `<main>'

/Applications/SketchUp 2019/SketchUp.app/Contents/Resources/Content/Tools/extensions.rb:197:in `eval'

/Applications/SketchUp 2019/SketchUp.app/Contents/Resources/Content/Tools/extensions.rb:197:in `require'

/Applications/SketchUp 2019/SketchUp.app/Contents/Resources/Content/Tools/extensions.rb:197:in `load'

/Users/USERNAME/Library/Application Support/SketchUp 2019/SketchUp/Plugins/ams_ClothWorks.rb:38:in `register_extension'

/Users/USERNAME/Library/Application Support/SketchUp 2019/SketchUp/Plugins/ams_ClothWorks.rb:38:in `<module:ClothWorks>'

/Users/USERNAME/Library/Application Support/SketchUp 2019/SketchUp/Plugins/ams_ClothWorks.rb:7:in `<module:AMS>'

/Users/USERNAME/Library/Application Support/SketchUp 2019/SketchUp/Plugins/ams_ClothWorks.rb:6:in `<top (required)>'

Two users who updated to newer SU2019 were able to resolve the issue.

It looks like I built the binary with Ruby2.5.5, which is not available with Ruby2.5.1. I wonder if rebuilding with 2.5.1 would make it compatible across.

Also, the ruby-c-extension-examples seems to be using Ruby 2.5.1: https://github.com/SketchUp/ruby-c-extension-examples/tree/master/ThirdParty/lib/mac/2.5/Ruby.Framework/Versions

Where as the SketchUp Developer SDK | SketchUp Extension Warehouse, Previous Versions section, SU2019.3 is using Ruby 2.5.5 for the framework (\SDK_Mac_2019-3-252\samples\common\ThirdParty\ruby\lib\mac\Ruby.Framework\Versions).

Which one should we use? If the framework version does not matter, then how come I had the error above? It seems to be a dll loading error.

Also, as Dan pointed out in the first post SU2021 uses Ruby 2.7.1 and Ruby 2.7.2. Will binaries complied with Ruby 2.7.2 work with original SU2021 versions using Ruby 2.7.1?

That might depend on how your binary link to the framework. The framework has a Ruby binary but also a few aliases with version info in the filename. If you linked against one of the versioned aliases, for instance you linked against libruby.2.5.5.dylib then that would break on versions that had libruby.2.5.1.dylib.

Can you check your link dependencies using otool? Post them back here?

I checked with the binaries of the Ruby C Extension example project:

mac-mini-2014:ruby-c-extension-examples thomas$ otool -L Release\ \(2.7\)/SUEX_HelloWorld.bundle

Release (2.7)/SUEX_HelloWorld.bundle:
	@executable_path/../Frameworks/Ruby.framework/Versions/2.7.1/Ruby (compatibility version 2.7.0, current version 2.7.1)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 905.6.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)
mac-mini-2014:ruby-c-extension-examples thomas$ otool -L Release\ \(2.5\)/SUEX_HelloWorld.bundle

Release (2.5)/SUEX_HelloWorld.bundle:
	@executable_path/../Frameworks/Ruby.framework/Versions/Current/Ruby (compatibility version 2.5.0, current version 2.5.1)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 905.6.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)
mac-mini-2014:ruby-c-extension-examples thomas$ otool -L Release\ \(2.2\)/SUEX_HelloWorld.bundle

Release (2.2)/SUEX_HelloWorld.bundle:
	@executable_path/../Frameworks/Ruby.framework/Versions/Current/libruby.2.2.0.dylib (compatibility version 2.2.0, current version 2.2.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 905.6.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)
mac-mini-2014:ruby-c-extension-examples thomas$ otool -L Release\ \(2.0\)/SUEX_HelloWorld.bundle

Release (2.0)/SUEX_HelloWorld.bundle:
	@executable_path/../Frameworks/Ruby.framework/Versions/Current/libruby.2.0.0.dylib (compatibility version 2.0.0, current version 2.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 905.6.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)

The key paths used:

@executable_path/../Frameworks/Ruby.framework/Versions/2.7.1/Ruby (compatibility version 2.7.0, current version 2.7.1)
@executable_path/../Frameworks/Ruby.framework/Versions/Current/Ruby (compatibility version 2.5.0, current version 2.5.1)
@executable_path/../Frameworks/Ruby.framework/Versions/Current/libruby.2.2.0.dylib (compatibility version 2.2.0, current version 2.2.0)
@executable_path/../Frameworks/Ruby.framework/Versions/Current/libruby.2.0.0.dylib (compatibility version 2.0.0, current version 2.0.0)

As you can see Ruby 2.0, 2.2 and 2.5 link against the Current alias path. 2.0 and 2.2 uses a versioned dylib name, but the compatibility alias. Ruby 2.5 links against Current/Ruby - which is probably the better path to link against.

2.7 here is probably problematic. This is where I’d expect to break when running inside SU with Ruby 2.7.1. (In fact, I think that is a result of us messing up how we packaged Ruby 2.7 and we had to keep a 2.7.1 alias when we updated to 2.7.2.

So I think your 2.5.1 vs 2.5.5 issues are related to this. You might have to use install_name_tool to correct the rpath of your binary.

Here are my results

Antons-Mac-mini:2.7 anton$ otool -L ./cw_lib.bundle
./cw_lib.bundle:
	/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 158.0.0)
	/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 23.0.0)
	@rpath/SketchUpAPI.framework/Versions/A/SketchUpAPI (compatibility version 1.0.0, current version 1.0.0)
	@executable_path/../Frameworks/Ruby.framework/Versions/2.7.1/Ruby (compatibility version 2.7.0, current version 2.7.1)
	/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1560.12.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
	/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1671.10.106)
	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1560.12.0)

Antons-Mac-mini:2.5 anton$ otool -L ./cw_lib.bundle
./cw_lib.bundle:
	/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 158.0.0)
	/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 23.0.0)
	@rpath/SketchUpAPI.framework/Versions/A/SketchUpAPI (compatibility version 1.0.0, current version 1.0.0)
	@executable_path/../Frameworks/Ruby.framework/Versions/2.5.5/Ruby (compatibility version 2.5.0, current version 2.5.5)
	/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1560.12.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
	/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1671.10.106)
	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1560.12.0)

Antons-Mac-mini:2.2 anton$ otool -L ./cw_lib.bundle
./cw_lib.bundle:
	/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 158.0.0)
	/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 23.0.0)
	@rpath/SketchUpAPI.framework/Versions/A/SketchUpAPI (compatibility version 1.0.0, current version 1.0.0)
	@executable_path/../Frameworks/Ruby.framework/Versions/Current/libruby.2.2.0.dylib (compatibility version 2.2.0, current version 2.2.0)
	/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1560.12.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
	/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1671.10.106)
	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1560.12.0)

Antons-Mac-mini:2.0 anton$ otool -L ./cw_lib.bundle
./cw_lib.bundle:
	/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 158.0.0)
	/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 23.0.0)
	@rpath/SketchUpAPI.framework/Versions/A/SketchUpAPI (compatibility version 1.0.0, current version 1.0.0)
	@executable_path/../Frameworks/Ruby.framework/Versions/Current/libruby.2.0.0.dylib (compatibility version 2.0.0, current version 2.0.0)
	/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1560.12.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
	/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1671.10.106)
	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1560.12.0)

I prefer to reconfigure Xcode or the Ruby framework over using install name tool. But it’s weird that it is like that. As far as I remember, I only had to drag and drop the Ruby framework into xCode and it would automatically set the link path like that.

Yea, but I think we messed up the symlinks in one of the releases so that XCode ends up linking against a patch-version path. Manual adjustment might be required.