Mailing List Archive

How to install Ruby bindings in an ebuild
I need to install Ruby bindings (something.so) during an ebuild,
specifically into the /usr/lib64/ruby/vendor_ruby/3.0.0/x86_64-linux
directory. I scanned existing ebuilds for an example, but have not yet
found one. The developer manual [1] mentions newlib.so, but that
function appears to inject "/lib64" into the destination path on my
machine. Thus, I currently use the following crutch:

exeinto /usr/lib64/ruby/vendor_ruby/3.0.0/x86_64-linux
doexe ./bindings/ruby/something.so

While this works for the time being, this seems quite wrong to me,
because the destination path is obviously hardcoded. Is there perhaps
something in the ruby-utils or ruby-single eclasses I missed? I had
hoped to find support for installing vendor modules for Ruby here.

Your suggestiions are appreciated.

-Ralph

[1] https://devmanual.gentoo.org/function-reference/install-functions/index.html
Re: How to install Ruby bindings in an ebuild [ In reply to ]
On 2023-04-19 01:08:23, Ralph Seichter wrote:
> I need to install Ruby bindings (something.so) during an ebuild,
> specifically into the /usr/lib64/ruby/vendor_ruby/3.0.0/x86_64-linux
> directory.

Hey Ralph. I'm not an expert on the ruby eclasses, but they work more
or less like the python ones, if that helps at all.

In this case, it looks like you have a package that builds a binary
ruby extension. That extension should be married to a specific version
of ruby, namely the one it was built against. I think the best way to
support that in a package is to declare which ruby versions are
supported with USE_RUBY and ruby-ng.eclass. USE_RUBY will be cross-
referenced with the user's RUBY_TARGETS to determine which ruby
versions are ultimately supported. Then, parts of the ebuild will be
repeated for each ruby version that the ebuilds supports and that the
user wants.

You can fine-tune what happens in each phase with the eclass functions
each_ruby_<phase>. So for example, if this is a C package, you might
only want to run ./configure && make extension && make install-extension
in the separate version-specific phases, so as to avoid rebuilding the
whole entire package for each version of ruby.

As always, the devil is in the details, but ruby-ng.eclass is a good
starting point.
Re: How to install Ruby bindings in an ebuild [ In reply to ]
Hello Michael. Long time no read. ;-)

> I think the best way to support that in a package is to declare which
> ruby versions are supported with USE_RUBY and ruby-ng.eclass.

I tried what you suggested. However, inheriting from ruby-ng.eclass
introduces an odd problem: For some reason unknown to me, "${S}" no
longer matches the default value of "${WORKDIR}/${P}", but only what I'd
expect in "${WORKDIR}". That means the base directory for src_compile
and src_install is not correct, causing the build to fail. It might be a
bug in ruby-ng, or a side effect of inheriting from ruby-ng on top of
the other eclasses already needed/used by the ebuild. I don't feel
comfortable with opening this particular can of worms when only a single
library something.so needs to be installed. Right now, I changed to
this:

local p=$(ruby -e 'puts $LOAD_PATH' | grep 'vendor.\+linux')
[[ -d "${p}" ]] || die "'${p}' is not a directory"
exeinto "${p}"

Not very pretty either, but at least this avoids any hardcoded
directories.

-Ralph
Re: How to install Ruby bindings in an ebuild [ In reply to ]
On Fri, 2023-04-21 at 09:16 +0200, Ralph Seichter wrote:
>
> I tried what you suggested. However, inheriting from ruby-ng.eclass
> introduces an odd problem: For some reason unknown to me, "${S}" no
> longer matches the default value of "${WORKDIR}/${P}", but only what I'd
> expect in "${WORKDIR}".

The eclass sets S=$WORKDIR at first because it creates a separate
source tree for each version of ruby that will be built for. For
example, you might have both $WORKDIR/ruby27 and $WORKDIR/ruby28. Later
on in the each_ruby_foo phases, $S will point to one of those, so it
should look more like what you're expecting.


> library something.so needs to be installed. Right now, I changed to
> this:
>
> local p=$(ruby -e 'puts $LOAD_PATH' | grep 'vendor.\+linux')
> [[ -d "${p}" ]] || die "'${p}' is not a directory"
> exeinto "${p}"
>
> Not very pretty either, but at least this avoids any hardcoded
> directories.
>

That uses the currently-eselected version of ruby to determine the path
though. If you eselect another version, or if you update the current
one, the bindings will stop working.

It may still not be worth the effort, but I'd keep that in mind when
updating ruby.
Re: How to install Ruby bindings in an ebuild [ In reply to ]
* Michael Orlitzky:

> The eclass sets S=$WORKDIR at first because it creates a separate
> source tree for each version of ruby that will be built for. [...]

Hm. While that sounds useful for "full Ruby" ebuilds, I don't see how to
circumvent the impact for the particular ebuild I am trying to extend,
other than overriding S in src_compile() etc.

The build needs to create a C shared library, Python bindings, and now
an additional shared library containing the Ruby bindings. Might this be
a case where a new, separate ebuild for the Ruby bindings would be a
better option than expanding the existing build?

> That uses the currently-eselected version of ruby to determine the
> path though.

I thought of that and tried to use ${RUBY} instead, but the variable was
empty. Hence I use the literal 'ruby' as a workaround, until a better
method comes to mind.

-Ralph
Re: How to install Ruby bindings in an ebuild [ In reply to ]
On Fri, 2023-04-21 at 22:15 +0200, Ralph Seichter wrote:
>
> Hm. While that sounds useful for "full Ruby" ebuilds, I don't see how to
> circumvent the impact for the particular ebuild I am trying to extend,
> other than overriding S in src_compile() etc.
>
> The build needs to create a C shared library, Python bindings, and now
> an additional shared library containing the Ruby bindings. Might this be
> a case where a new, separate ebuild for the Ruby bindings would be a
> better option than expanding the existing build?
> >

Ultimately what you want to do is build all of that other stuff once,
and then build ruby binding for each version of ruby. You can probably
make that happen by mucking around with the each_ruby_foo and
all_ruby_foo phases, but I think a separate ebuild would work too.
Assuming that the bindings link to the library, in both cases you face
the same problem: to convince the build system to link against a
different copy of the C library. With a single ebuild, you want the
ruby-specific builds to link against the one shared library you just
built; with a separate ebuild you'd want them all to link against the
system copy that was installed by the main ebuild.


> I thought of that and tried to use ${RUBY} instead, but the variable was
> empty. Hence I use the literal 'ruby' as a workaround, until a better
> method comes to mind.

One final option would be to figure out how the eclass is finding the
supported ruby versions, and copy it. Then you could loop through them
and use your hack with each one.