Building Ruby Gem Native Extensions in GUIX

Hi there, I’m having trouble building a native extension for a Ruby Gem.

The gem is ‘byebug’, and it comes with a native extension written in C.

From this video, I found that installing Ruby gems, in general, should be covered by guix install ruby-<gem>, which handles installing gems altogether.

Using guix install ruby-<gem>, basically installs a ruby gem as any other guix package,. from what I understand.
The installation actually succeeds, but when executing `ruby -e “require ‘byebug’”, I get:

Ignoring byebug-11.1.3 because its extensions are not built. Try: gem pristine byebug --version 11.1.3
<internal:/gnu/store/nkp7immncpclk9wrkq09835242rgqbn3-ruby-3.2.3/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require': cannot load such file -- byebug (LoadError)
	from <internal:/gnu/store/nkp7immncpclk9wrkq09835242rgqbn3-ruby-3.2.3/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'
	from -e:1:in `<main>'


Executing gem pristine byebug gives me the error:

ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /gnu/store/lryjnwjlwr8xrvxs4l59c0anhn4vjfcr-profile/lib/ruby/vendor_ruby directory.

which is comprehensible, as I cannot compile the native extension, into the /gnu store.
However, this seems to imply that I cannot install and use byebug when installing byebug as a guix package. The gem’s storage location is simply immutable to me and compiling a native extension can’t happen in that folder.
So, there is also the option of installing gems into the home directory, specifying GEM_PATH and GEM_HOME.
By doing to I can actually install gems via `gem install .

Still, when wanting to install a native extension for byebug, there is an issue.

  • I can navigate to the ext/byebug folder and execute ruby extconf.rb to generate a Makefile
  • Then execute make install and that’s where I receive an error that I cannot properly comprehend anymore.
x@guix-em ~/ruby-gems/gems/byebug-11.1.3/ext/byebug $ make
compiling breakpoint.c
In file included from /gnu/store/nkp7immncpclk9wrkq09835242rgqbn3-ruby-3.2.3/include/ruby-3.2.0/ruby/defines.h:16,
                 from /gnu/store/nkp7immncpclk9wrkq09835242rgqbn3-ruby-3.2.3/include/ruby-3.2.0/ruby/ruby.h:25,
                 from /gnu/store/nkp7immncpclk9wrkq09835242rgqbn3-ruby-3.2.3/include/ruby-3.2.0/ruby.h:38,
                 from byebug.h:4,
                 from breakpoint.c:1:
/home/x/.guix-profile/include/stdio.h:52:9: error: unknown type name ‘__gnuc_va_list’
   52 | typedef __gnuc_va_list va_list;
      |         ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:52:24: error: conflicting types for ‘va_list’; have ‘int’
   52 | typedef __gnuc_va_list va_list;
      |                        ^~~~~~~
In file included from /home/x/.guix-profile/include/stdarg.h:10,
                 from /gnu/store/nkp7immncpclk9wrkq09835242rgqbn3-ruby-3.2.3/include/ruby-3.2.0/ruby/ruby.h:23:
/home/x/.guix-profile/include/bits/alltypes.h:326:27: note: previous declaration of ‘va_list’ with type ‘va_list’ {aka ‘__va_list_tag[1]’}
  326 | typedef __builtin_va_list va_list;
      |                           ^~~~~~~
/home/x/.guix-profile/include/stdio.h:366:22: error: unknown type name ‘__gnuc_va_list’
  366 |                      __gnuc_va_list __arg);
      |                      ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:371:54: error: unknown type name ‘__gnuc_va_list’
  371 | extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);
      |                                                      ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:374:22: error: unknown type name ‘__gnuc_va_list’
  374 |                      __gnuc_va_list __arg) __THROWNL;
      |                      ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:383:56: error: unknown type name ‘__gnuc_va_list’
  383 |                       const char *__restrict __format, __gnuc_va_list __arg)
      |                                                        ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:391:23: error: unknown type name ‘__gnuc_va_list’
  391 |                       __gnuc_va_list __arg)
      |                       ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:404:22: error: unknown type name ‘__gnuc_va_list’
  404 |                      __gnuc_va_list __arg)
      |                      ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:460:21: error: unknown type name ‘__gnuc_va_list’
  460 |                     __gnuc_va_list __arg)
      |                     ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:467:53: error: unknown type name ‘__gnuc_va_list’
  467 | extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg)
      |                                                     ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:472:54: error: unknown type name ‘__gnuc_va_list’
  472 |                     const char *__restrict __format, __gnuc_va_list __arg)
      |                                                      ^~~~~~~~~~~~~~
In file included from /home/x/.guix-profile/include/features.h:490,
                 from /home/x/.guix-profile/include/bits/libc-header-start.h:33,
                 from /home/x/.guix-profile/include/stdio.h:27:
/home/x/.guix-profile/include/stdio.h:479:12: error: unknown type name ‘__gnuc_va_list’
  479 | extern int __REDIRECT (vfscanf,
      |            ^~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:484:12: error: unknown type name ‘__gnuc_va_list’
  484 | extern int __REDIRECT (vscanf, (const char *__restrict __format,
      |            ^~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:487:12: error: unknown type name ‘__gnuc_va_list’
  487 | extern int __REDIRECT_NTH (vsscanf,
      |            ^~~~~~~~~~~~~~
/home/x/.guix-profile/include/stdio.h:858:29: error: unknown type name ‘__gnuc_va_list’
  858 |                             __gnuc_va_list __args)
      |                             ^~~~~~~~~~~~~~
In file included from /home/x/.guix-profile/include/stdio.h:891:
/home/x/.guix-profile/include/bits/stdio.h:39:40: error: unknown type name ‘__gnuc_va_list’
   39 | vprintf (const char *__restrict __fmt, __gnuc_va_list __arg)
      |                                        ^~~~~~~~~~~~~~
In file included from /home/x/.guix-profile/include/sys/types.h:129,
                 from /gnu/store/nkp7immncpclk9wrkq09835242rgqbn3-ruby-3.2.3/include/ruby-3.2.0/ruby/defines.h:19:
/home/x/.guix-profile/include/bits/types/time_t.h:8:9: error: unknown type name ‘__time64_t’
    8 | typedef __time64_t time_t;
      |         ^~~~~~~~~~
In file included from /home/x/.guix-profile/include/sys/select.h:37,
                 from /home/x/.guix-profile/include/sys/types.h:179:
/home/x/.guix-profile/include/bits/types/struct_timeval.h:11:3: error: unknown type name ‘__time64_t’
   11 |   __time64_t tv_sec;            /* Seconds.  */
      |   ^~~~~~~~~~
In file included from /home/x/.guix-profile/include/sys/select.h:39:
/home/x/.guix-profile/include/bits/types/struct_timespec.h:14:3: error: unknown type name ‘__time64_t’
   14 |   __time64_t tv_sec;            /* Seconds.  */
      |   ^~~~~~~~~~
cc1: note: unrecognized command-line option ‘-Wno-self-assign’ may have been intended to silence earlier diagnostics
cc1: note: unrecognized command-line option ‘-Wno-parentheses-equality’ may have been intended to silence earlier diagnostics
cc1: note: unrecognized command-line option ‘-Wno-constant-logical-operand’ may have been intended to silence earlier diagnostics
make: *** [Makefile:247: breakpoint.o] Error 1

I do understand some of that output, but of course the first question is:

  • How can the generated makefile fail to specify the wrong paths to the respective header files or specify the wrong defines?

I did naively search for definitions of __gnuc_va_list and __time64_t, both of which I found in the /gnu store. However, they are surrounded by IFDEF
E.g. from "/gnu/store/y11hlxawl23iz2jja9c3rqzc7gvfbgxx-gcc-toolchain-13.3.0/include/stdio.h"

#if defined __USE_XOPEN || defined __USE_XOPEN2K8
# ifdef __GNUC__                                                                                                                                                                                   
#  ifndef _VA_LIST_DEFINED
typedef __gnuc_va_list va_list;
#   define _VA_LIST_DEFINED
#  endif
# else
#  include <stdarg.h>
# endif
#endif

And that is basically where I am feeling at a loss. I have no clue how to really unravel this issue, not to mention whether I went into the wrong direction already. My search engine results where mostly addressing the same compilation error, but for self-written C programs written.

Any help is welcome, thanks for taking the time.