#!/usr/bin/env bash
shopt -s extglob

# deps: apt update && apt install bash file binutils patchelf findutils grep sed coreutils strace -y
# deps: apk add bash file binutils patchelf findutils grep sed coreutils strace
# deps: dnf install bash file binutils patchelf findutils grep sed coreutils strace -y
# deps: pacman -Sy bash file binutils patchelf findutils grep sed coreutils strace --noconfirm
# deps: xbps-install -Sy bash file binutils patchelf findutils grep sed coreutils strace

RED='\033[1;91m'
BLUE='\033[1;94m'
GREEN='\033[1;92m'
YELLOW='\033[1;33m'
RESETCOLOR='\033[1;00m'

ONE_DIR=${ONE_DIR:=1}
DST_DIR="${DST_DIR:=.}"
TMPDIR="${TMPDIR:=/tmp}"
CREATE_LINKS=${CREATE_LINKS:=1}

[[ -z "$PYINSTALL_DIR" && -d "$HOME/.local/share/uv/python" ]] && \
PYINSTALL_DIR="$HOME/.local/share/uv/python"
PYINSTALL_DIR="${PYINSTALL_DIR:=$TMPDIR/pyinstall}"

ARCH="$(uname -m)"
GIT_SHARUN_RELEASE="https://github.com/VHSgunzo/sharun/releases/latest/download/sharun-${ARCH}"
GIT_WRAPPE_RELEASE="https://github.com/VHSgunzo/wrappe/releases/latest/download/wrappe-${ARCH}"
GIT_UV_RELEASE="https://github.com/astral-sh/uv/releases/latest/download/uv-${ARCH}-unknown-linux-musl.tar.gz"

STRIP=${STRIP:=0}
VERBOSE=${VERBOSE:=0}
LIBS_ONLY=${LIBS_ONLY:=0}
QUIET_MODE=${QUIET_MODE:=0}
HARD_LINKS=${HARD_LINKS:=0}
WITH_HOOKS=${WITH_HOOKS:=0}
WITH_SHARUN=${WITH_SHARUN:=0}
WITH_WRAPPE=${WITH_WRAPPE:=0}
WRAPPE_CLVL=${WRAPPE_CLVL:=8}
PATCH_RPATH=${PATCH_RPATH:=0}
STRACE_MODE=${STRACE_MODE:=0}
STRACE_TIME=${STRACE_TIME:=5}
GEN_LIB_PATH=${GEN_LIB_PATH:=0}
ANY_EXECUTABLE=${ANY_EXECUTABLE:=0}
WRAPPE_CLEANUP=${WRAPPE_CLEANUP:=1}
MAX_INTERP_LEN=${MAX_INTERP_LEN:=256}
PATCH_INTERPRETER=${PATCH_INTERPRETER:=0}

XDG_OPEN_WRAPPER='#!/bin/sh
# xdg-open and gio-launch-desktop wrapper for sharun
# unsets env variables that cause issues to child processes

CURRENTDIR="$(readlink -f "$(dirname "$0")")"
APPDIR="${APPDIR:-${SHARUN_DIR:-$(dirname "$CURRENTDIR")}}"
PATH="$(echo "$PATH" | sed "s|$CURRENTDIR||g")"
export PATH

problematic_vars="BABL_PATH GBM_BACKENDS_PATH GCONV_PATH GDK_PIXBUF_MODULEDIR \
	GDK_PIXBUF_MODULE_FILE GEGL_PATH GIO_MODULE_DIR GI_TYPELIB_PATH \
	GSETTINGS_SCHEMA_DIR GST_PLUGIN_PATH GST_PLUGIN_SCANNER GST_PLUGIN_SYSTEM_PATH \
	GST_PLUGIN_SYSTEM_PATH_1_0 GTK_DATA_PREFIX GTK_EXE_PREFIX GTK_IM_MODULE_FILE \
	GTK_PATH LIBDECOR_PLUGIN_DIR LIBGL_DRIVERS_PATH PERLLIB PIPEWIRE_MODULE_DIR \
	QT_PLUGIN_PATH SPA_PLUGIN_DIR TCL_LIBRARY TK_LIBRARY XTABLES_LIBDIR"

for var in $problematic_vars; do
	checkvar="$(printenv "$var" 2>/dev/null)"
	if [ -n "$checkvar" ] && echo "$checkvar" | grep -q "$APPDIR"; then
		unset "$var"
		>&2 echo "unset $var to prevent issues"
	fi
done

if [ "$(basename "$0")" = "gio-launch-desktop" ]; then
	export GIO_LAUNCHED_DESKTOP_FILE_PID=$$
	exec "$@"
else
	exec xdg-open "$@"
fi'

usage() {
    echo -e "[ Usage ]: lib4bin [OPTIONS] /path/executable -- [STRACE MODE EXEC ARGS]

[ Options ]:
    -d, --dst-dir '/path'    Destination directory (env: DST_DIR='/path')
    -e, --strace-mode        Use strace for get libs (env: STRACE_MODE=1)
    -t, --strace-time 5      Specify the time in seconds for strace mode (env: STRACE_TIME=5)
    -g, --gen-lib-path       Generate a lib.path file (env: GEN_LIB_PATH=1)
    -h, --help               Show this message
    -i, --patch-interpreter  Patch INTERPRETER to a relative path (env: PATCH_INTERPRETER=1)
    -k, --with-hooks         Pack additional files required for libraries (env: WITH_HOOKS=1)
    -l, --libs-only          Pack only libraries without executables (env: LIBS_ONLY=1)
    -n, --not-one-dir        Separate directories for each executable (env: ONE_DIR=0)
    -p, --hard-links         Pack sharun and create hard links (env: HARD_LINKS=1)
    -q, --quiet-mode         Show only errors (env: QUIET_MODE=1)
    -r, --patch-rpath        Patch RPATH to a relative path (env: PATCH_RPATH=1)
    -s, --strip              Strip binaries and libraries (env: STRIP=1)
    -v, --verbose            Verbose mode (env: VERBOSE=1)
    -w, --with-sharun        Pack sharun from PATH or env or download
                                (env: WITH_SHARUN=1, SHARUN=/path|URL, SHARUN_URL=URL, UPX_SHARUN=1)
    -o, --with-wrappe        Pack with wrappe from PATH or env or download
                                (env: WITH_WRAPPE=1, WRAPPE=/path|URL, WRAPPE_URL=URL)
    -c, --wrappe-clvl 0-22   Specify the compression level for wrappe (env: WRAPPE_CLVL=0-22) (default: 8)
    -x, --wrappe-exec name   Specify the name of the wrappe packaged executable (env: WRAPPE_EXEC=name)
    -m, --wrappe-args 'args' Specify the args for the wrappe packaged executable (env: WRAPPE_ARGS='args')
    -z, --wrappe-dir '/path' Specify path to the sharun dir for packing with wrappe (env: WRAPPE_DIR='/path')
    -u, --wrappe-no-cleanup  Disable cleanup the wrappe unpack directory after exit (env: WRAPPE_CLEANUP=0)
                                It can also be set at runtime (env: STARTPE_CLEANUP=0)
    -y, --with-python        Pack python using uv from PATH or env or download
                                (env: WITH_PYTHON=1, UV=/path|URL, UV_URL=URL)
    -pp, --python-pkg 'pkg'  Specify the python package or '/path/requirements.txt' (env: PYTHON_PKG='pkg')
    -pv, --python-ver 3.12   Specify the python version for packing (env: PYTHON_VER=3.12)
    -pi, --python-pip        Leave pip after install python package (env: PYTHON_LEAVE_PIP=1)
    -pw, --python-wheel      Leave wheel after install python package (env: PYTHON_LEAVE_WHEEL=1)
    -ps, --python-setuptools Leave setuptools after install python package (env: PYTHON_LEAVE_SETUPTOOLS=1)"
    exit 1
}

error_msg() {
    echo -e "${RED}[ ERROR ][$(date +"%Y.%m.%d %T")]: $@ $RESETCOLOR" 1>&2
    return 1
}

info_msg() {
    if [ "$QUIET_MODE" != 1 ]
        then echo -e "${GREEN}[ INFO ][$(date +"%Y.%m.%d %T")]: $@ $RESETCOLOR" 1>&2
    fi
}

hook_msg() { info_msg "$YELLOW[ HOOK ]:$GREEN $@" ; }

skip_msg() {
    if [ "$QUIET_MODE" != 1 ]
        then echo -e "${YELLOW}[ SKIPPED ][$(date +"%Y.%m.%d %T")]: $@ $RESETCOLOR" 1>&2
    fi
}

