diff options
-rw-r--r-- | opencl.eselect/opencl.eselect | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/opencl.eselect/opencl.eselect b/opencl.eselect/opencl.eselect new file mode 100644 index 0000000..a29d095 --- /dev/null +++ b/opencl.eselect/opencl.eselect @@ -0,0 +1,340 @@ +# -*-eselect-*- vim: ft=eselect +# Copyright 1999-2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ +# Author: Martin Schlemmer <azarah@gentoo.org> +# Further modifications by Michał Górny <mgorny@gentoo.org> +# Further modifications by Tomáš Chvátal <scarabeus@gentoo.org> +# Further modifications by Donnie Berkholz <dberkholz@gentoo.org> +# Further modifications based off submissions to bug #54984 <cyfred@gentoo.org> +# Further modifications by Jeremy Huddleston <eradicator@gentoo.org> +# Made into eselect module by Jeremy Huddleston <eradicator@gentoo.org> + +inherit multilib package-manager config + +# Eselect data +DESCRIPTION="Manage the OpenCL implementation used by your system" +MAINTAINER="xarthisius@gentoo.org" +SVN_DATE='$Date$' +VERSION=$(svn_date_to_version "${SVN_DATE}" ) +EBUILD_VERSION="1.1.0" + +# Our data +ENV_FILE="${EROOT}/etc/env.d/03opencl" +PREFIX="${EROOT}/usr" +DST_PREFIX="${EROOT}/usr" +unset IGNORE_MISSING + +get_current_implementation() { + local ret + local ldpath=$(load_config "${ENV_FILE}" LDPATH) + local opencl_profile=$(load_config "${ENV_FILE}" OPENCL_PROFILE) + + if [[ -n ${opencl_profile} ]] ; then + ret="${opencl_profile}" + elif [[ -n ${ldpath} ]] ; then + ret="${ldpath%%:*}" + ret="${ret##*OpenCL/vendors/}" + ret="${ret%/lib*}" + fi + + echo ${ret} +} + +get_implementations() { + local ret + local libdir + local dir + local dir_name + + for libdir in $(list_libdirs) ; do + [[ ${ROOT} != / ]] && libdir=${libdir#${EROOT}} + for dir in "${PREFIX}/${libdir}"/OpenCL/vendors/* ; do + dir_name=$(basename "${dir}") + [[ -d ${dir} && ${dir_name} != "global" ]] || continue + has ${dir_name} ${ret} && continue + ret=${ret:+${ret} }${dir_name} + done + done + + echo ${ret} +} + +# 1: file +# 2: workdir +upgrade_file() { + local file=$1 + local filename + local workdir=$2 + local linkfile=$(relative_name ${file} "${workdir}") + + [[ -f ${file} ]] || return + filename=$(basename "${file}") + + if [[ -f ${filename} || ( -L ${filename} && ! -e ${filename} ) ]] ; then + rm -f "${filename}"* || die -q "Failed to delete ${workdir}/${filename}" + fi + + #echo "DEBUG: ln -s \"${linkfile}\" \"${filename}\"" + if [[ "x${REMOVE_ONLY}" == "xfalse" ]]; then + ln -s "${linkfile}" "${filename}" || die -q "Failed to create symlink ${workdir}/${filename}" + fi +} + +setup_soname_symlinks() { + local file=$1 + local target=$2 + local soname + local scanner + + # if we have .so or dylib we need to make its soname symlinked + # in order to be easy to find and faster to grab + if [[ ${file} == *.so || ${file} == *.dylib ]] ; then + [[ ${file} == *.so ]] && scanner=scanelf || scanner="scanmacho" + soname=$(${scanner} -qBF '%S|%p' "${file}" | head -n1) + soname=${soname%|*} # stupid scanelf must print filename + [[ ${file} == *.so ]] && soname="${file%/*}"/${soname} + upgrade_file "${soname}" "${target}" + fi +} + +setup_lib_symlinks() { + local profile_libdir=$1 + local target=$2 + local file + + mkdir -p "${target}" || die "Failed to create ${target}" + + pushd "${target}" &> /dev/null + for file in "${profile_libdir}"/lib*.so; do + upgrade_file "${file}" "${target}" + setup_soname_symlinks "${file}" "${target}" + done + popd &> /dev/null +} + +setup_includes_symlinks() { + local target=$1 + local file + local sdir + + shift + + mkdir -p "${target}" || die "Failed to create ${target}" + pushd "${target}" &> /dev/null + for file in cl_ext.h cl_gl_ext.h cl_gl.h cl.h cl_platform.h opencl.h; do + for sdir in "$@"; do + if [[ -e ${sdir}/${file} ]]; then + upgrade_file "${sdir}/${file}" "${target}" + break + fi + done + done + popd &> /dev/null +} + +set_new_implementation() { + local cl_implem=$1 + local avail_implems=$(get_implementations) + local libdir + local moduledir + local gl_dir + local cl_local + + # Set a sane umask... bug #83115 + umask 022 + + if ! has ${cl_implem} ${avail_implems}; then + die -q "Invalid opencl implementation selected." + fi + + if [[ -z ${IGNORE_MISSING+1} ]]; then + local found_opencl + for libdir in $(list_libdirs); do + [[ ${ROOT} != / ]] && libdir=${libdir#${EROOT}} + [[ -d ${PREFIX}/${libdir}/OpenCL && ! -h ${PREFIX}/${libdir} ]] || continue + [[ -f "${PREFIX}/${libdir}/OpenCL/vendors/${cl_implem}/libOpenCL.so" ]] && found_opencl=yes + echo "${PREFIX}/${libdir}/OpenCL/vendors/${cl_implem}/libOpenCL.so" + done + + if [[ -z ${found_opencl} ]]; then + write_error_msg "The ${cl_implem} OpenCL implementation doesn't seem to provide" + write_error_msg "libOpenCL.so file. This might be an effect of breakage introduced" + write_error_msg "by a prioprietary driver installer. Please re-merge the package" + write_error_msg "providing your OpenCL implementation." + die -q "Selected OpenCL implementation incomplete." + fi + fi + + echo -n "Switching to ${cl_implem} OpenCL interface..." + if [[ -f ${ENV_FILE} ]] ; then + rm -f "${ENV_FILE}" || die -q "Failed to remove ${ENV_FILE}" + fi + + for libdir in $(list_libdirs); do + # Set libdir correctly to EROOT + [[ ${ROOT} != / ]] && libdir=${libdir#${EROOT}} + + # First make sure we have an opencl directory and this + # is a real lib dir, not a symlink + [[ -d ${PREFIX}/${libdir}/OpenCL && ! -h ${PREFIX}/${libdir} ]] || continue + + # Check if opencl implementation directory exists + # and use xorg-x11 as fallback (mesa) + # If even mesa is not around then simply die + if [[ -d "${PREFIX}/${libdir}/OpenCL/vendors/${cl_implem}" ]] ; then + cl_local="${cl_implem}" + REMOVE_ONLY="false" # global variable + else + # we are moving to implementation that does not have any support + # for specified libdir (ie 32bit libs for mesa) so we should + # remove the current symlinks and continue like nothing happened. + REMOVE_ONLY="true" # global variable + cl_local=$(get_current_implementation) + if ! has ${cl_local} ${avail_implems}; then + # skipping the libdir cause there was no profile actually + # selected before + continue 2 + fi + fi + + setup_lib_symlinks \ + "${PREFIX}/${libdir}/OpenCL/vendors/${cl_local}/" \ + "${DST_PREFIX}/${libdir}" + + setup_includes_symlinks \ + "${DST_PREFIX}/include/CL" \ + "${PREFIX}/${libdir}/OpenCL/vendors/${cl_implem}/include/CL/" \ + "${PREFIX}/${libdir}/OpenCL/vendors/${cl_implem}/include/" \ + "${PREFIX}/${libdir}/OpenCL/global/include/" + + # Setup the $LDPATH + if [[ "x${REMOVE_ONLY}" == "xfalse" ]]; then + # we need this relative to ROOT + ldpath="${ldpath:+${ldpath}:}${PREFIX#${ROOT}}/${libdir}/OpenCL/vendors/${cl_local}" + fi + done + + store_config ${ENV_FILE} LDPATH "${ldpath}" + store_config ${ENV_FILE} OPENCL_PROFILE "${cl_implem}" + + do_action env update &> /dev/null + + echo " done" +} + +### show action ### +describe_show() { + echo "Print the current OpenCL implementation." +} + +do_show() { + local current=$(get_current_implementation) + + if [[ -n ${current} ]] ; then + echo ${current} + return 0 + else + echo "(none)" + return 2 + fi +} + +### list action ### +describe_list() { + echo "List the available OpenCL implementations." +} + +do_list() { + local targets=( $(get_implementations) ) + local i + + write_list_start "Available OpenCL implementations:" + for (( i = 0; i < ${#targets[@]}; i++ )); do + [[ ${targets[i]} = $(get_current_implementation) ]] \ + && targets[i]=$(highlight_marker "${targets[i]}") + done + write_numbered_list -m "(none found)" "${targets[@]}" +} + +### set action ### +describe_set() { + echo "Select the OpenCL implementation." +} + +describe_set_parameters() { + echo "<target>" +} + +describe_set_options() { + echo "<target> : The profile to activate" + echo "--use-old : If an implementation is already set, use that one instead" + echo "--prefix=<val> : Set the source prefix (default: /usr)" + echo "--dst-prefix=<val> : Set the destination prefix (default: /usr)" + echo "--ignore-missing : Ignore missing files when setting a new implementation" +} + +do_set() { + local action="error" + local current=$(get_current_implementation) + local available=$(get_implementations) + local new + local opt + + while [[ ${#@} -gt 0 ]] ; do + opt=$1 + shift + case ${opt} in + --use-old) + if [[ -n ${current} ]] && has ${current} ${available}; then + action="old-implementation" + fi + ;; + --prefix=*) + PREFIX=${ROOT}${opt#*=} + available=$(get_implementations) + ;; + --dst-prefix=*) + DST_PREFIX=${ROOT}${opt#*=} + ;; + --ignore-missing) + IGNORE_MISSING=1 + ;; + *) + if [[ ${action} != "old-implementation" ]] ; then + action="set-implementation" + fi + + if is_number ${opt} ; then + targets=( $(get_implementations) ) + new=${targets[$(( ${opt} - 1 ))]} + if [[ -z ${new} ]] ; then + die -q "Unrecognized option: ${opt}" + fi + elif has ${opt} ${available}; then + new="${opt}" + else + die -q "Unrecognized option: ${opt}" + fi + ;; + esac + done + + case ${action} in + old-implementation) + set_new_implementation ${current} + return $? + ;; + set-implementation) + if [[ -n ${new} ]] ; then + set_new_implementation ${new} + return $? + else + die -q "Please specify an implementation to set" + fi + ;; + *) + die -q "Invalid usage of set action." + ;; + esac +} |