Search code examples
rubyrubygemscpu-architecture

How does gem decide, which arch-specific gem to install?


For example; if I want to install any architecture-dependent gem, like nokogiri (xml library for ruby), but for any architecture-dependent gem, the case is the same.

I use an x86 distribution, but on an x86_64 kernel. My ruby is 32-bit, but a gem install nokogiri installs the 64-bit version (what will cause an error, because its shared lib can not link to the 32-bit ruby).

How is it being decided? My ruby is 32-bit, I want the 32-bit gem. The problem is very similar in an armhf/arm64 constellation or if I am trying to use any different emulation layer (like qemu-user or cygwin or wine). In general, I want to install the gem which matches my ruby interpreter and not the one which is autodetected by something.

What to do?


Solution

  • After tracking the ruby internals a little, I found these:

    • The current used architecture is coming from the internal rbconfig.rb of the local ruby. In my system is it in /usr/lib/i386-linux-gnu/ruby/3.1.0/rbconfig.rb. Check for RBCONFIG["arch"] in that file. That is an usual gnu-style architecture triplet.
    • This triplet is decided during the compilation of that ruby instance and there is no common way to alter it. You can edit this file if you wish to, but the results will be likely an unusable ruby interpreter.
    • In the compilation time, this triplet is coming from an arch command, which is a trivial tool with the same result an uname -m. This command checks for the actually used kernel architecture and not the one you are compiling for!

    Thus, for example, in a 32-bit system on a 64-bit kernel, arch and uname -m reports x86-64 and not i386 (or x32).

    However, you can alter this quite easily with the flag --target to the compilation script. In the specific case if you want to compile a 32-bit ruby on a 64-bit system, use configure --target=i386-linux-gnu, even if it does not look needed (because you are using a 32-bit gcc).