which_exe() { command -v "$@" ; }

is_exe_exist() { which_exe "$@" &>/dev/null ; }

check_deps() {
    local ret=0
    local binaries=(file patchelf find grep sed)
    [ "$STRIP" != 1 ]||binaries+=(strip)
    [ "$STRACE_MODE" != 1 ]||binaries+=(strace)
    for bin in "${binaries[@]}"
        do
            if ! is_exe_exist $bin
                then
                    error_msg "$BLUE[$bin]$YELLOW not found!"
                    ret=1
            fi
    done
    if [ "$ret" != 0 ]
        then
            info_msg "You need to install ${BLUE}lib4bin${GREEN} dependencies: ${BLUE}file binutils patchelf findutils grep sed coreutils strace"
            exit 1
    fi
}

try_strip() {
    if [[ "$STRIP" == 1 && ! "$FILE_INFO" =~ 'no section header' ]]
        then
            info_msg "$YELLOW[ STRIP ]: $BLUE[$1]"
            strip -s -R .comment --strip-unneeded "$1"
    fi
}

try_remove_fullrpath() {
    if [ "$PATCH_RPATH" != 1 ]
        then
            local rpath="$(print_rpath "$1")"
            if grep -qE '^/|:/'<<<"$rpath"
                then
                    info_msg "$YELLOW[ REMOVE RPATH ]: $BLUE[$1 -> $rpath]"
                    patchelf $pvarg --remove-rpath "$1"||exit 1
            fi
    fi
}

try_set_rpath() {
    info_msg "$YELLOW[ SET RPATH ]: $BLUE[$1 -> $rpath]"
    if [ -n "$2" ]
        then local rpath="$2"
        else local rpath='$ORIGIN/../lib:$ORIGIN/../lib32'
    fi
    patchelf $pvarg --remove-rpath "$1"||exit 1
    patchelf $pvarg --set-rpath "$rpath" --force-rpath "$1"||exit 1
    patchelf $pvarg --no-default-lib "$1"||exit 1
}

get_md5sum() { md5sum<<<"$1"|awk '{print$1}'; }

print_needed() { patchelf --print-needed "$1" 2>/dev/null ; }

print_rpath() { patchelf --print-rpath "$1" 2>/dev/null ; }

ldd_libs() {
    ldd "$1" 2>/dev/null|grep -v 'error while loading shared libraries'|\
    grep '/lib'|cut -d'>' -f2|sed 's| (.*)||g'|sed 's|^[[:space:]]*||g'|sort -u
}

get_libs() {
    unset libs libs4libs
    local libs libs4libs needed_libs
    if [ "$STRACE_MODE" == 1 ] && ! is_so && \
    ([[ -z "$STRACE_EXE" || "$STRACE_EXE" == "$1" ]]||\
    [[ "$STRACE_EXE" == 'sharun' && "$1" == "$dst_dir/sharun" && "$binary_name" == 'sharun' ]])
        then
            local libs_file="${TMPDIR}/libs.$$"
            [[ "$(strace --help)" =~ always-show-pid ]] && \
            STRACE_ARGS='--always-show-pid'||unset STRACE_ARGS
            info_msg "$YELLOW[ STRACE ]: $BLUE[$1 ${STRACE_CMD_ARGS[@]}] ${GREEN}..."
            strace -f -e trace=openat,open $STRACE_ARGS -o "$libs_file" "$(readlink -f "$1")" "${STRACE_CMD_ARGS[@]}" 1>&2 &
            sleep $STRACE_TIME
            local pids="$(cut -d ' ' -f1<"$libs_file"|sort -u)"
            kill $pids 2>/dev/null
            libs="$(\
                sed '/nvidia/d;/libcuda/d;/ENOENT/d;/unfinished/d;/lib-dynload/d;/.wrappe/d;/_internal/d'<"$libs_file"|\
                    grep -Eo '".*lib.*\.so(\.[0-9].*)?"'|sed -u 's|"||g')\n"
            rm -f "$libs_file"
    fi
    [ -n "$2" ] && needed_libs="$2"||\
    needed_libs="$(print_needed "$1")"
    libs+="$(([ -z "$needed_libs" ]||\
        grep -E "$(tr '\n' '|'<<<"$needed_libs"|sed 's|\||$\||g')libpthread.so.[0-9]|libdl.so.[0-9]|librt.so.[0-9]|libm.so.[0-9]$"<<<"$ALL_LIBS" ; \
        ldd_libs "$1")|sort -u)"
    libs="$(echo -e "$libs"|sort -u)"
    [ -n "$IS_ELF32" ] && \
    libs="$(grep -vE '/lib/|/lib64/|/.*64-linux-gnu/'<<<"$libs")"||\
    libs="$(grep -vE '/lib32/|/i386-linux-gnu/|/arm-linux-gnu/'<<<"$libs")"
    OLD_IFS="$IFS"
    IFS=$'\n'
    for lib in $libs
        do libs4libs="$(echo -e "$(ldd_libs "$lib")\n$libs4libs")"
    done
    IFS="$OLD_IFS"
    echo -e "$libs\n$libs4libs"|sort -u|sed '/^$/d'
}

repath_needed_libs() {
    local needed_libs
    [ -n "$2" ] && needed_libs="$2"||\
    needed_libs="$(print_needed "$1")"
    local patch_needed_libs="$(grep '^/'<<<"$needed_libs")"
    if [ -n "$patch_needed_libs" ]
        then
            for lib in $patch_needed_libs
                do
                    local relib="$(basename "$lib")"
                    info_msg "$YELLOW[ REPATH ]: $BLUE[$lib -> $relib]"
                    patchelf $pvarg --replace-needed "$lib" "$relib" "$1"||exit 1
            done
    fi
}

try_mkdir() {
    if [ ! -d "$1" ]
        then mkdir $varg -p "$1"||exit 1
    fi
}

try_ln() {
    if [ ! -L "$2" ]
        then
            [ "$VERBOSE" == 1 ] && \
                echo -n "ln: "
            ln $varg -sf "$1" "$2"||exit 1
    fi
}

try_cp_exe() {
    if [ ! -f "$2" ]
        then
            [ "$VERBOSE" == 1 ] && \
                echo -n "cp: "
            cp $varg -f "$1" "$2"||exit 1
            chmod $varg 755 "$2"||exit 1
    fi
}

try_cp() {
    [ "$VERBOSE" == 1 ] && \
        echo -n "cp: "
    cp $varg -rf "$@"||exit 1
}

try_mv() {
    [ "$VERBOSE" == 1 ] && \
        echo -n "mv: "
    mv $varg -f "$@"||exit 1
}

try_cd() {
    [ "$VERBOSE" == 1 ] && \
        echo "cd: '$1'"
    cd "$1"||exit 1
}

