Fixing Ruby 2.1.1 on Arch

I recently tried to install Ruby 2.1.1 on my Arch box with ruby-install. Unfortunately, there's a bug on Arch Linux in the current stable build (2.1.1p76).

$ ruby-install ruby 2.1.1
  ...
  make[2]: Entering directory '~/src/ruby-2.1.1/ext/readline'
  compiling readline.c
  readline.c: In function ‘Init_readline’:
  readline.c:1977:26: error: ‘Function’ undeclared (first use in this function)
       rl_pre_input_hook = (Function *)readline_pre_input_hook;
                            ^
  readline.c:1977:26: note: each undeclared identifier is reported only once for each function it appears in
  readline.c:1977:36: error: expected expression before ‘)’ token
       rl_pre_input_hook = (Function *)readline_pre_input_hook;
                                      ^
  readline.c: At top level:
  readline.c:634:1: warning: ‘readline_pre_input_hook’ defined but not used [-Wunused-function]
   readline_pre_input_hook(void)
   ^
  Makefile:228: recipe for target 'readline.o' failed
  make[2]: *** [readline.o] Error 1
  make[2]: Leaving directory '~/src/ruby-2.1.1/ext/readline'
  exts.mk:198: recipe for target 'ext/readline/all' failed
  make[1]: *** [ext/readline/all] Error 2
  make[1]: Leaving directory '~/src/ruby-2.1.1'
  uncommon.mk:180: recipe for target 'build-ext' failed
  make: *** [build-ext] Error 2
  !!! Compiling ruby 2.1.1 failed!

The bug is fixed in trunk, but the fix has not yet been released. Of course, if you have a system Ruby installed on Arch, you'll see that it's version is 2.1.1. So how did the Arch package manage to compile 2.1.1 in spite of this bug?

The Arch team makes it easy to find the answer to this question. We can view the package from the Arch repos and see what patches they have applied. Start off by going to the package page for your architecture. For me, that's here. On the right side of the page, follow the link to view the source files:

Source Files

If there are any updates to the source made by the package maintainers, you will see patch files for them. In this case, there is one patch file:

From 4c4da3fc650a3595ecc06f49072f1ffae07db706 Mon Sep 17 00:00:00 2001  
From: Thomas Dziedzic <gostrc@gmail.com>  
Date: Sat, 1 Mar 2014 21:41:28 -0800  
Subject: [PATCH] Fix undeclared identifier error by using the actual type of  
 rl_pre_input_hook

---
 ext/readline/readline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ext/readline/readline.c b/ext/readline/readline.c  
index 659adb9..7bc0eed 100644  
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -1974,7 +1974,7 @@ Init_readline()

     rl_attempted_completion_function = readline_attempted_completion_function;
 #if defined(HAVE_RL_PRE_INPUT_HOOK)
-    rl_pre_input_hook = (Function *)readline_pre_input_hook;
+    rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook;
 #endif
 #ifdef HAVE_RL_CATCH_SIGNALS
     rl_catch_signals = 0;
-- 
1.9.0  

As you can see, this patch fixes the bug we saw when compiling Ruby. We can use this patch file with ruby-install to fix the bug! There's just one little fix to apply: the line numbers in the patch file don't match the line number from our compilation error. The compile error reported a problem on line 1977, but this patch applies the change to line 1974. All we have to do is update the patch to apply to the correct line. Create a patch file on your computer. Paste in the patch from the Arch package, and update the line number. Your file should look like this:

From 4c4da3fc650a3595ecc06f49072f1ffae07db706 Mon Sep 17 00:00:00 2001  
From: Thomas Dziedzic <gostrc@gmail.com>  
Date: Sat, 1 Mar 2014 21:41:28 -0800  
Subject: [PATCH] Fix undeclared identifier error by using the actual type of  
 rl_pre_input_hook

---
 ext/readline/readline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ext/readline/readline.c b/ext/readline/readline.c  
index 659adb9..7bc0eed 100644  
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -1977,7 +1977,7 @@ Init_readline()

     rl_attempted_completion_function = readline_attempted_completion_function;
 #if defined(HAVE_RL_PRE_INPUT_HOOK)
-    rl_pre_input_hook = (Function *)readline_pre_input_hook;
+    rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook;
 #endif
 #ifdef HAVE_RL_CATCH_SIGNALS
     rl_catch_signals = 0;
-- 
1.9.0  

Now, we can finish intalling Ruby 2.1.1! Just tell ruby-install to use the patch file we just created:

$ ruby-install -p path/to/fix-readline.patch ruby 2.1.1

The installation should succeed, and you can now use your favorite Ruby version manager to use Ruby 2.1.1.