Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wishlist] Having Linux cross compilers would be nice. #13

Closed
nicolasnoble opened this issue Feb 11, 2016 · 3 comments
Closed

[wishlist] Having Linux cross compilers would be nice. #13

nicolasnoble opened this issue Feb 11, 2016 · 3 comments

Comments

@nicolasnoble
Copy link

Basically, once I was done dealing with #12 on my side, I realized that I could exploit rake-compiler-dock for building the Linux gems. And after pushing it a bit, it actually worked. It'd be fantastic if these changes were integrated. This way, rake-compiler-dock would be able to create not only Windows, but also Linux "fat" gems.

Here's what I've done, and the issues I've encountered.

  • First, I had to install the gcc-multilib package in order to be able to create 32 bits binaries and libraries.
  • Then I added lines to spawn the linux 64 bits versions of ruby
  • Next, I spawned the linux 32 bits versions of ruby. The only main changes were to add -m32 to CFLAGS and LDFLAGS.
  • However, from here, I encountered an interesting issue. From one version of Ruby to another, the runtime's aren't named the same way. RVM would create runtimes named for example libruby.so.2.2, but the stock Debian package would have a libruby-2.2.so.2.2 library.
    2016-02-09
    Of course, linking against the static version of libruby instead of the dynamic version is a bad idea, since the Ruby loader will properly check if we're not trying anything like that, which would wreck havok with the garbage collector and ruby_xmalloc.

Interestingly enough, when compiling the MacOS versions of the rake-compiler rubies, as I am patching cross-ruby.make from rake-compiler, I didn't get that issue at all. The "static" version of the runtime is basically empty, and relying on either the fact everything is loaded using RTLD_LAZY|RTLD_GLOBAL, or that the main binary is linked using -rdynamic.

Now this time, I could've tried to also modify cross-ruby.rake into the Docker image, but I chose a more drastic solution: in these 3 lines, I nuked the .so version, made the -static.a version empty of everything, and moved them to simply .a files. This way I am letting mkmf link against an empty static runtime, forcing the linker to create imports for every symbols of the runtime, without actually specifying an import library. At load time, just like what happens under MacOS, the system will resolve the symbols against the already loaded runtime, which is fine since we're constructing a fat gem this way.

Possible alternate solutions to that... pretty dirty hack:

  • compile all of the mingw versions first, then patch cross-ruby.rake to spawn static versions only, then compile all of the linux versions.
  • patch mkmf.rb to remove the -lruby.

These changes enabled me to cross compile gems for Linux 32 and 64 bits, which work not only with rvm, but with many different versions of Rubies from different distributions.

So I think these additions would be great, not just for grpc, but for the rest of the community as well.

@larskanis
Copy link
Member

Building binary gems for Linux wasn't a focus of mine, since compiler and development packages are easily available on Linux for each gem user. This is different to Windows.

Nevertheless your trick with libruby is very interesting. That removes a big issue with the binary compatibility between different distributions. It could be an option for gems with no further dependent libraries (like grpc). I wonder how much that differs from a --enable-static compiled ruby.

nokogiri is a gem with a very slow installation, so it would benefit from a binary version. I'll try your solution with it.

@nicolasnoble
Copy link
Author

Our focus was easy binary distribution. The main issue is that we can't really call grpc easy to install if it requires a full compiler suite for it, and as you said, binary compatibility between different distribution wasn't making this easy. At the end, we managed to get something working for a lot of different platforms.

@larskanis
Copy link
Member

Thank you @nicolasnoble for your great description! I've added Linux binary gem support to the current master branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants