From: Hans de Graaff <graaff@gentoo.org>
To: gentoo-dev <gentoo-dev@lists.gentoo.org>
Subject: [gentoo-dev] RFC: ruby-ng.eclass - new eclass for ruby-based packages
Date: Wed, 02 Dec 2009 08:11:57 +0100 [thread overview]
Message-ID: <1259737917.26974.8.camel@localhost> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 1060 bytes --]
Hi,
The ruby team is currently working on two new eclasses to better handle
our ruby packages. This first one is intended to be a replacement for
the current ruby.eclass. A second eclass is forthcoming and will provide
support for handling gems.
This new eclass has much better handling of multiple ruby target
implementations, fixing https://bugs.gentoo.org/show_bug.cgi?id=167029
and provides a better framework to include more functionality later.
We intend to move this eclass to the main tree and gradually move over
the packages currently using ruby.eclass. ruby.eclass will be deprecated
over time but we don't have a specific timeline for that yet.
There is a testbed with ebuilds here:
http://git.overlays.gentoo.org/gitweb/?p=proj/ruby-scripts.git;a=tree;f=ruby-ng-testbed;hb=HEAD
The eclass itself is attached to this message and here:
http://git.overlays.gentoo.org/gitweb/?p=proj/ruby-scripts.git;a=blob;f=ruby-ng-testbed/eclass/ruby-ng.eclass;h=ce9a37440600c7913a21b5780a18b5e8dd9d712f;hb=HEAD
Kind regards,
Hans
[-- Attachment #1.2: ruby-ng.eclass --]
[-- Type: text/plain, Size: 11887 bytes --]
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/eclass/ruby.eclass,v 1.75 2009/03/03 15:51:54 a3li Exp $
#
# @ECLASS: ruby-ng.eclass
# @MAINTAINER:
# Ruby herd <ruby@gentoo.org>
#
# Author: Diego E. Pettenò <flameeyes@gentoo.org>
#
# Author: Alex Legler <a3li@gentoo.org>
#
# @BLURB: An eclass for installing Ruby packages with proper support for multiple Ruby slots.
# @DESCRIPTION:
# The Ruby eclass is designed to allow an easier installation of Ruby packages
# and their incorporation into the Gentoo Linux system.
#
# Currently available targets are:
# * ruby18 - Ruby (MRI) 1.8.x
# * ruby19 - Ruby (MRI) 1.9.x
# * ree18 - Ruby Enterprise Edition 1.8.x
# * jruby - JRuby
#
# This eclass does not define the implementation of the configure,
# compile, test, or install phases. Instead, the default phases are
# used. Specific implementations of these phases can be provided in
# the ebuild either to be run for each Ruby implementation, or for all
# Ruby implementations, as follows:
#
# * each_ruby_configure
# * all_ruby_configure
# @ECLASS-VARIABLE: USE_RUBY
# @DESCRIPTION:
# This variable contains a space separated list of targets (see above) a package
# is compatible to. It must be set before the `inherit' call. There is no
# default. All ebuilds are expected to set this variable.
# @ECLASS-VARIABLE: PATCHES
# @DESCRIPTION:
# A String or Array of filenames of patches to apply to all implementations.
# @ECLASS-VARIABLE: RUBY_OPTIONAL
# @DESCRIPTION:
# Set the value to "yes" to make the dependency on a Ruby interpreter optional.
inherit eutils toolchain-funcs
EXPORT_FUNCTIONS src_unpack src_prepare src_configure src_compile src_test src_install pkg_setup
case ${EAPI} in
2) ;;
*)
die "Unsupported EAPI=${EAPI} for ruby-ng.eclass"
esac
# @FUNCTION: ruby_implementation_depend
# @USAGE: target [comparator [version]]
# @RETURN: Package atom of a Ruby implementation to be used in dependencies.
# @DESCRIPTION:
# This function returns the formal package atom for a Ruby implementation.
#
# `target' has to be one of the valid values for USE_RUBY (see above)
#
# Set `comparator' and `version' to include a comparator (=, >=, etc.) and a
# version string to the returned string
ruby_implementation_depend() {
local rubypn=
local rubyslot=
case $1 in
ruby18)
rubypn="dev-lang/ruby"
rubyslot=":1.8"
;;
ruby19)
rubypn="dev-lang/ruby"
rubyslot=":1.9"
;;
ree18)
rubypn="dev-lang/ruby-enterprise"
rubyslot=":1.8"
;;
jruby)
rubypn="dev-java/jruby"
rubyslot=""
;;
*) die "$1: unknown Ruby implementation"
esac
echo "$2${rubypn}$3${rubyslot}"
}
# @FUNCTION: ruby_samelib
# @RETURN: use flag string with current ruby implementations
# @DESCRIPTION:
# Convenience function to output the use dependency part of a
# dependency. Used as a building block for ruby_add_rdepend() and
# ruby_add_bdepend(), but may also be useful in an ebuild to specify
# more complex dependencies.
ruby_samelib() {
local res=
for _ruby_implementation in $USE_RUBY; do
has -${_ruby_implementation} $@ || \
res="${res}ruby_targets_${_ruby_implementation}?,"
done
echo "[${res%,}]"
}
_ruby_implementation_depend() {
echo "ruby_targets_${1}? ( ${2}[ruby_targets_${1}] )"
}
_ruby_add_bdepend() {
local atom=$1
local conditions=$2
for condition in $conditions; do
atom="${condition}? ( ${atom} )"
done
DEPEND="${DEPEND} ${atom}"
RDEPEND="${RDEPEND}"
}
_ruby_add_rdepend() {
local atom=$1
local conditions=$2
for condition in $conditions; do
atom="${condition}? ( ${atom} )"
done
RDEPEND="${RDEPEND} ${atom}"
_ruby_add_bdepend "$atom" test
}
# @FUNCTION: ruby_add_rdepend
# @USAGE: [conditions] atom
# @DESCRIPTION:
# Adds the specified atom(s) with optional use condition(s) to
# RDEPEND, taking the current set of ruby targets into account. This
# makes sure that all ruby dependencies of the package are installed
# for the same ruby targets. Use this function for all ruby
# dependencies instead of setting RDEPEND yourself. Both atom and
# conditions can be a space-separated list of atoms or conditions.
ruby_add_rdepend() {
local atoms=
local conditions=
case $# in
1)
atoms=$1
;;
2)
conditions=$1
atoms=$2
;;
*)
die "bad number of arguments to $0"
;;
esac
for atom in $atoms; do
_ruby_add_rdepend "${atom}$(ruby_samelib)" "$conditions"
done
}
# @FUNCTION: ruby_add_bdepend
# @USAGE: [conditions] atom
# @DESCRIPTION:
# Adds the specified atom(s) with optional use condition(s) to both
# DEPEND and RDEPEND, taking the current set of ruby targets into
# account. This makes sure that all ruby dependencies of the package
# are installed for the same ruby targets. Use this function for all
# ruby dependencies instead of setting DEPEND and RDEPEND
# yourself. Both atom and conditions can be a space-separated list of
# atoms or conditions.
ruby_add_bdepend() {
local atoms=
local conditions=
case $# in
1)
atoms=$1
;;
2)
conditions=$1
atoms=$2
;;
*)
die "bad number of arguments to $0"
;;
esac
for atom in $atoms; do
_ruby_add_bdepend "${atom}$(ruby_samelib)" "$conditions"
done
}
for _ruby_implementation in $USE_RUBY; do
IUSE="${IUSE} ruby_targets_${_ruby_implementation}"
# If you specify RUBY_OPTIONAL you also need to take care of
# ruby useflag and dependency.
if [[ ${RUBY_OPTIONAL} != "yes" ]]; then
DEPEND="${DEPEND} ruby_targets_${_ruby_implementation}? ( $(ruby_implementation_depend $_ruby_implementation) )"
RDEPEND="${RDEPEND} ruby_targets_${_ruby_implementation}? ( $(ruby_implementation_depend $_ruby_implementation) )"
fi
done
_ruby_invoke_environment() {
old_S=${S}
sub_S=${S#${WORKDIR}}
environment=$1; shift
my_WORKDIR="${WORKDIR}"/${environment}
S="${my_WORKDIR}"/"${sub_S}"
if [[ -d "${S}" ]]; then
pushd "$S" &>/dev/null
elif [[ -d "${my_WORKDIR}" ]]; then
pushd "${my_WORKDIR}" &>/dev/null
else
pushd "${WORKDIR}" &>/dev/null
fi
ebegin "Running ${_PHASE:-${EBUILD_PHASE}} phase for $environment"
"$@"
popd &>/dev/null
S=${old_S}
}
_ruby_each_implementation() {
local invoked=no
for _ruby_implementation in ${USE_RUBY}; do
# only proceed if it's requested
use ruby_targets_${_ruby_implementation} || continue
RUBY=$(type -p $_ruby_implementation 2>/dev/null)
invoked=yes
if [[ -n "$1" ]]; then
_ruby_invoke_environment $_ruby_implementation "$@"
fi
unset RUBY
done
[[ ${invoked} == "no" ]] && die "You need to select at least one Ruby implementation by setting RUBY_TARGETS in /etc/make.conf."
}
# @FUNCTION: ruby-ng_pkg_setup
# @DESCRIPTION:
# Check whether at least one ruby target implementation is present.
ruby-ng_pkg_setup() {
# This only checks that at least one implementation is present
# before doing anything; by leaving the parameters empty we know
# it's a special case.
_ruby_each_implementation
}
# @FUNCTION: ruby-ng_src_unpack
# @DESCRIPTION:
# Unpack the source archive, including gems.
ruby-ng_src_unpack() {
mkdir "${WORKDIR}"/all
pushd "${WORKDIR}"/all &>/dev/null
# We don't support an each-unpack, it's either all or nothing!
if type all_ruby_unpack &>/dev/null; then
_ruby_invoke_environment all all_ruby_unpack
else
[[ -n ${A} ]] && unpack ${A}
fi
popd &>/dev/null
}
_ruby_apply_patches() {
for x in "${PATCHES[@]}"; do
epatch "${x}"
done
# This is a special case: instead of executing just in the special
# "all" environment, this will actually copy the effects on _all_
# the other environments, and is thus executed before the copy
type all_ruby_prepare &>/dev/null && all_ruby_prepare
}
_ruby_source_copy() {
# Until we actually find a reason not to, we use hardlinks, this
# should reduce the amount of disk space that is wasted by this.
cp -prl all ${_ruby_implementation} \
|| die "Unable to copy ${_ruby_implementation} environment"
}
# @FUNCTION: ruby-ng_src_prepare
# @DESCRIPTION:
# Apply patches and prepare versions for each ruby target
# implementation. Also carry out common clean up tasks.
ruby-ng_src_prepare() {
# Way too many Ruby packages are prepared on OSX without removing
# the extra data forks, we do it here to avoid repeating it for
# almost every other ebuild.
find . -name '._*' -delete
_ruby_invoke_environment all _ruby_apply_patches
_ruby_each_implementation _ruby_source_copy
if type each_ruby_prepare &>/dev/null; then
_ruby_each_implementation each_ruby_prepare
fi
}
# @FUNCTION: ruby-ng_src_configure
# @DESCRIPTION:
# Configure the package.
ruby-ng_src_configure() {
if type each_ruby_configure &>/dev/null; then
_ruby_each_implementation each_ruby_configure
fi
type all_ruby_configure &>/dev/null && \
_ruby_invoke_environment all all_ruby_configure
}
# @FUNCTION: ruby-ng_src_compile
# @DESCRIPTION:
# Compile the package.
ruby-ng_src_compile() {
if type each_ruby_compile &>/dev/null; then
_ruby_each_implementation each_ruby_compile
fi
type all_ruby_compile &>/dev/null && \
_ruby_invoke_environment all all_ruby_compile
}
# @FUNCTION: ruby-ng_src_test
# @DESCRIPTION:
# Run tests for the package.
ruby-ng_src_test() {
if type each_ruby_test &>/dev/null; then
_ruby_each_implementation each_ruby_test
fi
type all_ruby_test &>/dev/null && \
_ruby_invoke_environment all all_ruby_test
}
_each_ruby_check_install() {
local libruby_basename=$(${RUBY} -rrbconfig -e 'puts Config::CONFIG["LIBRUBY_SO"]')
local libruby_soname=$(scanelf -qS "/usr/$(get_libdir)/${libruby_basename}" | awk '{ print $1 }')
# The current implementation lacks libruby (i.e.: jruby)
[[ -z ${libruby_soname} ]] && return 0
scanelf -qnR "${D}"/$(dirname $(${RUBY} -rrbconfig -e 'puts Config::CONFIG["sitedir"]')) \
| fgrep -v "${libruby_soname}" \
> "${T}"/ruby-ng-${_ruby_implementation}-mislink.log
if [[ -s "${T}"/ruby-ng-${_ruby_implementation}-mislink.log ]]; then
ewarn "Extensions installed for ${_ruby_implementation} with missing links to ${libruby}"
ewarn $(< "${T}"/ruby-ng-${_ruby_implementation}-mislink.log )
die "Missing links to ${libruby}"
fi
}
# @FUNCTION: ruby-ng_src_install
# @DESCRIPTION:
# Install the package for each ruby target implementation.
ruby-ng_src_install() {
if type each_ruby_install &>/dev/null; then
_ruby_each_implementation each_ruby_install
fi
type all_ruby_install &>/dev/null && \
_ruby_invoke_environment all all_ruby_install
_PHASE="check install" \
_ruby_each_implementation _each_ruby_check_install
}
# @FUNCTION: doruby
# @USAGE: file [file...]
# @DESCRIPTION:
# Installs the specified file(s) into the sitelibdir of the Ruby interpreter in ${RUBY}.
doruby() {
( # don't want to pollute calling env
insinto $(${RUBY} -r rbconfig -e 'print Config::CONFIG["sitelibdir"]')
insopts -m 0644
doins "$@"
) || die "failed to install $@"
}
# @FUNCTION: ruby_get_libruby
# @RETURN: The location of libruby*.so belonging to the Ruby interpreter in ${RUBY}.
ruby_get_libruby() {
${RUBY} -rrbconfig -e 'puts File.join(Config::CONFIG["libdir"], Config::CONFIG["LIBRUBY"])'
}
# @FUNCTION: ruby_get_hdrdir
# @RETURN: The location of the header files belonging to the Ruby interpreter in ${RUBY}.
ruby_get_hdrdir() {
local rubyhdrdir=$(${RUBY} -rrbconfig -e 'puts Config::CONFIG["rubyhdrdir"]')
if [[ "${rubyhdrdir}" = "nil" ]] ; then
rubyhdrdir=$(${RUBY} -rrbconfig -e 'puts Config::CONFIG["archdir"]')
fi
echo "${rubyhdrdir}"
}
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
next reply other threads:[~2009-12-02 7:13 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-02 7:11 Hans de Graaff [this message]
2009-12-02 8:51 ` [gentoo-dev] Re: RFC: ruby-ng.eclass - new eclass for ruby-based packages Christian Faulhammer
2009-12-02 8:57 ` Tomáš Chvátal
2009-12-02 10:46 ` Fabian Groffen
2009-12-05 8:59 ` Hans de Graaff
2009-12-02 10:59 ` Christian Faulhammer
2009-12-05 9:32 ` Hans de Graaff
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1259737917.26974.8.camel@localhost \
--to=graaff@gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox