---
title: "Using enable-load-relative flag in building Ruby binaries"
description: "Using enable-load-relative flag in building Ruby binaries"
canonical_url: "https://www.bigbinary.com/blog/use-of-enable-load-relative-flag-in-building-ruby-binaries"
markdown_url: "https://www.bigbinary.com/blog/use-of-enable-load-relative-flag-in-building-ruby-binaries.md"
---

# Using enable-load-relative flag in building Ruby binaries

Using enable-load-relative flag in building Ruby binaries

- Author: Vishal Yadav
- Published: June 20, 2023
- Categories: NeetoCI, Ruby

I'm working on building [NeetoCI](https://neeto.com/neetoci), which is a CI/CD
solution. While building precompiled Ruby binaries, we encountered some
challenges. This blog post explores the problems we faced and how we solved
them.

## Pre-compiled Ruby binaries

Pre-compiled Ruby binaries are distribution-ready versions of Ruby that include
optimized features for specific systems. These Ruby binaries save time by
eliminating the need to compile Ruby source code manually. Pre-compiled Ruby
binaries help users quickly deploy applications that use different versions of
Ruby on multiple machines.

[RVM](https://rvm.io/) (Ruby Version Manager) is widely used for managing Ruby
installations on Unix-like systems. RVM provides customized pre-compiled Ruby
binaries tailored for various CPU architectures. These binaries offer additional
features like readline support and SSL/TLS support. You can find them at
[RVM binaries](https://rvm.io/binaries/).

## The Need for pre-compiled Ruby Binaries

[NeetoCI](https://www.neeto.com/neetoci) must execute user code in a
containerized environment. A Ruby environment is essential for running Ruby on
Rails applications. However, relying on the system's Ruby version is impractical
since it may differ from the user's required version. Although rbenv or rvm can
be used to install the necessary Ruby version, this approach could be slow. To
save time, we chose to leverage pre-compiled Ruby binaries.

As a CI/CD system, NeetoCI must ensure that all versions of Ruby that an
application requires are always available. Hence, we decided to build our
binaries instead of relying on binaries provided by RVM. Also, this would allow
us to do more system-specific optimizations to the Ruby binary at build time.

## Building pre-compiled Ruby binaries

We built a Ruby binary following the
[official documentation](https://github.com/ruby/ruby/blob/master/doc/contributing/building_ruby.md)
. We were able to execute it on our local development machines. But the same
binary ran into an error in our CI/CD environment.

![Bad Interpreter](https://www.bigbinary.com/blog/images/images_used_in_blog/2023/use-of-enable-load-relative-flag-in-building-ruby-binaries/failing-binary-error-image.png)

```bash
$ bundle config path vendor/bundle
./ruby: bad interpreter: No such file or directory
```

To debug the issue, we initially focused on `$PATH`. However, even after
resolving the `$PATH` issues, the problem persisted. We conducted a thorough
investigation to identify the root cause. Unfortunately, not much was written on
the Internet about this error. There was no mention of it in the official
[Ruby documentation](https://github.com/ruby/ruby/blob/master/doc/contributing/building_ruby.md).

As the next step, we decided to download the binary for version 3.2.2 from
[RVM](https://rvm.io/binaries/). While examining the configuration file, we
noticed that the following arguments were used with the configure command during
the Ruby binary build process:

```bash
configure_args="'--prefix=/usr/share/rvm/rubies/ruby-3.2.2' '--enable-load-relative' '--sysconfdir=/etc' '--disable-install-doc' '--enable-shared'"
```

Here are the explanations of the configuration arguments:

1. `--prefix=/usr/share/rvm/rubies/ruby-3.2.2`: This specifies the directory
   where the Ruby binaries, libraries and other files will be kept after the
   installation is done.

2. `--enable-load-relative`: This specifies that Ruby can load relative paths
   for dynamically linked libraries. It allows the usage of relative paths
   instead of absolute paths when loading shared libraries. This feature can be
   beneficial in specific deployment scenarios.

3. `--sysconfdir=/etc`: This argument sets the directory where Ruby's system
   configuration files will be installed. In this case, it specifies the `/etc`
   directory as the location for these files.

4. `--disable-install-doc`: When this option is enabled, the installation of
   documentation files during the build process is disabled. This can help speed
   up the build process and save disk space, especially if you do not require
   the documentation files.

5. `--enable-shared`: Enabling this option allows the building of shared
   libraries for Ruby. Shared libraries enable Ruby to dynamically link and load
   specific functionality at runtime, leading to potential performance
   improvements and reduced memory usage.

In simpler terms, when the `--enable-load-relative` flag is enabled, the
compiled Ruby binary can search for shared libraries in its own directory using
the `$ORIGIN` variable.

When I built the binary on the Docker registry, then the passed `--prefix` was
something like `/usr/share/neetoci`. When the binary is built, then binary had
`/usr/share/neetoci` is hard-coded at various places. When we download this
binary and use in CI then in the CI environment, Ruby is looking for
`/user/share/neetoci` to load dependencies.

By enabling `--enable-load-relative` flag while building the binary Ruby will
not use the hard coded value. Rather Ruby will use `$ORIGIN` variable and will
search for the dependencies in the directory mentioned in `$ORIGIN`.

This is particularly helpful when the Ruby binary is relocated to a different
directory or system. By using relative paths with `$ORIGIN`, the binary can find
its shared libraries regardless of its new location. Without this flag, shared
libraries are loaded using absolute paths, which can cause issues if the binary
is moved to a different location and cannot locate its shared libraries.

In our specific use case, where we create and download binaries in separate
containers, we encountered an error due to the absolute paths. To overcome this,
we enabled the `--enable-load-relative` flag. This allowed the binary to find
its shared libraries successfully, and it worked as expected in our CI/CD
environment.

![Successful Build](https://www.bigbinary.com/blog/images/images_used_in_blog/2023/use-of-enable-load-relative-flag-in-building-ruby-binaries/passing-ruby-binary-image.png)

## Links

- [Human page](https://www.bigbinary.com/blog/use-of-enable-load-relative-flag-in-building-ruby-binaries)