get_relative_path() {
    local start_dir="$1"
    local target_dir="$2"
    start_dir=$(readlink -f "$start_dir")
    target_dir=$(readlink -f "$target_dir")
    local common_path=''
    local i=0
    while [ $i -lt ${#start_dir} ] && \
        [ $i -lt ${#target_dir} ] && \
        [ "${start_dir:$i:1}" = "${target_dir:$i:1}" ]
        do
            common_path+="${start_dir:$i:1}"
            i=$((i+1))
    done
    if [ -n "$common_path" ] && \
        [ "${common_path: -1}" != "/" ]
        then common_path=$(dirname "$common_path")
    fi
    local up_path=''
    local remaining_start="${start_dir#"$common_path"}"
    if [ -n "$remaining_start" ]
        then
            for dir in $(echo "$remaining_start" | tr "/" "\n" | grep -v "^$")
                do up_path+="../"
            done
    fi
    local down_path="${target_dir#"$common_path"}"
    local relative_path="$up_path${down_path#/}"
    echo "$relative_path"
}

find_exe() {
    [ -n "$1" ] && local path="$1" && shift
    find "$path" -maxdepth 1 -not -type d -executable "$@" 2>/dev/null|sort
}

find_so() { find "$@" -name '*.so' -o -name '*.so.*' 2>/dev/null ; }

is_so() { [ -n "$IS_SO" ] && [[ "${binary_name,,}" =~ .*(\.so$|\.so\..*) || "${binary_real_name,,}" =~ .*(\.so$|\.so\..*) ]] ; }

check_url_stat_code() {
    set -o pipefail
    if is_exe_exist curl
        then curl -sL -o /dev/null -I -w "%{http_code}" "$1" 2>/dev/null
    elif is_exe_exist wget
        then wget --no-check-certificate --server-response \
                --spider "$1"|& awk '/^  HTTP/{print$2}'|tail -1
    else
        error_msg "Failed to check URL $BLUE[$1]: ${RED}curl and wget not found!"
        return 1
    fi
}

is_url() {
    [ -z "$1" ] && \
        return 1
    if [ -n "$2" ]
        then [ "$(check_url_stat_code "$1")" == "$2" ]
        else [ "$(check_url_stat_code "$1")" == "200" ]
    fi
}

find_py_unneeded() {
    OLD_IFS="$IFS"
    IFS=$'\n'
    PY_UNNEEDED_LIST=($(find "$1" -type f -iname '*.cmd' \
        -o -iname '*.md' -o -name 'LICENSE*' -o -iname '*.ps1' \
        -o -iname '*.bat' -o -iname '*.exe' -o -iname '*.whl'))
    IFS="$OLD_IFS"
}

is_net_conn() {
    if is_exe_exist nc
        then nc -zw1 github.com 443 &>/dev/null
    elif is_exe_exist curl
        then curl -Ifs github.com &>/dev/null
    elif is_exe_exist wget
        then wget -q --spider github.com &>/dev/null
    elif is_exe_exist ping
        then ping -c 2 github.com &>/dev/null
    else
        error_msg "Failed to check internet connection: nc, curl, wget and ping not found!"
        return 1
    fi
}

try_dl() {
    if is_net_conn
        then
            if [ -n "$1" ]
                then
                    URL="$1"
                    if [ -n "$2" ]
                        then
                            if [ -d "$2" ]
                                then
                                    FILEDIR="$2"
                                    FILENAME="$(basename "$1")"
                                else
                                    FILEDIR="$(dirname "$2")"
                                    FILENAME="$(basename "$2")"
                            fi
                        else
                            FILEDIR="."
                            FILENAME="$(basename "$1")"
                    fi
                    if is_url "$URL"
                        then
                            WGET_ARGS=(-q --no-check-certificate -t 3 -T 5 -w 0.5 "$URL" -O "$FILEDIR/$FILENAME")
                            try_mkdir "$FILEDIR"
                            if [ "$NO_ARIA2C" != 1 ] && is_exe_exist aria2c
                                then
                                    aria2c --no-conf -R -x 13 -s 13 --allow-overwrite -d "$FILEDIR" -o "$FILENAME" "$URL"
                            elif is_exe_exist curl
                                then
                                    curl -R --progress-bar --insecure --fail -L "$URL" -o "$FILEDIR/$FILENAME"
                            elif is_exe_exist wget2
                                then
                                    wget2 --force-progress "${WGET_ARGS[@]}"
                            elif is_exe_exist wget
                                then
                                    wget --show-progress "${WGET_ARGS[@]}"
                            else
                                error_msg "Downloader not found!"
                            fi
                        else
                            error_msg "$FILENAME not found in $(echo "$URL"|awk -F/ '{print$3"/"$4}')"
                    fi
                else
                    error_msg "Specify download URL!"
            fi
        else
            error_msg "There is no internet connection?"
    fi
    return $?
}

parse_arg_options() {
    [ "$1" == 'dash' ] && shift && \
    local _ALLOW_DASH=1||unset _ALLOW_DASH
    if [ -n "$3" ] && [[ "$_ALLOW_DASH" == 1 || "$3" != -* ]]
        then eval "${1}='$3'"
        else
            error_msg "${YELLOW}Option ${BLUE}$2 ${YELLOW}requires a non-empty argument!\n"
            usage
    fi
}

while [[ "$#" -gt 0 ]]; do
    case $1 in
        -h|--help) usage ;;
        -s|--strip) STRIP=1; shift ;;
        -v|--verbose) VERBOSE=1; shift ;;
        -n|--not-one-dir) ONE_DIR=0; shift ;;
        -l|--libs-only) LIBS_ONLY=1; shift ;;
        -k|--with-hooks) WITH_HOOKS=1; shift ;;
        -q|--quiet-mode) QUIET_MODE=1; shift ;;
        -p|--hard-links) HARD_LINKS=1; shift ;;
        -e|--strace-mode) STRACE_MODE=1; shift ;;
        -w|--with-sharun) WITH_SHARUN=1; shift ;;
        -o|--with-wrappe) WITH_WRAPPE=1; shift ;;
        -y|--with-python) WITH_PYTHON=1; shift ;;
        -r|--patch-rpath) PATCH_RPATH=1; shift ;;
        -pi|--python-pip) PYTHON_LEAVE_PIP=1; shift ;;
        -pw|--python-wheel) PYTHON_LEAVE_WHEEL=1; shift ;;
        -ps|--python-setuptools) PYTHON_LEAVE_SETUPTOOLS=1; shift ;;
        -g|--gen-lib-path) GEN_LIB_PATH=1; shift ;;
        -u|--wrappe-no-cleanup) WRAPPE_CLEANUP=0; shift ;;
        -i|--patch-interpreter) PATCH_INTERPRETER=1; shift ;;
        -d|--dst-dir) parse_arg_options DST_DIR "$1" "$2"; shift 2 ;;
        -pv|--python-ver) parse_arg_options PYTHON_VER "$1" "$2"; shift 2 ;;
        -pp|--python-pkg) parse_arg_options PYTHON_PKG "$1" "$2"; shift 2 ;;
        -t|--strace-time) parse_arg_options STRACE_TIME "$1" "$2"; shift 2 ;;
        -x|--wrappe-exec) parse_arg_options WRAPPE_EXEC "$1" "$2"; shift 2 ;;
        -c|--wrappe-clvl) parse_arg_options WRAPPE_CLVL "$1" "$2"; shift 2 ;;
        -z|--wrappe-dir) parse_arg_options WRAPPE_DIR "$1" "$2"; shift 2 ;;
        -m|--wrappe-args) parse_arg_options dash WRAPPE_ARGS "$1" "$2"; shift 2 ;;
         -*) error_msg "Unknown parameter: ${BLUE}$1\n"; usage ;;
        *) break ;;
    esac
done

if [ "$VERBOSE" == 1 ]
    then
        varg='-v'
        pvarg='--debug'
    else
        unset varg pvarg
fi

if [[ -n "$WRAPPE_DIR" && ! -x "$WRAPPE_DIR/sharun" ]]
    then error_msg 'sharun was not found in specified wrappe directory!'; exit 1
fi

[[ "$STRACE_TIME" =~ ^[0-9]+$ ]]||\
    STRACE_TIME=5

[[ -n "$WRAPPE_EXEC" || -n "$WRAPPE_ARGS" || -d "$WRAPPE_DIR" ]] && \
    WITH_WRAPPE=1
(( WRAPPE_CLVL >= 0 && WRAPPE_CLVL <= 22 ))||\
    WRAPPE_CLVL=8
[ -d "$WRAPPE_DIR" ] && \
WRAPPE_DIR="$(readlink -f "$WRAPPE_DIR")"
[ "$WITH_WRAPPE" == 1 ] && \
    WITH_SHARUN=1 GEN_LIB_PATH=1

[[ -n "$PYTHON_PKG" ]] && WITH_PYTHON=1
[[ "$PYTHON_VER" =~ ^[0-9]+\.[0-9]+$ ]] && \
    WITH_PYTHON=1||unset PYTHON_VER

if [ "$WITH_PYTHON" == 1 ]
    then
        ONE_DIR=1
        WITH_SHARUN=1
        TMP_UV="${TMPDIR}/uv-${ARCH}-unknown-linux-musl/uv"
        UV="${UV:="$(readlink -f "$(which_exe uv)")"}"
        UV="${UV:="$TMP_UV"}"
        if [ ! -x "$UV" ]
            then
                if [[ "${UV,,}" =~ ^http ]]
                    then
                        UV_URL="$UV"
                        UV="$TMP_UV"
                fi
                UV_URL="${UV_URL:=$GIT_UV_RELEASE}"
                info_msg "Downloading uv -> '$UV'..."
                info_msg "$UV_URL"
                if NO_ARIA2C=1 try_dl "$UV_URL" '/dev/stdout'|tar -zxvf- -C "$TMPDIR"
                    then chmod $varg +x "$UV"
                    else
                        error_msg "Failed to download uv!"
                        exit 1
                fi
        fi
        if [ ! -x "$UV" ]
            then
                error_msg "uv not found!"
                exit 1
        fi
fi

