Skip to content

Instantly share code, notes, and snippets.

@wycats
Created May 1, 2012 23:20
Show Gist options
  • Save wycats/2572313 to your computer and use it in GitHub Desktop.
Save wycats/2572313 to your computer and use it in GitHub Desktop.
otool -L results on Tokaido vs. rvm1 Ruby

One goal of Tokaido is to reduce the external dependencies of the precompiled Ruby.

There are several parts of the Ruby standard library that are normally linked against dylibs in your system. One such example is OpenSSL. To reduce external dependencies and the possibility of future failure (for example, if Apple removes OpenSSL from a future release), we would like to statically link these precompiled parts of the standard library instead of dynamically linking.

Also worth noting: psych depends on libyaml, which doesn't come with OSX to begin with. We do not want to rely upon libyaml existing in the system in order to use the precompiled Ruby, so we statically compile libyaml into psych.

In the output below, you can see that Tokaido compiled Ruby has dependencies only on libSystem and libobjc, which are extremely stable OSX libraries, and not on libruby, libssl or libcrypto. Instead, those libraries are statically compiled into openssl.bundle. This increases the portability of the precompiled Ruby and eliminates a number of possible failure scenarios.

# otool -L prints a list of the shared libraries this .bundle file
# is linked against. We will run it first against the Tokaido ruby
# and then against the rvm installed Ruby
# running against Tokaido
$ otool -L lib/ruby/1.9.1/x86_64-darwin11.3.0/openssl.bundle
lib/ruby/1.9.1/x86_64-darwin11.3.0/openssl.bundle:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
# running against rvm Ruby
$ otool -L lib/ruby/1.9.1/x86_64-darwin11.3.0/openssl.bundle
lib/ruby/1.9.1/x86_64-darwin11.3.0/openssl.bundle:
/Users/wycats/.rvm/rubies/ruby-1.9.3-p0/lib/libruby.1.9.1.dylib (compatibility version 1.9.1, current version 1.9.1)
/usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 44.0.0)
/usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 44.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
# running against system Ruby
$ otool -L lib/ruby/1.8/universal-darwin11.0/openssl.bundle
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin11.0/openssl.bundle:
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/libruby.1.dylib (compatibility version 1.8.0, current version 1.8.7)
/usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
/usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
@regularfry
Copy link

Are the changes which enable this something that can be pushed upstream? MRI is supposed to have a static build option, but in my experience it's not been usable without extension hackery.

@wycats
Copy link
Author

wycats commented May 2, 2012

All of the work uses existing MRI flags. The trick is getting the OSX linker to find and use the .a files from the dependencies. I don't think it's in scope for MRI to provide tooling for downloading and statically building dependencies, do you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment