-
Notifications
You must be signed in to change notification settings - Fork 34
[wishlist] Having Linux cross compilers would be nice. #13
Description
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-multilibpackage 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
-m32toCFLAGSandLDFLAGS. - 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 alibruby-2.2.so.2.2library.

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 andruby_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.rbto 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.