# -*-eselect-*- vim: ft=eselect # Copyright 1999-2010 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Id$ # Author: Martin Schlemmer # Further modifications by Michał Górny # Further modifications by Tomáš Chvátal # Further modifications by Donnie Berkholz # Further modifications based off submissions to bug #54984 # Further modifications by Jeremy Huddleston # Made into eselect module by Jeremy Huddleston 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 cl.hpp; do for sdir in "$@"; do for file in ${sdir} ; do if [[ -f ${sdir}/${file} ]]; then upgrade_file "${sdir}/${file}" "${target}" break fi done 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 "DEBUG: ${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/global/include/CL/" # 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 "" } describe_set_options() { echo " : The profile to activate" echo "--use-old : If an implementation is already set, use that one instead" echo "--prefix= : Set the source prefix (default: /usr)" echo "--dst-prefix= : 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 }