BINARY_LIST=()
unset STRACE_EXE
declare -A DST_DIRS
[ -n "$DST_DIR" ] && \
DST_DIR="$(readlink -f "$DST_DIR")"
if [[  ! -d "$WRAPPE_DIR" || "$WITH_PYTHON" == 1 ]]
    then
        if [ "$2" == '--' ]
            then
                STRACE_MODE=1
                STRACE_EXE="$1"; shift 2
                STRACE_CMD_ARGS=("$@"); shift "${#@}"
        fi

        check_deps

        if [ "$WITH_PYTHON" == 1 ]
            then
                PYTMP_DIR="$DST_DIR/pytmp-$$"
                info_msg "$YELLOW[ PYTHON INSTALL ]: $BLUE[$PYINSTALL_DIR] ${GREEN}..."
                "$UV" python install --install-dir "$PYINSTALL_DIR" $PYTHON_VER||exit 1
                CPYTHON_VER="$(ls -r1 "$PYINSTALL_DIR"|grep -m1 "cpython-${PYTHON_VER}.*-linux-${ARCH}.*")"
                CPYTHON_DIR="$PYINSTALL_DIR/$CPYTHON_VER"
                if [[ -n "$CPYTHON_VER" && -d "$CPYTHON_DIR" ]]
                    then
                        info_msg "$YELLOW[ PYTHON VERSION ]: $BLUE[$CPYTHON_VER]"
                        try_mkdir "$PYTMP_DIR"
                        try_cp -T "$PYINSTALL_DIR/$CPYTHON_VER" "$PYTMP_DIR"
                        find_py_unneeded "$PYTMP_DIR/"
                        rm -rf "$PYTMP_DIR"/{.lock,share} "$PYTMP_DIR/lib"/!(pkgconfig|*python*) "${PY_UNNEEDED_LIST[@]}"
                        if [ -n "$PYTHON_PKG" ]
                            then
                                PYTHON_PKGS=(pip setuptools wheel)
                                info_msg "$YELLOW[ PIP INSTALL ]: $BLUE[$PYTHON_PKG -> $PYTMP_DIR] ${GREEN}..."
                                PYTHON_PKG_NAME="$(basename "$PYTHON_PKG")"
                                [[ -f "$PYTHON_PKG" && "${PYTHON_PKG_NAME,,}" == 'requirements.txt' ]] && \
                                    PYTHON_PKGS+=(-r "$PYTHON_PKG")||PYTHON_PKGS+=("$PYTHON_PKG")
                                "$UV" pip install --prefix "$PYTMP_DIR" --compile-bytecode --refresh --upgrade \
                                    --python "$PYTMP_DIR/bin/python" --link-mode=copy --prerelease=allow \
                                    "${PYTHON_PKGS[@]}"||exit 1
                                find_py_unneeded "$PYTMP_DIR/"
                                PY_UNINSTALL_LIST=()
                                if [ "$PYTHON_LEAVE_PIP" != 1 ]
                                    then
                                        PY_UNINSTALL_LIST+=(pip)
                                        PY_UNNEEDED_LIST+=(
                                            "$PYTMP_DIR/lib/pkgconfig"
                                            "$PYTMP_DIR"/{.lock,include}
                                            "$PYTMP_DIR"/lib/python*/ensurepip
                                            "$PYTMP_DIR/bin"/{pip,python*-config}*
                                            "$PYTMP_DIR/lib"/python*/config-*-linux*
                                            "$PYTMP_DIR"/lib/python*/site-packages/{pip,pip-*}
                                        )

                                fi
                                [ "$PYTHON_LEAVE_WHEEL" == 1 ]||PY_UNINSTALL_LIST+=(wheel)
                                [ "$PYTHON_LEAVE_SETUPTOOLS" == 1 ]||PY_UNINSTALL_LIST+=(setuptools)
                                if [ -n "$PY_UNINSTALL_LIST" ]
                                    then
                                        "$UV" pip uninstall --prefix "$PYTMP_DIR" --python "$PYTMP_DIR/bin/python" \
                                            "${PY_UNINSTALL_LIST[@]}"||exit 1
                                fi
                                rm -rf "$PYTMP_DIR/share/man" "${PY_UNNEEDED_LIST[@]}"
                        fi
                    else
                        error_msg "python $CPYTHON_VER not found!"
                        exit 1
                fi
                unset PY_UNNEEDED_LIST
                [ "$WITH_WRAPPE" == 1 ] && \
                dst_dir="$DST_DIR/wrappe-$$"||\
                dst_dir="$DST_DIR"
                try_mkdir "$dst_dir"
                try_cp -T "$PYTMP_DIR" "$dst_dir"
                rm -rf "$PYTMP_DIR"
                OLD_IFS="$IFS"
                IFS=$'\n'
                for script in $(grep -m1 "^'''exec.*python" -lr "$dst_dir/bin")
                    do sed -i '1s|.*|#!/usr/bin/env python|;2,3d' "$script"
                done
                BINARY_LIST+=(
                    $(find_exe "$dst_dir/bin/")
                    #$(find_so "$dst_dir")
                )
                IFS="$OLD_IFS"
        fi

        if [ -n "$STRACE_EXE" ]
            then BINARY_LIST+=("$STRACE_EXE")
        elif [ -n "$1" ]
            then BINARY_LIST+=("$@")
            else
                if [ -z "$BINARY_LIST" ]
                    then
                        error_msg "Specify the executable or shared object!\n"
                        usage
                fi
        fi

        ALL_LIBS="$(find_so \
            /usr/lib /usr/libexec /usr/lib64 \
            /usr/lib32 /lib /lib64 /lib32 \
            |sort -u \
        )"

        binary_number=1
        declare -A BINARIES
        declare -A LIBRARIES
        for binary in "${BINARY_LIST[@]}"
            do
                unset binary_real_name IS_PYINSTELF
                if [ -L "$binary" ]
                    then
                        binary_src_pth="$(readlink -f "$binary")"
                        binary_real_name="$(basename "$binary_src_pth")"
                    else
                        binary_src_pth="$binary"
                fi
                if [[ "${BINARIES["$binary"]}" != 1 ]]
                    then
                        binary_name="$(basename "$binary")"
                        binary_readlink_name="$(basename "$(readlink "$binary")")"
                        if [ "$WITH_PYTHON" != 1 ]
                            then
                                if [ "$ONE_DIR" == 1 ]
                                    then
                                        [ "$WITH_WRAPPE" == 1 ] && \
                                        dst_dir="$DST_DIR/wrappe-$$"||\
                                        dst_dir="$DST_DIR"
                                    else
                                        [ "$WITH_WRAPPE" == 1 ] && \
                                        dst_dir="$DST_DIR/${binary_name}/wrappe-$$"||\
                                        dst_dir="$DST_DIR/${binary_name}"
                                fi
                        fi
                        if [ "$binary" == 'sharun' ]
                            then binary_src_pth="$dst_dir/sharun"
                        fi
                        dst_dir_pth="${dst_dir}/shared"
                        sharun_bin_dir_pth="${dst_dir}/bin"
                        [[ -f "$dst_dir_pth" || -L "$dst_dir_pth" ]] && \
                            dst_dir_pth="${dst_dir_pth}.dir"
                        DST_DIRS["$dst_dir_pth"]=
                        bin_dir_pth="${dst_dir_pth}/bin"
                        FILE_INFO="$(file "$binary_src_pth" 2>/dev/null|cut -d':' -f2-)"
                        IS_ELF="$(grep -o 'ELF'<<<"$FILE_INFO")"
                        IS_STATIC="$(grep -o 'static'<<<"$FILE_INFO")"
                        IS_SCRIPT="$(grep -o 'script'<<<"$FILE_INFO")"
                        IS_ELF32="$(grep -o 'ELF 32-bit'<<<"$FILE_INFO")"
                        IS_SO="$(grep -o 'shared object'<<<"$FILE_INFO")"
                        IS_EXECUTABLE="$(grep -o 'executable'<<<"$FILE_INFO")"
                        IS_EXECUTABLE="${IS_EXECUTABLE:=$(([ -n "$IS_SO" ] && ! is_so) && echo executable)}"
                        IS_SHARUN="$(find "$binary_src_pth" -xdev -samefile "${dst_dir}/sharun" 2>/dev/null)"
                        info_msg "$YELLOW[ $binary_number ]: $BLUE[$binary_name] ${GREEN}..."
                        if [ "$HARD_LINKS" == 1 ] && [[ -n "$IS_SCRIPT" || -n "$IS_STATIC" ]]
                            then
                                hard_links=0
                                with_sharun=1
                        fi
                        hard_links=${HARD_LINKS:=0}
                        with_sharun=${WITH_SHARUN:=0}
                        create_links=${CREATE_LINKS:=1}
                        patch_interpreter=${PATCH_INTERPRETER:=0}
                        if ([ -n "$IS_EXECUTABLE" ] || is_so)
                            then
                                needed_libs="$(print_needed "$binary_src_pth")"
                                LIBS="$(get_libs "$binary_src_pth" "$needed_libs")"
                                is_so && LIBS="$(echo -e "$LIBS\n$binary"|sort -u|sed '/^$/d')"
                                if [[ -n "$LIBS" && -z "$IS_SCRIPT" && -z "$IS_STATIC" ]]
                                    then
                                        INTERPRETER="$(basename "$(grep -Em1 'ld-(linux|musl).*\.so'<<<"$LIBS"|cut -d'=' -f1|sed 's|\t||')")"
                                        [[ "$create_links" == 1 && "$hard_links" == 1 && ! -x "${dst_dir}/sharun" ]] && \
                                            with_sharun=1
                                    else
                                        create_links=0
                                        bin_dir_pth="$sharun_bin_dir_pth"
                                fi
                                if [ "$LIBS_ONLY" != 1 ] && ! is_so && [[ "$binary_name" != 'sharun' && \
                                    "$binary_readlink_name" != 'sharun' ]]
                                    then
                                        if [[ "$binary_real_name" != 'sharun' && -z "$IS_SHARUN" ]]
                                            then
                                                if [[ "$with_sharun" == 1 && ! -x "${dst_dir}/sharun" ]]
                                                    then
                                                        TMP_SHARUN="${TMPDIR}/sharun-${ARCH}$([ "$UPX_SHARUN" != 1 ]||echo -upx)"
                                                        SHARUN="${SHARUN:="$(readlink -f "$(which_exe sharun)")"}"
                                                        SHARUN="${SHARUN:="$TMP_SHARUN"}"
                                                        if [ ! -x "$SHARUN" ]
                                                            then
                                                                if [[ "${SHARUN,,}" =~ ^http ]]
                                                                    then
                                                                        SHARUN_URL="$SHARUN"
                                                                        SHARUN="$TMP_SHARUN"
                                                                fi
                                                                SHARUN_URL="${SHARUN_URL:=${GIT_SHARUN_RELEASE}$([ "$UPX_SHARUN" != 1 ]||echo -upx)}"
                                                                info_msg "Downloading sharun -> '$SHARUN'..."
                                                                info_msg "$SHARUN_URL"
                                                                if try_dl "$SHARUN_URL" "$SHARUN"
                                                                    then chmod $varg +x "$SHARUN"
                                                                    else
                                                                        error_msg "Failed to download sharun!"
                                                                        exit 1
                                                                fi
                                                        fi
                                                        if [ -x "$SHARUN" ]
                                                            then
                                                                try_mkdir "$dst_dir"
                                                                try_cp_exe "$SHARUN" "${dst_dir}/sharun"
                                                            else
                                                                error_msg "sharun not found!"
                                                                exit 1
                                                        fi
                                                fi
                                                try_mkdir "$bin_dir_pth"
                                                [ -n "$binary_real_name" ] && \
                                                    binary_dst_pth="$bin_dir_pth/$binary_real_name"||\
                                                    binary_dst_pth="$bin_dir_pth/$binary_name"
                                                try_cp_exe "$binary_src_pth" "$binary_dst_pth"
                                                if [ -n "$IS_SCRIPT" ]
                                                    then
                                                        for intep in python bash sh ash zsh fish dash perl ruby go node
                                                            do
                                                                if grep -qo "^#!.*bin/$intep" "$binary_dst_pth"
                                                                    then
                                                                        sed -i "1s|^#!.*bin/$intep|#!/usr/bin/env $intep|" "$binary_dst_pth"
                                                                        break
                                                                fi
                                                        done
                                                fi
                                                if [[ "${BINARIES["$binary_dst_pth"]}" != 1 ]]
                                                    then
                                                        if [ -n "$IS_ELF" ]
                                                            then try_strip "$binary_dst_pth"
                                                        fi
                                                        if [[ -n "$LIBS" && -z "$IS_SCRIPT" && -z "$IS_STATIC" ]]
                                                            then
                                                                repath_needed_libs "$binary_dst_pth" "$needed_libs"
                                                                try_remove_fullrpath "$binary_dst_pth"
                                                                IS_PYINSTELF="$(grep -aom1 'PyInstaller' "$binary_src_pth")"
                                                                if [ -n "$IS_PYINSTELF" ]
                                                                    then
                                                                        pyinternal_dir="$(readlink -f "$(dirname "$binary_src_pth")/_internal")"
                                                                        if [ -d "$pyinternal_dir" ]
                                                                            then
                                                                                rm -rf "$bin_dir_pth/_internal"
                                                                                try_cp -T "$pyinternal_dir" "$bin_dir_pth/_internal"
                                                                                if [ "$dst_dir" == "$(dirname "$pyinternal_dir")" ]
                                                                                    then rm -rf "$pyinternal_dir" "$binary_src_pth"
                                                                                fi
                                                                            else patch_interpreter=1
                                                                        fi
                                                                        export PATCH_RPATH_$(get_md5sum "${dst_dir_pth}")=1
                                                                fi
                                                        fi
                                                        BINARIES["$binary_dst_pth"]=1
                                                fi
                                            else
                                                bin_dir_pth="${dst_dir_pth}/bin"
                                                binary_real_name="$binary_readlink_name"
                                        fi
                                        if [[ -n "$binary_real_name" && "$binary_name" != "$binary_real_name" ]]
                                            then
                                                (try_cd "$bin_dir_pth"
                                                try_ln "$binary_real_name" "$binary_name")||exit 1
                                        fi
                                        if [ "$create_links" == 1 ]||[[ "$binary_name" != 'sharun' && \
                                            "$binary_readlink_name" != 'sharun' && -n "$IS_SHARUN" ]]
                                            then
                                                try_mkdir "$sharun_bin_dir_pth"
                                                [ "$hard_links" == 1 ] && \
                                                    ln_args='-f'||ln_args='-sf'
                                                (try_cd "$sharun_bin_dir_pth"
                                                [ "$VERBOSE" != 1 ]||echo -n "ln: "
                                                ln $varg $ln_args ../sharun "$binary_name"||exit 1
                                                if [ -n "$binary_real_name" ]
                                                    then
                                                        [ "$VERBOSE" != 1 ]||echo -n "ln: "
                                                        ln $varg $ln_args ../sharun "$binary_real_name"||exit 1
                                                fi)||exit 1
                                        fi
                                fi
                                for lib_src_pth in $LIBS
                                    do
                                        if [[ "${LIBRARIES["$lib_src_pth"]}" != 1 ]]
                                            then
                                                unset lib_src_real_pth lib_src_real_name
                                                if [ -L "$lib_src_pth" ]
                                                    then
                                                        lib_src_real_pth="$(readlink -f "$lib_src_pth")"
                                                        lib_src_real_name="$(basename "$lib_src_real_pth")"
                                                        lib_src_dirname_pth="$(readlink -f "$(dirname "$lib_src_real_pth")")"
                                                        FILE_INFO="$(file "$lib_src_real_pth" 2>/dev/null)"
                                                    else
                                                        lib_src_dirname_pth="$(readlink -f "$(dirname "$lib_src_pth")")"
                                                        FILE_INFO="$(file "$lib_src_pth" 2>/dev/null)"
                                                fi
                                                if [[ "$FILE_INFO" =~ 'shared object' ]]
                                                    then
                                                        lib_src_name="$(basename "$lib_src_pth")"
                                                        grep -qE '/lib32|/i386-linux-gnu|/arm-linux-gnu'<<<"$lib_src_dirname_pth" && \
                                                            lib_dir="lib32"||lib_dir="lib"
                                                        lib_dst_dir_pth="${dst_dir_pth}/${lib_dir}$(sed \
                                                            "s|$dst_dir||;s|/shared||;s|^/usr||;s|^/opt||;s|^/lib64||;s|^/lib32||;s|^/lib||;s|^/.*-linux-gnu||"<<<"$lib_src_dirname_pth")"
                                                        [ -n "$lib_src_real_name" ] && \
                                                            lib_dst_pth="$lib_dst_dir_pth/$lib_src_real_name"||\
                                                            lib_dst_pth="$lib_dst_dir_pth/$lib_src_name"
                                                        if [[ ! -d "${dst_dir_pth}/${lib_dir}" && -d "${dst_dir}/${lib_dir}" \
                                                                && ! -L "${dst_dir_pth}/${lib_dir}" ]]
                                                            then
                                                                (try_mkdir "$dst_dir_pth"
                                                                try_cd "$dst_dir_pth"
                                                                try_ln ../$lib_dir $lib_dir)||exit 1
                                                        fi
                                                        try_mkdir "$lib_dst_dir_pth"
                                                        if [[ -d "$bin_dir_pth/_internal" && ! -L "$bin_dir_pth/_internal" ]]
                                                            then
                                                                try_cp -nT "$bin_dir_pth/_internal" "$(readlink -f "${dst_dir_pth}/${lib_dir}")"
                                                                rm -rf "$bin_dir_pth/_internal"
                                                                (try_cd "$bin_dir_pth"
                                                                try_ln ../${lib_dir} _internal)||exit 1
                                                        fi
                                                        try_cp_exe "$lib_src_pth" "$lib_dst_pth"
                                                        if [[ -n "$lib_src_real_name" && "$lib_src_name" != "$lib_src_real_name" ]]
                                                            then
                                                                (try_cd "$lib_dst_dir_pth"
                                                                try_ln "$lib_src_real_name" "$lib_src_name")||exit 1
                                                        fi
                                                        if [[ "${LIBRARIES["$lib_dst_pth"]}" != 1 ]]
                                                            then
                                                                if ! is_so && [[ ! -d "${dst_dir}/${lib_dir}" && \
                                                                    ! -L "${dst_dir}/${lib_dir}" ]]
                                                                    then
                                                                        (try_cd "$dst_dir"
                                                                        try_ln shared/$lib_dir $lib_dir)||exit 1
                                                                fi
                                                                repath_needed_libs "$lib_dst_pth"
                                                                try_strip "$lib_dst_pth"
                                                                try_remove_fullrpath "$lib_dst_pth"
                                                                if [ "$WITH_HOOKS" == 1 ]
                                                                    then
                                                                        if [ ! -f "$dst_dir/bin/xdg-open" ]
                                                                            then
                                                                                hook_msg "adding xdg-open wrapper..."
                                                                                try_mkdir "$dst_dir/bin"
                                                                                echo "$XDG_OPEN_WRAPPER" > "$dst_dir/bin/xdg-open"
                                                                                chmod $varg +x "$dst_dir/bin/xdg-open"
                                                                        fi
                                                                        case "$lib_dst_pth" in
                                                                            */gio/modules/*.so)
                                                                                sys_giom_cache="${lib_src_pth/modules\/*\.so/modules\/giomodule.cache}"
                                                                                dst_giom_dir="$(dirname "$lib_dst_pth")"
                                                                                dst_giom_cache="$dst_giom_dir/giomodule.cache"
                                                                                if [[ -f "$sys_giom_cache" &&  ! -f "$dst_giom_cache" ]]
                                                                                    then
                                                                                        hook_msg "copy giomodule.cache..."
                                                                                        try_mkdir "$dst_giom_dir"
                                                                                        try_cp "$sys_giom_cache" "$dst_giom_cache"
                                                                                fi ;;
                                                                            */libgio-*.so*)
                                                                                if [ ! -f "$dst_dir/bin/gio-launch-desktop" ]
                                                                                    then
                                                                                    hook_msg "make gio-launch-desktop wrapper..."
                                                                                    try_ln 'xdg-open' "$dst_dir/bin/gio-launch-desktop"
                                                                                fi ;;
                                                                            */libglib-*.so*)
                                                                                glib="$(grep -o 'glib-.*\.so'<<<"$lib_src_name"|sed "s|\.so$||")"
                                                                                sys_glib_schemas="/usr/share/$glib/schemas"
                                                                                dst_glib_schemas="$dst_dir/share/$glib/schemas"
                                                                                if [[ -d "$sys_glib_schemas" && ! -d "$dst_glib_schemas" ]]
                                                                                    then
                                                                                        hook_msg "copy glib schemas..."
                                                                                        try_mkdir "$dst_glib_schemas"
                                                                                        try_cp -T "$sys_glib_schemas" "$dst_glib_schemas"
                                                                                fi ;;
                                                                            */gdk-pixbuf-*/*/loaders/*.so)
                                                                                sys_pixbufl_cache="${lib_src_pth/loaders\/*\.so/loaders.cache}"
                                                                                dst_pixbufl_dir="$(dirname "$lib_dst_pth")"
                                                                                dst_pixbufl_cache="${dst_pixbufl_dir}.cache"
                                                                                if [[ -f "$sys_pixbufl_cache" && ! -f "$dst_pixbufl_cache" ]]
                                                                                    then
                                                                                        hook_msg "copy gdk pixbuf loaders.cache..."
                                                                                        try_mkdir "$dst_pixbufl_dir"
                                                                                        try_cp "$sys_pixbufl_cache" "$dst_pixbufl_cache"
                                                                                        sed -i 's|/usr/lib/.*/loaders/||g' "$dst_pixbufl_cache"
                                                                                fi ;;
                                                                            */gtk-*/*/immodules/*.so)
                                                                                sys_gtkimm_cache="${lib_src_pth/immodules\/*\.so/immodules.cache}"
                                                                                dst_gtkimm_dir="$(dirname "$lib_dst_pth")"
                                                                                dst_gtkimm_cache="${dst_gtkimm_dir}.cache"
                                                                                if [[ -f "$sys_gtkimm_cache" && ! -f "$dst_gtkimm_cache" ]]
                                                                                    then
                                                                                        hook_msg "copy gtk immodules.cache..."
                                                                                        try_mkdir "$dst_gtkimm_dir"
                                                                                        try_cp "$sys_gtkimm_cache" "$dst_gtkimm_cache"
                                                                                        sed -i 's|/usr/lib/.*/immodules/||g' "$dst_gtkimm_cache"
                                                                                fi ;;
                                                                            */libfontconfig.so*)
                                                                                sys_fcfg='/etc/fonts/fonts.conf'
                                                                                dst_fcfg="$dst_dir/etc/fonts/fonts.conf"
                                                                                if [[ -f "$sys_fcfg" && ! -f "$dst_fcfg" ]]
                                                                                    then
                                                                                        hook_msg "copy fonts.conf..."
                                                                                        try_mkdir "$dst_dir/etc/fonts"
                                                                                        try_cp "$sys_fcfg" "$dst_fcfg"
                                                                                fi ;;
                                                                            */libfolks*.so*)
                                                                                sys_folks_dir="$(dirname "$lib_src_pth")/folks"
                                                                                dst_folks_dir="$(dirname "$lib_dst_pth")/folks"
                                                                                if [[ -d "$sys_folks_dir" && ! -d "$dst_folks_dir" ]]
                                                                                    then
                                                                                        hook_msg "copy folks lib dir..."
                                                                                        try_cp -T "$sys_folks_dir" "$dst_folks_dir"
                                                                                fi ;;
                                                                            */libthai*.so*)
                                                                                sys_libthai_dir='/usr/share/libthai'
                                                                                dst_libthai_dir="$dst_dir/share/libthai"
                                                                                if [[ -d "$sys_libthai_dir" && ! -d "$dst_libthai_dir" ]]
                                                                                    then
                                                                                        hook_msg "copy libthai..."
                                                                                        try_mkdir "$dst_libthai_dir"
                                                                                        try_cp -T "$sys_libthai_dir" "$dst_libthai_dir"
                                                                                fi ;;
                                                                            */libxkbcommon*.so*)
                                                                                sys_xcb_dir='/usr/share/X11/xkb'
                                                                                dst_xcb_dir="$dst_dir/share/X11/xkb"
                                                                                if [[ -d "$sys_xcb_dir" && ! -d "$dst_xcb_dir" ]]
                                                                                    then
                                                                                        hook_msg "copy X11 xkb..."
                                                                                        try_mkdir "$dst_xcb_dir"
                                                                                        try_cp -T "$sys_xcb_dir" "$dst_xcb_dir"
                                                                                fi ;;
                                                                            */libgbm.so*)
                                                                                sys_gbm_dir="$(dirname "$lib_src_pth")/gbm"
                                                                                dst_gbm_dir="$(dirname "$lib_dst_pth")/gbm"
                                                                                if [[ -d "$sys_gbm_dir" && ! -d "$dst_gbm_dir" ]]
                                                                                    then
                                                                                        hook_msg "copy gbm lib dir..."
                                                                                        try_cp -T "$sys_gbm_dir" "$dst_gbm_dir"
                                                                                fi ;;
                                                                            */libEGL_mesa.so*)
                                                                                sys_glvnd_dir='/usr/share/glvnd/egl_vendor.d'
                                                                                dst_glvnd_dir="$dst_dir/share/glvnd/egl_vendor.d"
                                                                                if [[ -d "$sys_glvnd_dir" && ! -d "$dst_glvnd_dir" ]]
                                                                                    then
                                                                                        hook_msg "copy EGL vendors..."
                                                                                        try_mkdir "$dst_glvnd_dir"
                                                                                        try_cp -T "$sys_glvnd_dir" "$dst_glvnd_dir"
                                                                                fi ;;
                                                                            */libvulkan.so*)
                                                                                sys_vk_icd_dir='/usr/share/vulkan/icd.d'
                                                                                dst_vk_icd_dir="$dst_dir/share/vulkan/icd.d"
                                                                                if [[ -d "$sys_vk_icd_dir" && ! -d "$dst_vk_icd_dir" ]]
                                                                                    then
                                                                                        hook_msg "copy Vulkan ICD..."
                                                                                        try_mkdir "$dst_vk_icd_dir"
                                                                                        try_cp -T "$sys_vk_icd_dir" "$dst_vk_icd_dir"
                                                                                        sed -i 's|/usr/lib||g;s|/.*-linux-gnu||g;s|"/|"|g' "$dst_vk_icd_dir"/*
                                                                                fi ;;
                                                                            */libwebkit*gtk-*.so*)
                                                                                webkit="$(grep -Eo 'webkit(2)?gtk-[0-9]*\.[0-9]*'<<<"$lib_src_name")"
                                                                                dst_webkit_lib_dir="$(dirname "$lib_dst_pth")/$webkit"
                                                                                hook_msg "hack webkitgtk to be portable..."
                                                                                sed -i 's|/usr|././|g' "$lib_dst_pth"
                                                                                for sys_webkit_lib_dir in "${lib_src_dirname_pth}/$webkit" \
                                                                                    "${lib_src_dirname_pth}exec/$webkit"
                                                                                    do
                                                                                        if [ -d "$sys_webkit_lib_dir" ] && \
                                                                                            [[ ! -d "$dst_webkit_lib_dir/injected-bundle" || \
                                                                                                ! -f "$dst_webkit_lib_dir/WebKitWebProcess" ]]
                                                                                            then try_cp -T "$sys_webkit_lib_dir" "$dst_webkit_lib_dir"
                                                                                        fi
                                                                                done
                                                                                for bin_to_wrap in "$dst_webkit_lib_dir"/*
                                                                                    do
                                                                                        if [[ -f "$bin_to_wrap" && ! -L "$bin_to_wrap" ]] && \
                                                                                            ! grep -q '.*\.so.*'<<<"$bin_to_wrap"
                                                                                            then
                                                                                                try_mkdir "$bin_dir_pth"
                                                                                                try_mv "$bin_to_wrap" "$bin_dir_pth"
                                                                                                ln $varg -sr "$dst_dir/sharun" "$dst_webkit_lib_dir/$(basename "$bin_to_wrap")"
                                                                                        fi
                                                                                done
                                                                                if [ "$(basename "$lib_src_dirname_pth")" != "$lib_dir" ]
                                                                                    then try_ln . "$dst_dir_pth/$lib_dir/$(basename "$lib_src_dirname_pth")"
                                                                                fi
                                                                                if ! grep -q 'SHARUN_WORKING_DIR=${SHARUN_DIR}' "$dst_dir/.env" 2>/dev/null
                                                                                    then echo 'SHARUN_WORKING_DIR=${SHARUN_DIR}' >> "$dst_dir/.env"
                                                                                fi ;;
                                                                            */libwebkit*gtkinjectedbundle.so)
                                                                                sed -i 's|/usr|././|g' "$lib_dst_pth" ;;
                                                                            */libncursesw.so*|*/libcursesw.so*|*/libcurses.so*)
                                                                                dst_terminfo_dir="$dst_dir/share/terminfo"
                                                                                for terminfo_dir in '/etc' '/usr/share'
                                                                                    do
                                                                                        sys_terminfo_dir="$terminfo_dir/terminfo"
                                                                                        if [[ -d "$sys_terminfo_dir" && ! -d "$dst_terminfo_dir" ]]
                                                                                            then
                                                                                                hook_msg "copy terminfo..."
                                                                                                try_mkdir "$dst_terminfo_dir"
                                                                                                try_cp -T "$sys_terminfo_dir" "$dst_terminfo_dir"
                                                                                                break
                                                                                        fi
                                                                                done
                                                                                sys_tabset_dir='/usr/share/tabset'
                                                                                dst_tabset_dir="$dst_dir/share/tabset"
                                                                                if [[ -d "$sys_tabset_dir" && ! -d "$dst_tabset_dir" ]]
                                                                                    then
                                                                                        hook_msg "copy tabset..."
                                                                                        try_mkdir "$dst_tabset_dir"
                                                                                        try_cp -T "$sys_tabset_dir" "$dst_tabset_dir"
                                                                                fi ;;
                                                                            */qt*/plugins/*.so)
                                                                                qt_conf="$sharun_bin_dir_pth/qt.conf"
                                                                                if [ ! -f "$qt_conf" ]
                                                                                    then
                                                                                        hook_msg "create qt.conf..."
                                                                                        qt="$(grep -Eo 'qt([0-9])?'<<<"$lib_src_pth")"
                                                                                        echo -e \
                                                                                        "[Paths]\nPrefix = ../shared/${lib_dir}/${qt}\nPlugins = plugins\nImports = qml\nQml2Imports = qml" \
                                                                                        > "$qt_conf"
                                                                                fi ;;
                                                                            */libmagic.so*)
                                                                                dst_magic_file="$dst_dir/share/file/misc/magic.mgc"
                                                                                for magic_file_dir in 'file' 'file/misc' 'misc'
                                                                                    do
                                                                                        sys_magic_file="$(readlink -f "/usr/share/$magic_file_dir/magic.mgc")"
                                                                                        if [[ -f "$sys_magic_file" && ! -f "$dst_magic_file" ]]
                                                                                            then
                                                                                                hook_msg "copy magic file..."
                                                                                                try_mkdir "$(dirname "$dst_magic_file")"
                                                                                                try_cp "$sys_magic_file" "$dst_magic_file"
                                                                                                break
                                                                                        fi
                                                                                done ;;
                                                                            */libgirepository-*.so*)
                                                                                girepository="$(grep -o 'girepository-.*\.so'<<<"$lib_src_name"|sed "s|\.so$||")"
                                                                                sys_girepository="${lib_src_dirname_pth}/$girepository"
                                                                                dst_girepository="$lib_dst_dir_pth/$girepository"
                                                                                if [[ -d "$sys_girepository" && ! -d "$dst_girepository" ]]
                                                                                    then
                                                                                        hook_msg "copy girepository..."
                                                                                        try_mkdir "$dst_girepository"
                                                                                        try_cp -T "$sys_girepository" "$dst_girepository"
                                                                                        find "$lib_src_dirname_pth" -type f -wholename "*/$girepository/*.typelib" 2>/dev/null|\
                                                                                        grep -v "^$sys_girepository"|while IFS=$'\n' read -r sys_typelib
                                                                                            do
                                                                                                dst_typelib="$dst_girepository/$(basename "$sys_typelib")"
                                                                                                if [[ -f "$sys_typelib" && ! -f "$dst_typelib" ]]
                                                                                                    then try_cp "$sys_typelib" "$dst_typelib"
                                                                                                fi
                                                                                        done
                                                                                fi ;;
                                                                            */gconv/*.so)
                                                                                sys_gconv_modules_file="$(dirname "$lib_src_pth")/gconv-modules"
                                                                                dst_gconv_modules_file="$(dirname "$lib_dst_pth")/gconv-modules"
                                                                                if [[ -f "$sys_gconv_modules_file" &&  ! -f "$dst_gconv_modules_file" ]]
                                                                                    then
                                                                                        hook_msg "copy gconv-modules file..."
                                                                                        try_cp "$sys_gconv_modules_file" "$dst_gconv_modules_file"
                                                                                fi ;;
                                                                        esac
                                                                fi
                                                                LIBRARIES["$lib_dst_pth"]=1
                                                        fi
                                                    else
                                                        skip_msg "$BLUE[$lib_src_pth]$YELLOW not shared object!"
                                                fi
                                                LIBRARIES["$lib_src_pth"]=1
                                        fi
                                done
                                if [ -n "$INTERPRETER" ]
                                    then
                                        interpreter_pth="${dst_dir}/shared/$lib_dir/$INTERPRETER"
                                        if [[ "$patch_interpreter" == 1 && "${LIBRARIES["${INTERPRETER}_patched"]}" != 1 ]]
                                            then
                                                if [ "$LIBS_ONLY" != 1 ] && ! is_so
                                                    then
                                                        (try_cd "$bin_dir_pth"
                                                        if [ -f "../$lib_dir/$INTERPRETER" ]
                                                            then
                                                                if [ -n "$IS_PYINSTELF" ]
                                                                    then new_interp="$(printf "%${MAX_INTERP_LEN}s"|tr ' ' "i")"
                                                                    else new_interp="../$lib_dir/$INTERPRETER"
                                                                fi
                                                                info_msg "$YELLOW[ SET INTERPRETER ]: $BLUE[$bin_dir_pth/$binary_name]"
                                                                patchelf $pvarg --set-interpreter "$new_interp" "$binary_name"||exit 1
                                                        fi)||exit 1
                                                fi
                                                info_msg "$YELLOW[ PATCH INTERPRETER ]: $BLUE[$interpreter_pth]"
                                                sed -i 's|/usr|/XXX|g;s|/lib|/XXX|g;s|/etc|/XXX|g' "$interpreter_pth"||exit 1
                                                LIBRARIES["${INTERPRETER}_patched"]=1
                                        elif [[ "${LIBRARIES["${INTERPRETER}_sedpreload"]}" != 1 ]]
                                            then
                                                info_msg "$YELLOW[ REMOVE INTERPRETER PRELOAD ]: $BLUE[$interpreter_pth]"
                                                sed -i 's|/etc/ld.so.preload|/XXX/ld.so.preload|g' "$interpreter_pth"||exit 1
                                                LIBRARIES["${INTERPRETER}_sedpreload"]=1
                                        fi
                                fi
                                info_msg "[ DONE ]"
                                binary_number=$(( $binary_number + 1 ))
                            else
                                if [ -e "$binary_src_pth" ]
                                    then skip_msg "$BLUE[$binary]$YELLOW not executable or shared object!"
                                    else
                                        if [ "$STRACE_EXE" == "$binary" ]
                                            then
                                                error_msg "$BLUE[$binary]$RED executable for strace not found!"
                                                exit 1
                                            else skip_msg "$BLUE[$binary]$YELLOW not found!"
                                        fi
                                fi
                        fi
                        BINARIES["$binary"]=1
                fi
        done
        unset BINARIES LIBRARIES
    else
        DST_DIRS["$WRAPPE_DIR/shared"]=
fi

if [ "$WITH_WRAPPE" == 1 ]
    then
        TMP_WRAPPE="${TMPDIR}/wrappe-${ARCH}"
        WRAPPE="${WRAPPE:="$(readlink -f "$(which_exe wrappe)")"}"
        WRAPPE="${WRAPPE:="$TMP_WRAPPE"}"
        if [ ! -x "$WRAPPE" ]
            then
                if [[ "${WRAPPE,,}" =~ ^http ]]
                    then
                        WRAPPE_URL="$WRAPPE"
                        WRAPPE="$TMP_WRAPPE"
                fi
                WRAPPE_URL="${WRAPPE_URL:=$GIT_WRAPPE_RELEASE}"
                info_msg "Downloading wrappe -> '$WRAPPE'..."
                info_msg "$WRAPPE_URL"
                if try_dl "$WRAPPE_URL" "$WRAPPE"
                    then chmod $varg +x "$WRAPPE"
                    else
                        error_msg "Failed to download wrappe!"
                        exit 1
                fi
        fi
        if [ ! -x "$WRAPPE" ]
            then
                error_msg "wrappe not found!"
                exit 1
        fi
fi

for dst_dir in "${!DST_DIRS[@]}"
    do
        unset binpatched
        if [[ "$GEN_LIB_PATH" == 1 || "$PATCH_RPATH" == 1 || -n "$(echo "${!PATCH_RPATH_@}")" ]]
            then
                for lib_dir in lib lib32
                    do
                        lib_dir="${dst_dir}/${lib_dir}"
                        if [ -d "$lib_dir" ]
                            then
                                LIBS="$(find_so "$lib_dir/")"
                                if [ -n "$LIBS" ]
                                    then
                                        if [ "$GEN_LIB_PATH" == 1 ]
                                            then
                                                info_msg "$YELLOW[ GEN LIB PATH ]: $BLUE[${lib_dir}/lib.path]"
                                                sed "s|${lib_dir}|+|g"<<<"$(xargs -I {} dirname "{}"<<<"$LIBS"|\
                                                    sort -u)"|grep -v '+/lib-dynload' > "${lib_dir}/lib.path"||exit 1
                                        fi
                                        if [[ "$PATCH_RPATH" == 1 || "$(printenv PATCH_RPATH_$(get_md5sum "$dst_dir"))" == 1 ]]
                                            then
                                                patch_files="$LIBS"
                                                if [ "$binpatched" != 1 ]
                                                    then
                                                        binpatched=1
                                                        patch_files+="\n$(find_exe "$(readlink -f "$lib_dir"/../bin)" -not -type l)"
                                                fi
                                                echo -e "$patch_files"|grep -v 'lib-dynload'|sort -u|while IFS=$'\n' read -r file
                                                    do
                                                        abs_path=$(readlink -f "$file")
                                                        file_dirname=$(dirname "$abs_path")
                                                        rpath=''
                                                        for subdir in $(find "$lib_dir" -type d|grep -v 'lib-dynload')
                                                            do
                                                                relative_path=$(get_relative_path "$file_dirname" "$subdir")
                                                                if [ -n "$relative_path" ] && \
                                                                    [ "$relative_path" != "." ]
                                                                    then
                                                                        [ -n "$rpath" ] && \
                                                                            rpath="$rpath:\$ORIGIN/$relative_path"||\
                                                                            rpath="\$ORIGIN/$relative_path"
                                                                fi
                                                        done
                                                        if [[ ! "$abs_path" =~ /ld-(linux|musl).*\.so && \
                                                            ! "$abs_path" =~ ld-[0-9]\.[0-9]+\.so ]]
                                                            then try_set_rpath "$abs_path" "$rpath"
                                                        fi
                                                done
                                        fi
                                fi
                        fi
                done
        fi
        src_dir="${dst_dir%/shared}"
        if [[ "$WITH_WRAPPE" == 1 && -x "$src_dir/sharun" ]]
            then
                src_bins=($(find_exe "$src_dir/bin/" -printf "%f\n"))
                if [ -n "$src_bins" ]
                    then
                        if [ "${#src_bins[@]}" == 1 ]
                            then wrappe_exec="$src_dir/bin/$src_bins"
                            else
                                if [[ -n "$WRAPPE_EXEC" && "$WRAPPE_EXEC" != 'sharun' ]]
                                    then wrappe_exec="$src_dir/bin/$WRAPPE_EXEC"
                                    else wrappe_exec="$src_dir/sharun"
                                fi
                        fi
                        wexec_name="${wrappe_exec##*/}"
                        IS_SCRIPT="$(file "$(readlink -f "$wrappe_exec")"|grep -o script)"
                        if [ -n "$IS_SCRIPT" ]
                            then
                                wrappe_exec="$src_dir/sharun"
                                [[ -n "$WRAPPE_EXEC" && "$WRAPPE_EXEC" != 'sharun' ]] && \
                                    wexec_name="$WRAPPE_EXEC"
                        fi
                        if [[ -L "$wrappe_exec" && "$(readlink -f "$wrappe_exec")" =~ sharun$ ]]||\
                            [ -n "$IS_SCRIPT" ]
                            then wrappe_args="$wexec_name $WRAPPE_ARGS"
                            else wrappe_args="$WRAPPE_ARGS"
                        fi
                        [[ ! "$wout_dir" =~ ^"$DST_DIR" ]] && \
                            wout_dir="$DST_DIR"||\
                            wout_dir="$(dirname "$src_dir")"
                        try_mkdir "$wout_dir"
                        info_msg "$YELLOW[ PACKING WITH WRAPPE ]: $BLUE[$src_dir]"
                        "$WRAPPE" --unpack-target temp --unpack-directory .wrappe \
                            $([ "$WRAPPE_CLEANUP" == 0 ]||echo '--cleanup') --verification none \
                            --show-information none --compression "$WRAPPE_CLVL" "$src_dir" \
                            "$wrappe_exec" "$wout_dir/$wexec_name" -- $wrappe_args||exit 1
                        if [ ! -d "$WRAPPE_DIR" ]
                            then rm -rf "$src_dir"
                        fi
                fi
        fi
done
